How to properly manage text and icon with QToolButton? - c++

I have code snippet looks like this:
nextPageBtn = new QToolButton();
nextPageBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
nextPageBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
nextPageBtn->setIcon(QIcon(":/next.png"));
nextPageBtn->setText("Next");
Currently I have two problems with this.
First:
I want the text is on the left of the icon, but with the code I provide, the text is on the right like this:
Second:
When the window is enlarged, I can not figure out a way to keep the text and icon in the center of the button. It looks like this when the button gets bigger:
Edit:
This is how I manage the layout:
nextPageHLayout = new QHBoxLayout; //This is the layout for QToolButton, it has two spacers and a QToolButton
mainVLayout->addLayout(nextPageHLayout); //mainVLayout is the main layout, and I put the mainVLayout to the central widget, and it also contains a QLabel above the nextPageHLayout
QSpacerItem *leftBtnSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed);
nextPageHLayout->addSpacerItem(leftBtnSpacer);
nextPageBtn = new QToolButton(mainWidget);
nextPageHLayout->addWidget(nextPageBtn);
nextPageBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
nextPageBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
nextPageBtn->setIcon(QIcon(":/next.png"));
nextPageBtn->setText("Next");
QSpacerItem *rightBtnSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed);
nextPageHLayout->addSpacerItem(rightBtnSpacer);

You must make the following changes:
You should not change the size policy of the QToolButton, that's why it's expanding.
You must change the layoutDirection to Qt::RightToLeft.
QHBoxLayout * nextPageHLayout = new QHBoxLayout; //This is the layout for QToolButton, it has two spacers and a QToolButton
mainVLayout->addLayout(nextPageHLayout); //mainVLayout is the main layout, and it also contains a QLabel above the nextPageHLayout
QSpacerItem *leftBtnSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
nextPageHLayout->addSpacerItem(leftBtnSpacer);
nextPageBtn = new QToolButton(mainWidget);
nextPageHLayout->addWidget(nextPageBtn);
nextPageBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
nextPageBtn->setIcon(QIcon(":/next.png"));
nextPageBtn->setText("Next");
nextPageBtn->setLayoutDirection(Qt::RightToLeft);
QSpacerItem *rightBtnSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
nextPageHLayout->addSpacerItem(rightBtnSpacer);

Related

Is possible to have a widget that doesnt scroll in a QScrollArea?

Given this example:
Suppose A and B are QWidgets
Is it possible to keep everything starting from B static when the QScrollArea widget is scrolled?
The QScrollArea occupies the entire GUI, B is inside it to let the vertical ScrollBar closer to the right border of the GUI, or it would look like this:
What I can do in this case?
It is possible. You have to make use of the scrollbar being a widget of its own.
Here is the method:
Change your window in Qt Designer to be: spacer, QScrollArea (that will contain widget A), spacer, widget B, spacer; everything is in a QGridLayout (or QHBoxLayout but please read until the end).It is because widget B is outside the scroll area that it will not move during scrolling.
In your widget constructor, after ui->setupUi(); reparent and move the vertical scrollbar of your QScrollArea with these lines of code:
scrollArea->verticalScrollBar()->setParent(w);
layout->addWidget(sa->verticalScrollBar()); //Adds the scrollbar to the right of the layout.
Note about the margins:Obviously, you can easily push the scrollbar to the very right of your window by setting the layout right margin to 0.
If you also want it to cover the entire height of your window, while keeping some space between the other widgets and the window's border, that is where a QHBoxLayout will not suffice and you need a QGridLayout instead, set its top and bottom margin to 0 and add spacers (fixed size) to obtain the same visual result.
The C++ code for such a window would be:
QWidget* widget = new QWidget();
QGridLayout* layout = new QGridLayout(widget);
layout->setSpacing(0);
layout->setContentsMargins(9, 0, 0, 0);
widget->setLayout(layout);
QScrollArea* scrollArea = new QScrollArea(widget);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
QWidget* widgetB = new QLabel("Widget B", widget);
//Creates the spacer that will "simulate" the top and bottom margins
QSpacerItem* topSpacer = new QSpacerItem(0, 9, QSizePolicy::Minimum, QSizePolicy::Fixed),
* bottomSpacer = new QSpacerItem(0, 9, QSizePolicy::Minimum, QSizePolicy::Fixed);
layout->addItem(topSpacer, 0, 0);
layout->addWidget(scrollArea, 1, 0);
layout->addItem(bottomSpacer, 2, 0);
layout->addWidget(widgetB, 1, 1);
//Moves the scrollbar outside the scroll area
scrollArea->verticalScrollBar()->setParent(widget);
layout->addWidget(scrollArea->verticalScrollBar(), 0, 2, 3, 1);
QLabel* innerLabel = new QLabel("Some big label to force the scrolling");
scrollArea->setWidget(innerLabel);
innerLabel->setMinimumHeight(500);
widget->show();

