I want to have a dynamic list of QProgessBars laid out vertically. But the thing is I want some of them to be moved horizontally. For example:
#################
###########
###########
######
When I move widgets in the layout like this:
sl->move(10, 0);
nothing happens.
I also tried using QGridLayout with spacers:
QGridLayout * lay = new QGridLayout();
lay->setAlignment(Qt::AlignLeft|Qt::AlignTop);
for (int i = 1; i < 15; ++i) {
QProgressBar * sl = new QProgressBar();
QSpacerItem * sp = new QSpacerItem(10, 10 + i);
lay->addWidget(sl, i, 0);
lay->addItem(sp, i, 0);
}
I there a way to do it programmatically?
Hi you need to use this QGridLayout::addWidget version. For instance, when you execute
grid->addWidget(w1, 0, 0, 1, 5);
grid->addWidget(w2, 1, 1, 2, 3);
grid->addWidget(w3, 3, 0, 1, 5);
your final gui will look something like this:
w1 w1 w1 w1 w1
w2 w2 w2
w2 w2 w2
w3 w3 w3 w3 w3
You can see the grid as a 2D-array. So w2 starts from grid[1][1] and spans over 2 rows and 3 columns. And since w2 spans over 2 rows, w3 should start at w1's row + 2 (i.e. 3).
Do layout nesting, like they would do in html. Vertical layout with four (or three, if first row got only progress bar) horizontal layouts in it
But using Grid as top layout would allow to add margins at sides.
Of course you can do that programmatically. I've shown how that may look in Designer, but what designer actually does is to generate plain linear code. You can do that in for cycle instead.
Generated code:
if (Dialog->objectName().isEmpty())
Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(504, 377);
gridLayoutWidget = new QWidget(Dialog);
gridLayoutWidget->setObjectName(QString::fromUtf8("gridLayoutWidget"));
gridLayoutWidget->setGeometry(QRect(9, 9, 481, 351));
gridLayout = new QGridLayout(gridLayoutWidget);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->setContentsMargins(0, 0, 0, 0);
horizontalLayout_3 = new QHBoxLayout();
horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_3->addItem(horizontalSpacer);
progressBar_2 = new QProgressBar(gridLayoutWidget);
progressBar_2->setObjectName(QString::fromUtf8("progressBar_2"));
progressBar_2->setValue(24);
horizontalLayout_3->addWidget(progressBar_2);
horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_3->addItem(horizontalSpacer_2);
gridLayout->addLayout(horizontalLayout_3, 1, 0, 1, 1);
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer_3);
progressBar_3 = new QProgressBar(gridLayoutWidget);
progressBar_3->setObjectName(QString::fromUtf8("progressBar_3"));
progressBar_3->setValue(24);
horizontalLayout_2->addWidget(progressBar_3);
gridLayout->addLayout(horizontalLayout_2, 2, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
progressBar_4 = new QProgressBar(gridLayoutWidget);
progressBar_4->setObjectName(QString::fromUtf8("progressBar_4"));
progressBar_4->setValue(24);
horizontalLayout->addWidget(progressBar_4);
horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_4);
gridLayout->addLayout(horizontalLayout, 3, 0, 1, 1);
horizontalLayout_4 = new QHBoxLayout();
horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
progressBar = new QProgressBar(gridLayoutWidget);
progressBar->setObjectName(QString::fromUtf8("progressBar"));
progressBar->setValue(24);
horizontalLayout_4->addWidget(progressBar);
gridLayout->addLayout(horizontalLayout_4, 0, 0, 1, 1);
Related
I am trying to align QLabels in a simple GridLayout but this doesn't work seems to be a bug in QT 5.9 ?
Here is my snippet, everything is in a QDialog:
MyDialogue::MyDialogue(QWidget *parent) : QDialog(parent) {
QLabel *labelA = new QLabel(); labelA->setFixedSize(100, 25);
QLabel *labelB = new QLabel(); labelB->setFixedSize(100, 25);
QLabel *labelC = new QLabel(); labelC->setFixedSize(100, 25);
QLabel *labelD = new QLabel(); labelD->setFixedSize(100, 25);
labelA->setStyleSheet("background-color:blue");
labelB->setStyleSheet("background-color:yellow");
labelC->setStyleSheet("background-color:purple");
labelD->setStyleSheet("background-color:green");
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(labelA, 1, 1);
layout->addWidget(labelB, 1, 2);
layout->addWidget(labelC, 2, 1, 2, 2);
layout->addWidget(labelD, 3, 1, 3, 2);
}
The result:
Ok I found the solution (my mistake) :
MyDialogue::MyDialogue(QWidget *parent) : QDialog(parent) {
QLabel *labelA = new QLabel();
QLabel *labelB = new QLabel();
QLabel *labelC = new QLabel();
QLabel *labelD = new QLabel();
labelA->setStyleSheet("background-color:blue");
labelB->setStyleSheet("background-color:yellow");
labelC->setStyleSheet("background-color:purple");
labelD->setStyleSheet("background-color:green");
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(labelA, 1, 1);
layout->addWidget(labelB, 1, 2);
layout->addWidget(labelC, 2, 1, 1, 2);
layout->addWidget(labelD, 3, 1, 1, 2);
}
I was incorrectly thinking that for expanding a row along 2 columns (the case of labelC and labelD) I had to write the corrdinates of the starting cell (2,1) the actual position and then the ending cell (2,2). I was misguided by a Java layout manager that worked exactly that way. Just for the record here you just have to indicate the total number of row span and column span which is 2 in my case.
I think the title speaks for itself: Given a QTableWidget with items added by the setItem member function, I want to know what the margin is for each item. In particular, I want the width of the left margin in these cells.
I have prepared a little example computing text margins (a space between item rectangle and text content rectangle) of an item users clicks on:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow mainWin;
QTableWidget* table = new QTableWidget(3, 3, &mainWin);
table->setItem(0, 0, new QTableWidgetItem("Item A"));
table->setItem(1, 0, new QTableWidgetItem("Item B"));
table->setItem(2, 0, new QTableWidgetItem("Item C"));
table->setItem(0, 1, new QTableWidgetItem("Item D"));
table->setItem(1, 1, new QTableWidgetItem("Item E"));
table->setItem(2, 1, new QTableWidgetItem("Item F"));
table->setItem(0, 2, new QTableWidgetItem("Item G"));
table->setItem(1, 2, new QTableWidgetItem("Item H"));
table->setItem(2, 2, new QTableWidgetItem("Item I"));
mainWin.setCentralWidget(table);
mainWin.show();
auto slot = [&table](QTableWidgetItem* item){
QStyleOptionViewItem option;
option.font = item->font();
option.fontMetrics = QFontMetrics(item->font());
if (item->textAlignment())
option.displayAlignment = static_cast<Qt::Alignment>(item->textAlignment());
else
option.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter; // default alignment
option.features |= QStyleOptionViewItem::HasDisplay;
option.text = item->text();
option.rect = table->visualItemRect(item);
// If your table cells contain also decorations or check-state indicators,
// you have to set also:
// option.features |= QStyleOptionViewItem::HasDecoration;
// option.icon = ...
// option.decorationSize = ...
QRect textRect = table->style()->subElementRect(QStyle::SE_ItemViewItemText, &option, nullptr);
double leftMargin = textRect.left() - option.rect.left();
double rightMargin = option.rect.right() - textRect.right();
double topMargin = textRect.top() - option.rect.top();
double bottomMargin = option.rect.bottom() - textRect.bottom();
qDebug() << leftMargin;
qDebug() << rightMargin;
qDebug() << topMargin;
qDebug() << bottomMargin;
};
QObject::connect(table, &QTableWidget::itemClicked, slot);
return app.exec();
}
EDIT
To compute an exact space between table cell border and the text pixels, you have to use a QFontMetrics class.
See the QFontMetrics::leftBearing() and QFontMetrics::tightBoundingRect().
I have such code on Qt.
wdgCenter = new QWidget(wdgMain);
wdgCenter->move(wdgCenter->parentWidget()->geometry().center());
wdgCenter->resize(QSize(170, 115));
welcomeLbl = new QLabel("Welcome to the Notes. Log in first.", wdgCenter);
welcomeLbl->setGeometry(QRect(QPoint(0, 0), QSize(175, 20)));
loginLbl = new QLabel("Login", wdgCenter);
loginLbl->setGeometry(QRect(QPoint(0, 30), QSize(50, 20)));
pswdLbl = new QLabel("Password", wdgCenter);
pswdLbl->setGeometry(QRect(QPoint(0, 60), QSize(50, 20)));
loginLine = new QLineEdit (wdgCenter);
loginLine->setGeometry(QRect(QPoint(60, 30), QSize(110, 20)));
passwordLine = new QLineEdit (wdgCenter);
passwordLine->setGeometry(QRect(QPoint(60, 60), QSize(110, 20)));
logInBtn = new QPushButton ("Log In", wdgCenter);
logInBtn->setGeometry(QRect(QPoint(0, 90), QSize(50, 25)));
createBtn = new QPushButton ("Create", wdgCenter);
createBtn->setGeometry(QRect(QPoint(60, 90), QSize(50, 25)));
The result you can see below on the first picture.
I want to move my wdgCenter to the center of the window. I tried QGridLayout like this below.
QGridLayout* gLayout = new QGridLayout(wdgMain);
gLayout->addWidget( welcomeLbl );
gLayout->setAlignment(welcomeLbl,Qt::AlignHCenter);
gLayout->addWidget( loginLbl, 1, 0 );
gLayout->setAlignment(loginLbl,Qt::AlignHCenter);
gLayout->addWidget( pswdLbl, 2, 0 );
gLayout->setAlignment(pswdLbl,Qt::AlignHCenter);
gLayout->addWidget( loginLine, 1, 1 );
gLayout->setAlignment(loginLine,Qt::AlignHCenter);
gLayout->addWidget( passwordLine, 2, 1 );
gLayout->setAlignment(passwordLine,Qt::AlignHCenter);
gLayout->addWidget( logInBtn, 3, 0 );
gLayout->setAlignment(logInBtn,Qt::AlignHCenter);
gLayout->addWidget( createBtn, 3, 1 );
gLayout->setAlignment(createBtn,Qt::AlignHCenter);
And the result you can see on the next picture below.
I also tried QHBoxLayout and QHBoxLayout but they just draw me my objects in on row or in one column.
In Qt Designer I did this with vertical and horizontal spacers like this:
But I need to do this programmatically.
How to set my wdgCenter to The center?
A simple way would be designing the UI using Qt Designer and let it generate the source code. Auto-generated source code for the UI is in a .h file called ui_<your class name>.h, for example: ui_mainwindow.h. This file is included automatically in <your class name>.cpp file, so you can find it there.
The Qt Designer overview:
Result:
This question already has answers here:
how can I fully disable resizing a window including the resize icon when the mouse hovers the border?
(15 answers)
Closed 9 years ago.
I have a QGridLayout inside a QWidget. I keep adding child QGridLayouts to this. I want the QWidget to resize according to the size needed for child layouts but for the user to be unable to resize it.
MainWindow.cpp (MainWindow is inherited from QWidget)
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)
{
QGridLayout *mainLayout = new QGridLayout();
{
AAController *ac1 = new AAController("Ins1");
AAController *ac2 = new AAController("Ins2");
AAController *ac3 = new AAController("Ins3");
mainLayout->addLayout(ac1, 0, 0);
mainLayout->addLayout(ac2, 0, 1);
mainLayout->addLayout(ac3, 1, 1);
}
setLayout(mainLayout);
}
AAController.cpp (AAController is inherited from QGridLayout)
AAController::AAController(const QString& instrument)
:_instrument(instrument)
{
_lblInstrument = new QLabel(_instrument);
_lblMismatchThreshold = new QLabel("Mismatch threshold : ");
_lblQuoteVolume = new QLabel("Quote volume : ");
_btnUpdateAlgo = new QPushButton("Update Algo");
_spnMismatchThreshold = new QSpinBox();
_spnQuoteVolume = new QSpinBox();
this->addWidget(_lblInstrument, 0, 1, 1, 2, Qt::AlignCenter);
this->addWidget(_lblMismatchThreshold, 1, 0, 1, 2);
this->addWidget(_lblQuoteVolume, 2, 0, 1, 2);
this->addWidget(_btnUpdateAlgo, 3, 2, 1, 2);
this->addWidget(_spnMismatchThreshold, 1, 3);
this->addWidget(_spnQuoteVolume, 2, 3);
setSizeConstraint(SetFixedSize);
}
I get something like this:
But at the moment I can resize this like:
I want to disable such resizing. How do I do this?
Try this in your main window:
this->layout()->setSizeConstraint(QLayout::SetFixedSize);
This is the result i got:
this->setWindowTitle(tr("数据转移程序"));
edt_ftp_server = new QLineEdit;
edt_ftp_port = new QLineEdit;
edt_ftp_account = new QLineEdit;
edt_ftp_pwd = new QLineEdit;
edt_ftp_pwd->setEchoMode( QLineEdit::Password );
lbl_ftp_server = new QLabel;
lbl_ftp_server->setText(tr("FTP服务器地址:"));
lbl_ftp_server->setBuddy( edt_ftp_server );
lbl_ftp_port = new QLabel;
lbl_ftp_port->setText(tr("FTP服务器端口:"));
lbl_ftp_port->setBuddy( edt_ftp_port );
lbl_ftp_account = new QLabel;
lbl_ftp_account->setText(tr("FTP登录帐号:"));
lbl_ftp_account->setBuddy( edt_ftp_account );
lbl_ftp_pwd = new QLabel;
lbl_ftp_pwd->setText(tr("FTP登录密码:"));
lbl_ftp_pwd->setBuddy( edt_ftp_pwd );
ftp_settings = new QGroupBox(this);
ftp_settings->setTitle(tr("FTP服务器设置"));
ftp_settingsLayout = new QGridLayout;
ftp_settingsLayout->addWidget( lbl_ftp_server, 0, 0);
ftp_settingsLayout->addWidget( edt_ftp_server, 0, 1);
ftp_settingsLayout->addWidget( lbl_ftp_port, 1, 0);
ftp_settingsLayout->addWidget( edt_ftp_port, 1, 1);
ftp_settingsLayout->addWidget( lbl_ftp_account, 2, 0);
ftp_settingsLayout->addWidget( edt_ftp_account, 2, 1);
ftp_settingsLayout->addWidget( lbl_ftp_pwd, 3, 0);
ftp_settingsLayout->addWidget( edt_ftp_pwd, 3, 1);
ftp_settings->setLayout( ftp_settingsLayout );
edt_db_server = new QLineEdit( this );
edt_db_port = new QLineEdit( this );
edt_db_account = new QLineEdit( this );
edt_db_pwd = new QLineEdit( this );
edt_db_pwd->setEchoMode( QLineEdit::Password );
lbl_db_server = new QLabel( this );
lbl_db_server->setText(tr("FTP服务器地址:"));
lbl_db_server->setBuddy( edt_ftp_server );
lbl_db_port = new QLabel( this );
lbl_db_port->setText(tr("FTP服务器端口:"));
lbl_db_port->setBuddy( edt_ftp_port );
lbl_db_account = new QLabel( this );
lbl_db_account->setText(tr("FTP登录帐号:"));
lbl_db_account->setBuddy( edt_ftp_account );
lbl_db_pwd = new QLabel( this );
lbl_db_pwd->setText(tr("FTP登录密码"));
lbl_db_pwd->setBuddy( edt_ftp_pwd );
db_settings = new QGroupBox(this);
db_settings->setTitle(tr("数据库服务器设置"));
db_settingsLayout = new QGridLayout;
db_settingsLayout->addWidget( lbl_ftp_server, 0, 0);
db_settingsLayout->addWidget( edt_ftp_server, 0, 1);
db_settingsLayout->addWidget( lbl_ftp_port,1, 0);
db_settingsLayout->addWidget( edt_ftp_port,1, 1);
db_settingsLayout->addWidget( lbl_ftp_account, 2, 0);
db_settingsLayout->addWidget( edt_ftp_account, 2, 1);
db_settingsLayout->addWidget( lbl_ftp_pwd,3, 0);
db_settingsLayout->addWidget( edt_ftp_pwd, 3, 1);
db_settings->setLayout( db_settingsLayout );
buttonsLayout = new QHBoxLayout;
buttonsLayout->addStretch();
btn_start = new QPushButton;
btn_start->setText(tr("开始"));
buttonsLayout->addWidget(btn_start);
btn_stop = new QPushButton;
btn_stop->setText(tr("停止"));
buttonsLayout->addWidget( btn_stop );
btn_exit = new QPushButton;
btn_exit->setText(tr("退出"));
buttonsLayout->addWidget(btn_exit);
settingLayout = new QVBoxLayout;
settingLayout->addWidget( db_settings );
settingLayout->addStretch();
settingLayout->addWidget( ftp_settings );
centralLayout = new QHBoxLayout;
centralLayout->addLayout( settingLayout );
lst_log = new QListWidget;
centralLayout->addWidget(lst_log);
winLayout = new QVBoxLayout;
winLayout->addLayout( centralLayout );
winLayout->addLayout( buttonsLayout );
setLayout( winLayout );
I am developing a tiny qt program, and have writen above code in a QMainWindow subclass Constructor.
But the widgets displayed are messed up.All advices are appreciated!
The following is the result screenshot:
I suspect that the problem lies in the top level layout, which is winLayout. Set QMainWindow's central widget to winLayout's parent:
winLayout = new QVBoxLayout(ui->centralWidget);
I recommend using Qt Creator or Qt Designer for designing the user interfaces. Qt Creator creates the necessary code for layouts and other uninteresting things. And even if you decide to create user interfaces by writing your own code, you can create a prototype with Qt Creator and look what kind of code it creates.