Conceptual Question; QLabel as Banner?
This is more of a conceptual question, so I don't have code to post yet. I am a little bit stuck on thinking of the right way to implement this idea, and I was wondering if anyone could offer an idea.
The Problem: I currently have a custom implementation of a linear layout, where widgets are being placed
from left to right horizontally. When row space runs out, they are moved down to the next row, like so:
1 2 3 4
5 6 7 8
9
The widgets that I am placing each belong to groups that can be arbitrarily long. I am currently trying to design a banner that would be place on top of these object, so if widgets 1,2,3 are in group A, and 4,5.6 are in group B there would be a banner over them like:
[ A ] [
1 2 3 4
B ]
5 6
I thought that QLabel would be the easiest way to do this, but if I run into the case where a group is split into the next row like above, I'm not sure how I can gracefully split the text inside of the label between rows :/. I was wondering if there was an easier way that I'm not thinking of or if I should just try to make this "split a QLabel's text into two different QLabels" idea work.
Cheers,
sp
Re: Conceptual Question; QLabel as Banner?
It's not really clear to me what you mean with a banner?
Do you want some column descriptions?
example:
Code:
[ItemBanner1Group1] [ItemBanner2Group1] [ItemBanner3Group1]
item 1 item 2 item 3
[ItemBanner3Group1]
item 4
[ItemBanner1Group2] [ItemBanner2Group2]
item 1 item 2
where everything between [ ] is a banner, and the item is underneath the banner
Re: Conceptual Question; QLabel as Banner?
Thanks for the interest. I hope this does a better job of explaining what I'm going for:
The banner acts as a label that is spread across a set of grouped items. So if items 1-3 are in group one, and items 4-6 are in group two, each
group has its own "banner" with text that would say something like "group 1". I was thinking of making a QLabel that would have the same width
as the sum of the 3 items and placing the label on top of all the grouped items, but I wasn't sure if this would be a good idea, since if a group is
split the label must carry on to a new row.
[Text describing group one] [Text de
[Item 1] [item 2] [item 3] ] [Item 4]
scribing group two]
[item 5] [item 6]
Re: Conceptual Question; QLabel as Banner?
If I understand correctly what You need is QGroupBox.
1 Attachment(s)
Re: Conceptual Question; QLabel as Banner?
I gave it a try, check out the code below.
It's absolutely not perfect. In fact, I think the most correct way to do this is to create a QLayout subclass.
Screenshot attached below
Edit:
It works by keeping a list of groups and items.
First clear the layout from any widget or layout item.
Then go through each group.
In each group, add all the items to the layout, keeping below the maximum amount of columns
Then, when every item of a group is added add labels, keeping an eye on the span of the items for this group in the rows.
It might not be exactly like you want, but I think you can take it from here :-)
Header
Code:
#ifndef SPECIALLAYOUT_H
#define SPECIALLAYOUT_H
#include <QGridLayout>
#include <QStringList>
#include <QString>
#include <QMultiMap>
#include <QWidget>
{
Q_OBJECT
public:
explicit SpecialLayout
(QWidget *parent
= 0);
void addGroup
(const QString &groupName
);
void addItemWidget
(const QString &inGroup
);
void setMaximumColumns(int columns);
signals:
public slots:
protected:
void rebuildLayout();
private:
QMultiMap<QString, QString> m_groupWidgetMap;
int m_maximumColumnCount;
};
#endif // SPECIALLAYOUT_H
Implementation
Code:
#include "speciallayout.h"
#include <QLabel>
#include <QSpacerItem>
#include <QSizePolicy>
SpecialLayout
::SpecialLayout(QWidget *parent
) :{
m_maximumColumnCount = 10;
}
void SpecialLayout
::addGroup(const QString &groupName
) {
if (m_groupNames.contains(groupName))
return;
m_groupNames.append(groupName);
}
void SpecialLayout
::addItemWidget(const QString &inGroup
) {
if (!m_groupNames.contains(inGroup))
return;
m_groupWidgetMap.insert(inGroup, "Item");
rebuildLayout();
}
{
return m_groupNames;
}
void SpecialLayout::setMaximumColumns(int columns)
{
m_maximumColumnCount = columns;
}
void SpecialLayout::rebuildLayout()
{
while ((item = takeAt(0))) {
if (item->widget())
delete item->widget();
delete item;
}
int currentColumn = 0;
int currentRow = 0;
int widgetColumn = 0;
int widgetRow = 0;
int columnCount = 0;
foreach
(QString group, m_groupNames
) {
if (!m_groupWidgetMap.values(group).isEmpty()) {
widgetColumn = currentColumn;
widgetRow = currentRow;
foreach
(QString string, m_groupWidgetMap.
values(group
)) { addWidget(itemWidget, widgetRow + 1, widgetColumn);
++widgetColumn;
if (widgetColumn > m_maximumColumnCount - 1) {
widgetColumn = 0;
widgetRow += 2;
}
}
columnCount = m_groupWidgetMap.values(group).count();
int columnSpan;
while (columnCount > 0) {
columnSpan = qMin(m_maximumColumnCount - currentColumn, columnCount);
addWidget(label, currentRow, currentColumn, 1, columnSpan);
columnCount -= columnSpan;
currentColumn += columnSpan;
if (currentColumn > m_maximumColumnCount - 1) {
currentColumn = 0;
currentRow += 2;
}
}
}
}
}
Re: Conceptual Question; QLabel as Banner?
Quote:
Originally Posted by
tbscope
I gave it a try, check out the code below.
It's absolutely not perfect. In fact, I think the most correct way to do this is to create a QLayout subclass.
Screenshot attached below
Edit:
It works by keeping a list of groups and items.
First clear the layout from any widget or layout item.
Then go through each group.
In each group, add all the items to the layout, keeping below the maximum amount of columns
Then, when every item of a group is added add labels, keeping an eye on the span of the items for this group in the rows.
It might not be exactly like you want, but I think you can take it from here :-)
Header
Code:
#ifndef SPECIALLAYOUT_H
#define SPECIALLAYOUT_H
#include <QGridLayout>
#include <QStringList>
#include <QString>
#include <QMultiMap>
#include <QWidget>
{
Q_OBJECT
public:
explicit SpecialLayout
(QWidget *parent
= 0);
void addGroup
(const QString &groupName
);
void addItemWidget
(const QString &inGroup
);
void setMaximumColumns(int columns);
signals:
public slots:
protected:
void rebuildLayout();
private:
QMultiMap<QString, QString> m_groupWidgetMap;
int m_maximumColumnCount;
};
#endif // SPECIALLAYOUT_H
Implementation
Code:
#include "speciallayout.h"
#include <QLabel>
#include <QSpacerItem>
#include <QSizePolicy>
SpecialLayout
::SpecialLayout(QWidget *parent
) :{
m_maximumColumnCount = 10;
}
void SpecialLayout
::addGroup(const QString &groupName
) {
if (m_groupNames.contains(groupName))
return;
m_groupNames.append(groupName);
}
void SpecialLayout
::addItemWidget(const QString &inGroup
) {
if (!m_groupNames.contains(inGroup))
return;
m_groupWidgetMap.insert(inGroup, "Item");
rebuildLayout();
}
{
return m_groupNames;
}
void SpecialLayout::setMaximumColumns(int columns)
{
m_maximumColumnCount = columns;
}
void SpecialLayout::rebuildLayout()
{
while ((item = takeAt(0))) {
if (item->widget())
delete item->widget();
delete item;
}
int currentColumn = 0;
int currentRow = 0;
int widgetColumn = 0;
int widgetRow = 0;
int columnCount = 0;
foreach
(QString group, m_groupNames
) {
if (!m_groupWidgetMap.values(group).isEmpty()) {
widgetColumn = currentColumn;
widgetRow = currentRow;
foreach
(QString string, m_groupWidgetMap.
values(group
)) { addWidget(itemWidget, widgetRow + 1, widgetColumn);
++widgetColumn;
if (widgetColumn > m_maximumColumnCount - 1) {
widgetColumn = 0;
widgetRow += 2;
}
}
columnCount = m_groupWidgetMap.values(group).count();
int columnSpan;
while (columnCount > 0) {
columnSpan = qMin(m_maximumColumnCount - currentColumn, columnCount);
addWidget(label, currentRow, currentColumn, 1, columnSpan);
columnCount -= columnSpan;
currentColumn += columnSpan;
if (currentColumn > m_maximumColumnCount - 1) {
currentColumn = 0;
currentRow += 2;
}
}
}
}
}
This is very close to what I was going for. Thank you very much for the help!
Cheers,
sp