How do I align a widget? - c++

I cannot move the widget into the layout (QGridLayout). You need to move the "label shift" to the other widgets. That they were close. How can I do that?
QLabel * label_answer = new QLabel(this);
label_answer->setText("label_shift");
label_answer->setFont(params_font);
label_answer->setObjectName(QStringLiteral("label_answer_%1").arg(count-1));
lay->addWidget(main_label, i,0, Qt::AlignLeft);
lay->addWidget(box_input_value, i, 1, Qt::AlignLeft);
lay->addWidget(label_answer, i, 2, Qt::AlignLeft); // label_shift

You could add a extra column to the gridlayout, have the spinbox span 2 columns, which would mean the space needed in the label row is after the label, instead of before it

Related

Is it possible to add QTreeWidgetItem to QTableWidgetItem?

I have QTableWidget and I interested in how I can add QTreeWidget item into 3rd column in table? Is it possible?
I do it:
ui->tableWidget->insertRow(ui->tableWidget->rowCount());
ui->tableWidget->setCellWidget(ui->tableWidget->rowCount() - 1, 3, new QTreeWidget());
auto widget = dynamic_cast<QTreeWidget*>(ui->tableWidget->cellWidget(ui->tableWidget->rowCount() - 1, 3));
widget->setHeaderHidden(true);
QTreeWidgetItem * topLevel = new QTreeWidgetItem();
topLevel->setText(0, "This is top level");
widget->addTopLevelItem(topLevel);

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.

Align to the right text from QLabel and QLineEdit

I have a QLabel just below a QLineEdit with the same size and alignment properties:
QLineEdit *lineEdit = new QLineEdit("999");
lineEdit->setFixedWidth(100);
lineEdit->setAlignment(Qt::AlignRight);
//
QLabel *label = new QLabel("999");
label->setFixedWidth(100);
label->setAlignment(Qt::AlignRight);
//
QLayout *layout = new QVBoxLayout;
layout->addWidget(lineEdit);
layout->addWidget(label);
Here is how this is rendered:
How can I have the text of the bottom label exactly right-aligned to the text of the lineEdit?
Full award if you find a solution that works on all platforms, and that also works when the font sizes are different in the lineEdit and label.
Unfortunately it may not be possible, at least not out of the box, the right margin will not work, as it is always 0 even when the text is obviously offset to the left. The reason for this is this offset is not determined by the margins, but depends on the combination of platform GUI style and particular font's metrics that's being used, and its value is "conveniently" not available in the class public interface, there is no way to get to it.
You can get the font metrics easily, but you can't get the QStyleOptionFrame as the method required is protected, accessing it will require to subclass QLineEdit. However, if you are lucky, that value is very likely to be zero, so you could go with something as simple as this:
QVBoxLayout *layout = new QVBoxLayout;
QLineEdit *lineEdit = new QLineEdit("999");
lineEdit->setAlignment(Qt::AlignRight);
QLabel *label = new QLabel("999");
label->setAlignment(Qt::AlignRight);
int offsetValue = lineEdit->fontMetrics().averageCharWidth();
label->setIndent(offsetValue);
setLayout(layout);
layout->addWidget(lineEdit);
layout->addWidget(label);
If that doesn't work correctly for you, you will have no other choice but to subclass QLineEdit, carefully examine its paint event, determine where the offset is being calculated, and store that value in a public member so it can be accessed from the outside to be used to offset the label.
I personally got lucky with that code:
Would you be able to instead of using a QLineEdit and a QLabel to use two QLineEdits?
Consider the following:
QWidget* widget = new QWidget();
// Original line edit
QLineEdit *lineEdit1 = new QLineEdit("999");
lineEdit1->setFixedWidth(100);
lineEdit1->setAlignment(Qt::AlignRight);
lineEdit1->setStyleSheet("border-width: 2px;");
// A suggestion if you want a label
QLabel *label = new QLabel("999");
label->setFixedWidth(100);
label->setAlignment(Qt::AlignRight);
label->setStyleSheet("border: 2px solid rgba(255, 0, 0, 0%)");
// Alternatively if you can use another QLineEdit
QLineEdit *lineEdit2 = new QLineEdit("999");
lineEdit2->setFixedWidth(100);
lineEdit2->setAlignment(Qt::AlignRight);
lineEdit2->setReadOnly(true);
lineEdit2->setStyleSheet("background: rgba(0, 0, 0, 0%); "
"border-width: 2px; "
"border-style: solid; "
"border-color: rgba(0, 0, 0, 0%);");
// Bring it all together
QLayout *layout = new QVBoxLayout(widget);
layout->addWidget(lineEdit1);
layout->addWidget(label);
layout->addWidget(lineEdit2);
widget->show();
It forces all borders to be 2px, so on different platforms it should be the same. The second QLineEdit should not look different than the QLabel (The text color looks slightly darker than that of the label though, which might be a good thing since it matches the original edit)
The added benefit of using a QLineEdit instead of the QLabel is that the value is now selectable...
Disclaimer: I have only tested on Linux and I have not done a pixel level comparison.
Edit: I see the alignment fails with different font sizes.
simply, you can use the indent property of the QLabel.
https://doc.qt.io/qt-5/qlabel.html#indent-prop
The indent property can take +/- values. maybe the margin feature can do its job.