QComboBox not aligning to right

I have a QHBoxLayout and i want to add some children to the right, and other to the left:
label = new QLabel(...);
layout->addItem(label);
layout->setAlignment(label, Qt::AlignLeft);
select = new QComboBox(...);
layout->addItem(select);
layout->setAlignment(select, Qt::AlignRight);
However select is not been aligned to the right... any idea?
Neither with QCheckBox and QLabel, but works properly using QSlider
QHBoxLayout * layout = new QHBoxLayout(this);
QLabel * label = new QLabel("this is label");
layout->addWidget(label, Qt::AlignLeft);
layout->setAlignment(label, Qt::AlignLeft);
QComboBox * select = new QComboBox(this);
layout->addWidget(select);
layout->setAlignment(select, Qt::AlignRight);

Qt layouts, difference between passing and not passing QWidget as parent

I have created a simple QHBoxLayout (horizontal) that is pushed to the bottom of the QVBoxLayout (Vertical) and it contains two buttons. See code:
QWidget* create_ver_and_horizontal_box() {
QWidget* temp = new QWidget();
// Add buttons to the horizontal box
QHBoxLayout* hbox = new QHBoxLayout();
QPushButton *ok = new QPushButton("OK");
QPushButton *cancel = new QPushButton("Cancel");
hbox->addWidget(ok);
hbox->addWidget(cancel);
// Create a vertical box and add the horizontal box to
// the end of it
QVBoxLayout* vbox = new QVBoxLayout();
vbox->addStretch(1);
vbox->addLayout(hbox);
// set the layout and return
temp->setLayout(vbox);
return temp;
}
and the resulting UI is the following.
But when I add the QWidget temp to be the parent of the QHBoxLayout, like so:
// Add buttons to the horizontal box
QHBoxLayout* hbox = new QHBoxLayout(temp);
This is what I get:
I want to understand what is going on here. And in which cases I want the QWidget to be the parent of a layout or any other QWidget(s) and in which cases I don't the containing QWidget to be the parent of the containing QWidgets. For example, I could've added temp to be the parent of the two Push buttons but I didn't. What is the implication of not adding vs adding.
Thanks,
QHBoxLayout* hbox = new QHBoxLayout(temp);
is equivalent to
QHBoxLayout* hbox = new QHBoxLayout();
temp->setLayout(hbox);
I.e. you are making the horizontal layout responsible for temp.
The call to setLayout(vbox) should have generated a runtime warning message, that temp already has a layout, hinting at that.
Since you want the vertical layout to be responsible for that widget, either keep the temp->setLayout(vbox) or pass temp to the constructor of QVBoxLayout.

check QCheckBox in QVboxLayout of QStackedWidget

