QGroupBox: label cut and positioning inside QGridLayout - c++

To be more clear explaining my problem, I've done a screenshot with some notes on it, hope it helps:
QGroupBox Layout format problem
As you can see from it, I have one big QVBoxLayout for the main layout of the app, inside it I've put a Qwidget, then a QGridLayout and then a QGridLayout again.
Inside this last one QGridLayout, I've put two QGroupBoxes, one in position 0,0 and one in position 0,1. Each QGroupBox has its own inner Layout, both of QGridLayout type again.
The screenshot shows that the firs QGroupBox works good, while the second one, that's quite smaller than the first, has two problems:
1) The label shoul be "Specific Operations" but it is trunked, and the only way to show it completely seems to be to put the buttons one next to the other horizontally... but I don't want it!
2) I managed to align the QGroupbox on the left of its "grid" but I need it to be on the upper-left corner of it, while it is centered for the moment... How can I achieve this?
Here is part of the code that should help you understand. Here is the kalk.h file:
class Kalk : public QWidget
{
Q_OBJECT
public:
Kalk(QWidget *parent = 0);
private slots:
void kalkChange(QString);
//....
private:
QComboBox *chooser;
QVBoxLayout *mainLayout;
QGridLayout *subLayout;
QGridLayout *operationsLayout;
QGroupBox *baseOperators;
QGridLayout *baseOperatorsLayout;
QGroupBox *specificOperators;
QGridLayout *specificOperatorsLayout;
};
Then the corresponding kalk.cpp file:
Kalk::Kalk(QWidget *parent) : QWidget(parent){
chooser = new QComboBox();
//...
connect(chooser,SIGNAL(currentIndexChanged(QString)),this,SLOT(kalkChange(QString)));
mainLayout = new QVBoxLayout;
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
subLayout = new QGridLayout;
subLayout->setEnabled(false);
subLayout->setSizeConstraint(QLayout::SetFixedSize);
mainLayout->addWidget(chooser);
mainLayout->addLayout(subLayout);
//operationsLayout = new QHBoxLayout;
operationsLayout = new QGridLayout;
operationsLayout->setSizeConstraint(QLayout::SetFixedSize);
baseOperators = new QGroupBox(tr("Base Operations"));
baseOperatorsLayout = new QGridLayout(baseOperators);
baseOperatorsLayout->setSizeConstraint(QLayout::SetFixedSize);
specificOperators = new QGroupBox(tr("Specific Operations"));
specificOperatorsLayout = new QGridLayout(specificOperators);
specificOperatorsLayout->setSizeConstraint(QLayout::SetFixedSize);
operationsLayout->addWidget(baseOperators,0,0);
operationsLayout->setAlignment(baseOperators,Qt::AlignLeft);
operationsLayout->addWidget(specificOperators,0,1);
operationsLayout->setAlignment(specificOperators,Qt::AlignLeft);
mainLayout->addLayout(operationsLayout);
setLayout(mainLayout);
//...
}
In another function I load the buttons inside the Layout of the QGroupBox, but I don't think the problem is here...

Related

Issue change tab QTabWidget & QScrollArea Qt

I'm trying to create a QScrollArea in a QTabWidget.
Versions :
Qt 5.15.0
Qt creator 4.12.4
MSVC2019 64 bits
First of all, I've created the QTabWidget :
tabWidget = new QTabWidget(this);
tabWidget->setGeometry(10, 15, 1200, 665);
tabWidget->setStyleSheet("font-size : 15px");
tab1Content = new QWidget(tabWidget); tabWidget->addTab(tab1Content, "tab1");
tab2Content = new QWidget(tabWidget); tabWidget->addTab(tab2Content, "tab2");
tab3Content = new QWidget(tabWidget); tabWidget->addTab(tab3Content, "tab3");
tab4Content = new QWidget(tabWidget); tabWidget->addTab(tab4Content, "tab4");
I can add
tabWidget->setEnable(true);
And for all tabs, 0 <= i < tabWidget.count
tabWidget->setTabEnabled(i, true);
Click to change tab doesn't work : https://i.stack.imgur.com/8r1Jg.png
Strange thing : color looks like enabled but i can only change tabs with ← → and when i lost tabWidget focus by clicking on an other thing outside the tabWidget, i can't regain focus.
So i've created temporary button to change tabs and linked to tabWidget like that :
connect(changeTab, &QPushButton::clicked, [&]() {onChangeTab();});
void MainWindow::onChangeTab() {
tabWidget->setCurrentIndex(tabWidget->currentIndex() >= tabWidget->count() - 1 ? 0 : tabWidget->currentIndex() + 1);
}
It works well.
Thus, I've start to create the QScrollArea :
First, it doesn't work, so I've tried to found sth on internet :
QScrollArea not working as expected with QWidget and QVBoxLayout
My result : https://i.stack.imgur.com/jvVol.png
I cannot click on a single button and i can't scroll...
And if i try to force scroll like this, it doesn't scroll
scrollArea->scroll(0, 50);
Last thing, there isn't infinite loop or dead lock things because all things around this cursed tabWidget and scroll Area work perfectly.
I don't know why these objects "don't answer" if somedoby had this kind of experiment could you help me please ?
Thank you very much in advance.
try this code
#include "widget.h"
#include<QTabWidget>
#include<QLabel>
#include<QVBoxLayout>
#include<QScrollArea>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QTabWidget *tabWidget = new QTabWidget(this);
tabWidget->setGeometry(10, 15, 1200, 665);
tabWidget->setStyleSheet("font-size : 15px");
QWidget * tab1Content = new QWidget;
//preparing tab1content ( e.g.)
QVBoxLayout * verticalLayout = new QVBoxLayout;
// adding items to vertical layout
for(int i=0;i<100;i++)
verticalLayout->addWidget(new QLabel(QString::number(i)));
// set this vertical layout inside tab1content
tab1Content->setLayout(verticalLayout);
// create new scroll area ...
QScrollArea * scroll = new QScrollArea;
// ... and add tab1content in scroll area
scroll->setWidget(tab1Content);
// and finally add scroll area inside tabwidget
tabWidget->addTab(scroll,"tab1");
QWidget * tab2Content = new QWidget; tabWidget->addTab(tab2Content, "tab2");
QWidget * tab3Content = new QWidget; tabWidget->addTab(tab3Content, "tab3");
QWidget * tab4Content = new QWidget; tabWidget->addTab(tab4Content, "tab4");
}
Widget::~Widget()
{
}