Qt C++ - QListWidget layout doesn't scale to fit the content

I have a QWidget rzadKontener that represents a row in a QListWidget.
QWidget* rzadKontener = new QWidget;
QHBoxLayout* rzadKontenerLayout = new QHBoxLayout();
rzadKontenerLayout->setAlignment(Qt::AlignLeft);
rzadKontenerLayout->setAlignment(Qt::AlignTop);
rzadKontener->setObjectName("rzadKontener_" + poziom);
rzadKontener->setFixedHeight(200);
rzadKontener->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
rzadKontener->setLayout(rzadKontenerLayout);
(....)
QListWidgetItem* newItemRzad = new QListWidgetItem;
newItemRzad->setSizeHint(QSize(listSize*225, 200));
QString poziomText = poziom;
newItemRzad->setText(poziomText);
newItemRzad->setTextColor(QColor(Qt::white));
ui->listWidgetZdjeciaModelu->addItem(newItemRzad);
ui->listWidgetZdjeciaModelu->setItemWidget(newItemRzad, rzadKontener);
It contains a number of items, that are QWidgets with pictures, buttons and text. It is then placed in a QListWidget as a row full of these items. When I add 5 items at once, while creating a new rzadKontener, scroll bars in the QListWidget will appear. But if I add 3 and then 2 items later on, they'll go out of bounds without a scrollbar. How can I force the layout to scale to the new rzadKontener's size?
I found an answer. Instead of modifying the QWidget inside the list, I should be modifying the QListWidgetItem it's inside of (the parent...).
QWidget* newPicture = new QWidget;
yadda yadda yadda (....)
int currentRowWidth = ui->listWidgetZdjeciaModelu->findChild<QWidget*>(objectName)->width(); //gets max width of rzadKontener, which fills the entirety of the row - it equals the QListWidgetItem's width
int newWidth = currentRowWidth + 225; //225 is a fixed width of newPicture
ui->listWidgetZdjeciaModelu->item(0)->setSizeHint(QSize(newWidth, 200));
ui->listWidgetZdjeciaModelu->findChild<QWidget*>(objectName)->layout()->addWidget(newPicture );
We can do ui->listWidgetZdjeciaModelu->item(0)->setSizeHint(QSize(newWidth, 200)); instead of a specific row (->item(row)), because the list is a rectangle. Doesn't matter which row we enlarge, the entire thing will stretch anyway.
But, if you want to get the row number, you can do it this way:
int row=0;
//we make a list. Each of my QListWidgetItem has a unique string poziom in it, so I can filter by that.
QList<QListWidgetItem *> items = ui->listWidgetZdjeciaModelu->findItems(poziom, Qt::MatchContains);
if (items.size() > 0) {
//we use the first (and only, in my case) item on this list to get row number
row = ui->listWidgetZdjeciaModelu->row(items[0]);
}
Weird thing is, I already tried this. Must've kept making a typo.

QT - Adding widgets to horizontal layout

i have an horizontal layout and i am adding widgets by using
ui->horizontalLayout->addWidget(label);
But adding strategy is not what i want. For example, when i add items, it first puts the start, then puts at the end and keep putting from end.
But, what i want is that, when i add widget to layout, it should be put next to the previous widget. like that ,
is it possible to do that?
Add a stretcher to it after you have added all the widgets.
ui->horizontalLayout->addStretch();
will do.
You can add a spacer item, either on the outside of your horizontal layout, or inside your horizontal layout. If you add the spacer item inside the horizontal layout, you have to make sure you add your label widgets before the spacer item. Use the insertWidget() function to add your labels in this case.
Or you can add the spaceritem to the end of your horizontal layout after you've added your label widgets.
Here is an example:
QHBoxLayout *hlayout = new QHBoxLayout;
ui->verticalLayout->addLayout(hlayout);
QSpacerItem *item = new QSpacerItem(1,1, QSizePolicy::Expanding, QSizePolicy::Fixed);
hlayout->addSpacerItem(item);
for(int i = 0; i < 10; i++)
{
QLabel *label = new QLabel("NOTE");
hlayout->insertWidget(i, label);
}
setAlignment(Qt::AlignLeft); should do the trick. Also you can use this with: setSpacing(0);setContentsMargins(0, 0, 0, 0); to remove extra space between widgets.