QT GridLayout add Stacked QLabel - c++

I am creating an image gallery, i've implemented the reading in of Files and showing them in a resizable scroll-Area. We've decided to add meta-tags / Buttons and i am searching for a convenient way not to change too much but add this little features.
Any suggestion how i can achieve this? Can i add two Qlabels to each other? I tried to stuck two labels in a new layout and push this to the scrollWidgetLayout, but then i have only one Thumbnail.
//Create new ThumbNail-Object
thumbNail = new Thumbnail(ui->scrollArea);
scrollWidgetLayout->addWidget(thumbNail);
In the picture you can see what i have already and what i need (yellow).

You create a widget that acts like a container and put the labels inside it. Set a layout to this widget, I used QVBoxLayout. A better design would be to create a custom widget by subclassing QWidget, but I just used QFrame to make the example quick and simple.
centralWidget()->setLayout(new QVBoxLayout);
QScrollArea *area = new QScrollArea(this);
area->setWidgetResizable(true);
area->setWidget(new QWidget);
QGridLayout *grid = new QGridLayout;
area->widget()->setLayout(grid);
centralWidget()->layout()->addWidget(area);
for(int row = 0; row < 2; row++)
{
for(int column = 0; column < 5; column++)
{
QFrame *container = new QFrame; // this is your widget.. you can also subclass QWidget to make a custom widget.. might be better design
container->setStyleSheet("QFrame{border: 1px solid black;}"); // just to see the shapes better.. you don't need this
container->setLayout(new QVBoxLayout); // a layout for your widget.. again, if you subclass QWidget do this in its constructor
container->layout()->addWidget(new QLabel("TOP")); // the top label.. in your case where you show the icon
container->layout()->addWidget(new QLabel("BOTTOM")); // the bottom label.. in your case where you show the tag
grid->addWidget(container, row, column); // add the widget to the grid
}
}

Related

QTableView bigger than its container