Why is the QScrollArea restricted in size?

To my custom widget, inherited from QWidget, I have added a QScrollArea like this:
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)//MainWindow is a QWidget
{
auto *scrollArea = new QScrollArea(this);
auto *widget = new QWidget(this);
widget->setStyleSheet("background-color:green");
scrollArea->setWidget(widget);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
QVBoxLayout *parentLayout = new QVBoxLayout(widget);
this->setStyleSheet("background-color:blue");
for(int i=0;i<12;i++){
QHBoxLayout* labelLineEdit = f1();
parentLayout->addStretch(1);
parentLayout->addLayout(labelLineEdit);
}
parentLayout->setContentsMargins(0,0,40,0);
}
QHBoxLayout* MainWindow::f1()
{
QHBoxLayout *layout = new QHBoxLayout;
QLabel *label = new QLabel("Movie");
label->setStyleSheet("background-color:blue;color:white");
label->setMinimumWidth(300);
label->setMaximumWidth(300);
layout->addWidget(label);
QLineEdit *echoLineEdit = new QLineEdit;
echoLineEdit->setMaximumWidth(120);
echoLineEdit->setMaximumHeight(50);
echoLineEdit->setMinimumHeight(50);
echoLineEdit->setStyleSheet("background-color:white");
layout->addWidget(echoLineEdit);
layout->setSpacing(0);
return layout;
}
This produces a window which looks like this:
The problem is, that I want the scrollArea to occupy the entire window, but it does not. It also doesn't get resized when I resize the window.
How could I fix this?
The problem is, that I want the scrollArea to occupy the entire
window, but it does not. It also doesn't get resized when I resize the window.
The reason is that you have not set any kind of layout to manage the positioning of your QScrollArea widget itself, so it is just being left to its own devices (and therefore it just chooses a default size-and-location for itself and stays at that size-and-location).
A simple fix would be to add these lines to the bottom of your MainWindow constructor:
QBoxLayout * mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
mainLayout->addWidget(scrollArea);

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.

Creating tabs in Qt using QTabWidget