i have a QstackedWidget and i add QHboxLayout and QVBoxLayout to it, in my vertical layout i add 3 QCheckBox, and i add this layout with two spacer for left and right side to it, then i push this new layout with two spacer for top and bottom in horizontal layout, now i want to check if this QCheckBoxes are checked or not, but i don't know how to check this.
here is my code :
QVBoxLayout *center = new QVBoxLayout();
QVBoxLayout *main = new QVBoxLayout();
QHBoxLayout *middle = new QHBoxLayout();
QSpacerItem *topspacer = new QSpacerItem(14, 24, QSizePolicy::Fixed, QSizePolicy::Fixed);
QSpacerItem *buttom = new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Expanding);
QSpacerItem *left = new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Expanding);
QSpacerItem *right = new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Expanding);
middle->addItem(left);
middle->addLayout(center);
middle->addItem(right);
center->addWidget(checkBoxEvent(QString::fromStdString("Analyze events")));
center->addWidget(checkBoxEvent(QString::fromStdString("Edit Tracks")));
center->addWidget(checkBoxEvent(QString::fromStdString("Analyze players")));
main->addItem(topspacer);
main->addLayout(middle);
main->addItem(buttom);
Qwidget *m_page = new Qwidget();
m_page->setLayout(main);
m_stackedWidget->addWidget(m_page);
i tried this code for accessing to elements but i get segmentation fault:
for(int i = 0; i < m_stackedWidget->widget(2)->layout()->count(); i++)
if(dynamic_cast<QPushButton*>( m_stackedWidget->widget(2)->layout()->itemAt(i) )->isChecked())
this items are added to m_stackedWidget[1]

How to fix QHBoxLayout items size and add drop-down list to every item in QHBoxLayout

I have custom window class
#define NAME_WIDTH 150
#define NAME_HEIGHT 20
ObjectWindow::ObjectWindow(QWidget * parent)
{
}
void ObjectWindow::SetKey(KeyObject * keyObj)
{
QGridLayout * layout = new QGridLayout(this);
nameField = new QTextEdit(this);
nameField->setText(keyObj->name);
nameField->setGeometry(nameField->geometry().x(), nameField->geometry().y(),
NAME_WIDTH, NAME_HEIGHT);
layout->addWidget(nameField);
QHBoxLayout * picsLayout = new QHBoxLayout(this);
for(std::vector<ImageInstance*>::iterator imgObj = keyObj->images.begin(); imgObj != keyObj->images.end(); imgObj++)
{
QComboBox * folderList = new QComboBox;
picsLayout->addWidget(folderList);
QImage image((*imgObj)->imgPath);
QLabel * picLabel = new QLabel;
picLabel->setPixmap(QPixmap::fromImage(image).scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation));
picsLayout->addWidget(picLabel);
}
layout->addLayout(picsLayout, 2, 0);
QPushButton * saveBtn = new QPushButton(this);
saveBtn->setText("Save");
connect(saveBtn, SIGNAL(released()),this, SLOT(Save()));
layout->addWidget(saveBtn);
setLayout(layout);
}
What i need is
small text field to set the name, I don't unerstand why SetGeometry doesn't work
dropdown list above each image. I can create QHVertical layout for each set of image and list, but maybe there is more simple way to do it?
If you just want the user to set the name, a QLineEdit is probably enough.
Then the main advantage of using a QGridLayout is that you don't need to create other layouts. It acts like a grid where you put your widgets, a bit like Excel (and other spreadsheet programs).
Oh and I see that you are not constructing the Widgets in the constructor (which seems to be empty), that's what people usually do because constructing the UI can be expensive and you just want to update it when relevant, not rebuilding the whole UI just to update a field. But without more code I cannot tell when this function is being called.
You can try something like this:
QGridLayout * layout = new QGridLayout(this);
nameField = new QLineEdit(this);
nameField->setText(keyObj->name);
layout->addWidget(nameField, 0, 0, -1, 1); // expand to the right edge
int currentColumn = 0;
for(std::vector<ImageInstance*>::iterator imgObj = keyObj->images.begin(); imgObj != keyObj->images.end(); imgObj++)
{
QComboBox * folderList = new QComboBox;
layout->addWidget(folderList, 1, currentColumn);
QPixmap pixmap((*imgObj)->imgPath);
pixmap = pixmap.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QLabel * picLabel = new QLabel(this);
picLabel->setPixmap(pixmap);
layout->addWidget(picLabel, 2, currentColumn);
++currentColumn;
}
QPushButton * saveBtn = new QPushButton("Save", this);
connect(saveBtn, SIGNAL(released()),this, SLOT(Save()));
layout->addWidget(saveBtn, 3, 0, -1, 1);
setLayout(layout);
But it doesn't seem to be a good idea to add those widgets horizontally like that. What would happen if there are 100 items in this vector? You should investigate in using something like a QScrollArea or modifying the UI to give your client the best way to view and edit those (but without more context it seems difficult to give your more advice).