I am working on Qt applicaction. There I have QMainWindow. Inside it I have added QTableView. When I run the application I see that I need to scroll to display the whole table and also blank space shows up below it.
I would like main window to resize horizontally in order to use space needed by the table. Also I would like it to resize vertically to not having space unused. How could I achieve that?
This is my code so far:
void MainWindow::initUi() {
setWindowTitle(tr("Main Window"));
QWidget* centralWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
QFormLayout *upperLayout = new QFormLayout;
// Default layout appearance of QMacStyle
upperLayout->setRowWrapPolicy(QFormLayout::DontWrapRows);
upperLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
upperLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop);
upperLayout->setLabelAlignment(Qt::AlignLeft);
QVBoxLayout *resultsLayout = new QVBoxLayout;
QTableView* table = new QTableView(centralWidget);
table->verticalHeader()->hide();
QStandardItemModel* model= new QStandardItemModel(4, 4);
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 4; ++column) {
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model->setItem(row, column, item);
}
}
table->setModel(model);
QLabel* upperLabel = new QLabel(tr("Label:"), centralWidget);
upperLabel->setAlignment(Qt::AlignLeft);
resultLabel = new QLabel(tr("Result goes here"), centralWidget);
mainLayout->addLayout(resultsLayout);
resultsLayout->addLayout(upperLayout);
resultsLayout->addWidget(table);
upperLayout->addRow(upperLabel, resultLabel);
centralWidget->setLayout(mainLayout);
setCentralWidget(centralWidget);
this->adjustSize();
}
Set the sizeAdjustPolicy of the table to AdjustToContents view, then set the size policy to Fixed in both horizontal and vertical directions.
AdjustToContents might incur a slight performance penalty for dynamic contents in the view, since every data change may change the layout.
The Qt Designer is a really nifty tool to figure layout issues out quickly; the {table,list,tree} widgets behave exactly the same as the views do (because they're the same) and the widgets can be quickly filled with dummy data in Qt Designer.

How can I stretch a QLayout or QFrame, nested within a bigger layout?

I currently have this code set up to create a sidebar and I'm not entirely sure how to stretch it so that the left, top, and bottom sides touch the edge of the window.
QFrame *sidebar = new QFrame;
QLabel *sideItemA = new QLabel("Item A");
QLabel *sideItemB = new QLabel("Item B");
QVBoxLayout *sidebarLayout = new QVBoxLayout;
sidebarLayout->addWidget(sideItemA);
sidebarLayout->addWidget(sideItemB);
sidebarLayout->addStretch();
sidebar->setLayout(sidebarLayout);
sidebar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
sidebar->setStyleSheet("background-color:#FFFFFF");
sidebar->setMinimumWidth(150);
mainLayout->addWidget(sidebar);
Here is a screenshot of what the above code looks like:
I've tried doing this using nested layouts too and I get the same result. Any pointers? Is this even the best way to do it?

QT Clickable widget (possibly button) inside QTreeWidget?

I have a table that is basically a QTreeWidget and I want to put a clickable widget, possibly a button inside it. Each row is a QTreeWidgetItem, but I don't see how I can add a button with QTreeWidgetItem::setData
Here is a modification to the example provided in Qt Documentation for QTreeWidget adding a QPushButton to the second item
ui->treeWidget->setColumnCount(1);
QList<QTreeWidgetItem *> items;
for (int i = 0; i < 10; ++i)
items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item: %1").arg(i))));
ui->treeWidget->insertTopLevelItems(0, items);
ui->treeWidget->setItemWidget(items.value(1),0,new QPushButton("Click Me")); // Solution for your problem
For two push buttons side by side within an item,you can take this approach
QWidget *dualPushButtons = new QWidget();
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(new QPushButton("Button1"));
hLayout->addWidget(new QPushButton("Button2"));
dualPushButtons->setLayout(hLayout);
ui->treeWidget->setItemWidget(items.value(1),0,dualPushButtons);
You can adapt this by adding properties to the buttons etc.

Hiding a vertical layout programmatically?

I wanted to know if its possible to hide a vertical layout. I currently have a a horizontal layout with two vertical layouts.I wanted to hide one of the vertical layouts(with all its content) on button click. Any suggestions on how I could do that.
As #jmk said, you need to use a QWidget. I'll just add that it's very easy to turn an existing horizontal or vertical layout into a widget from Qt Designer by right-clicking on it and selecting Morph Into->QWidget:
The layout is entirely preserved, but now you can show/hide the layout box because it's an ordinary widget with that layout.
Instead of inserting vertical layouts directly into your top-level horizontal layout, use container widgets to easily control visibility:
// Create your left and right widgets
QWidget* leftWidget = new QWidget();
QVBoxLayout* leftLayout = new QVBoxLayout(leftWidget);
QWidget* rightWidget = new QWidget();
QVBoxLayout* rightLayout = new QVBoxLayout(rightWidget);
// Populate your vertical layouts here ...
QHBoxLayout* horizontalLayout = new QHBoxLayout(parentWidget);
horizontalLayout->addWidget(leftWidget);
horizontalLayout->addWidget(rightWidget);
Then, you can simply hide or show leftWidget or rightWidget to effectively control the visibility of everything in the vertical layouts that you have, without having to hide/show each individual widget.
My suggestion:
// l is the layout pointer
for (int i = 0; i != l->count(); ++i) {
QWidget* w = qobject_cast<QWidget*>(l->itemAt(i));
if (w != 0) {
w->setVisible(false); // hides the widget
}
else {
// do some recursive things with the layout
}
}
(Hope it works ;))
The widget is basically invisible.

QScrollArea with multiple QWidgets only shows empty box

I am trying to create a widget that would display some information. Each information would be a QWidget that contains multiple QLabel with text (the information). My idea is to put multiple (array of these) into a QScrollArea so that the user can view them scrolling up and down. The following code:
InfoWidget::InfoWidget(QWidget* parent) : QWidget(parent){
widgets = new QVector<MarkerInfoWidget*>();
csv_data = 0;
csv_velocity = 0;
labels = 0;
infoWidgetLayout = new QVBoxLayout(this);
setLayout(infoWidgetLayout);
scrollArea = new QScrollArea(this);
scrollWidgetLayout = new QVBoxLayout(scrollArea);
scrollArea->setLayout(scrollWidgetLayout);
infoWidgetLayout->addWidget(scrollArea);
//Test
QString name = "TEST";
for(int i=0; i<10; i++){
MarkerInfoWidget* markerWidget = new MarkerInfoWidget(name, scrollArea);
scrollWidgetLayout->addWidget(markerWidget);
widgets->append(markerWidget);
}
}
Both MarkerInfoWidget and InfoWidget extends QWidget. What I am getting is simply a box that has very small text:
If I drag it out and re-size it, it display correctly:
What I have noticed is that if I re-size it too small, it does not generate scrolls. What do I need to fix this?
I guess changing:
scrollArea->setLayout(scrollWidgetLayout);
to sth like:
QFrame* frame = new QFrame(scrollArea);
frame->setLayout(scrollWidgetLayout);
scrollArea->setWidget(frame);
As far as i know you have to put widget into QScrollableArea to make it really scrollable. Setting its layout is probably not the thing you want to do.