Here they tell us how to create tabs:
Create a QTabWidget.
Create a QWidget for each of the pages in the
tab dialog, but do not specify parent widgets for them.
Insert child
widgets into the page widget, using layouts to position them as
normal.
Call addTab() or insertTab() to put the page widgets into the
tab widget, giving each tab a suitable label with an optional
keyboard shortcut.
So, I created a tab widget:
class mainWindow : public QDialog
{
Q_OBJECT
QWidget* m_mainWindow;
QTabWidget* tab;
...
Then I have a Widget Class that defines a "page":
class tradeView : public QWidget
{
Q_OBJECT
QWidget* tradeWidget;
...
THis is how the c'tor of the widget (that is supposed to go into the tab as a page) looks like:
tradeView::tradeView()
{
tradeWidget = new QWidget;
tradeWidget->setWindowTitle("Trade View");
tradeWidget->setGeometry(150,18,1800,800);
m_pTableWidget = new QTableWidget(this);
m_pTableWidget->setRowCount(100);
m_pTableWidget->setColumnCount(6);
m_TableHeader<<"Client Id"<<"Symbol"<<"Quantity"<<"Strategy Id"<<"Expiry" << "Side";
m_pTableWidget->setHorizontalHeaderLabels(m_TableHeader);
m_pTableWidget->verticalHeader()->setVisible(false);
m_pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
m_pTableWidget->setShowGrid(false);
m_pTableWidget->setStyleSheet("QTableView {selection-background-color: red;}");
m_pTableWidget->setGeometry(QApplication::desktop()->screenGeometry());
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_pTableWidget);
tradeWidget->setLayout(layout);
}
Then I did the following inside my main dialog c'tor:
mainWindow::mainWindow(QWidget* parent):QDialog(parent)
{
m_mainWindow = new QWidget;
m_mainWindow->setWindowTitle("Main Window");
QVBoxLayout *layout = new QVBoxLayout;
tradeView* tradeViewWindow = new tradeView();
orderView* orderViewWindow = new orderView();
tab = new QTabWidget(this);
tab->addTab(tradeViewWindow, "Trade");
tab->addTab(orderViewWindow, "Order");
layout->addWidget(tab);
m_mainWindow->setLayout(layout);
m_mainWindow->setGeometry(150,18,1850,900);
m_mainWindow->show();
}
I was expecting the widget to show up in the tab.
But when I run the code, the tab is created, but is completely empty.
What am I missing here ?
Your widget construction is strange. The rough object ownership of your widgets is like the following:
MainWindow (top-level QDialog)
m_mainWindow (top-level QWidget)
tab (QTabWidget)
tradeViewWindow (QWidget)
orderViewWindow (QWidget)
tradeView->tradeWidget (hidden top-level QWidget)
QTableWidget
orderView->orderWidget (hidden top-level QWidget)
QTableWidget
Do you see the problem now? You actually have 4 top-level QWidgets and two of them are hidden. You are seeing empty tabs since you create QTableWidget in another QWidget which is hidden. In other words, QTableWidget's parent is not the tab, its parent is a hidden top-evel QWidget.
The solution: tradeView is already a QWidget itself, there is no need to create another tradeWidget inside it again. You should set the layout's parent to tradeView itself:
tradeView::tradeView()
{
//tradeWidget = new QWidget; // this is a hidden top-level QWidget
//tradeWidget->setWindowTitle("Trade View");
//tradeWidget->setGeometry(150,18,1800,800);
m_pTableWidget = new QTableWidget(this);
m_pTableWidget->setRowCount(100);
m_pTableWidget->setColumnCount(6);
m_TableHeader<<"Client Id"<<"Symbol"<<"Quantity"<<"Strategy Id"<<"Expiry" << "Side";
m_pTableWidget->setHorizontalHeaderLabels(m_TableHeader);
m_pTableWidget->verticalHeader()->setVisible(false);
m_pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
m_pTableWidget->setShowGrid(false);
m_pTableWidget->setStyleSheet("QTableView {selection-background-color: red;}");
m_pTableWidget->setGeometry(QApplication::desktop()->screenGeometry());
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_pTableWidget);
//tradeWidget->setLayout(layout);
this->setLayout(layout);
}
As a sidenote, your MainWindow which is a QDialog creates another m_mainWindow as well, are you sure this is your intention?

Replace page of a QTabWidget with a new widget

Basically I have a QTabWidget. At first it has a form widget, widget1. After that form is done being interacted with, the new widget2 form should take over that same tab.
I thought tabWidget->setCurrentWidget(new widget2()); would work, but it's basically an overload for setCurrentIndex(int).
Does anyone know of a way to do this?
You can use a QStackedWidget for this type of thing, in a tab or elsewhere.
Put all the widgets you'll want to display in that tab inside a single QStackedWidget, and place that stacked widget in a tab.
Here's a quick'n'dirty demo:
#include <QtGui>
class W: public QWidget
{
Q_OBJECT
public:
W(QWidget *parent=0): QWidget(parent)
{
// stacked widget displays one of its "children" at a time
QStackedWidget *sw = new QStackedWidget;
QPushButton *b1 = new QPushButton("hello");
sw->addWidget(b1);
QPushButton *b2 = new QPushButton("world");
sw->addWidget(b2);
// tab widget and simplistic layout
QTabWidget *tw = new QTabWidget(this);
tw->addTab(sw, "tab");
QHBoxLayout *l = new QHBoxLayout;
l->addWidget(tw);
setLayout(l);
// signal mapper to demo the widget switching
QSignalMapper *m = new QSignalMapper(this);
connect(b1, SIGNAL(clicked()), m, SLOT(map()));
m->setMapping(b1, 1);
connect(b2, SIGNAL(clicked()), m, SLOT(map()));
m->setMapping(b2, 0);
connect(m, SIGNAL(mapped(int)), sw, SLOT(setCurrentIndex(int)));
}
};