resize qwidget in a layout manually on runtime - qt

I have a QVBoxLayout with a few widgets in it (QTableViews). Now these QTableViews all have the same size. What can I do, that the user can change the size of one QTableView on runtime (so that 1 QTableView is bigger than the other one)? Maybe with a "seperator" which you can change with the mouse?

Use a QSplitter: http://doc.qt.digia.com/4.6/qsplitter.html
If you have this code:
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(table1);
layout->addWidget(table2);
layout->addWidget(table3);
setLayout(layout);
You should be able to just change it to:
QSplitter *splitter = new QSplitter;
splitter->addWidget(table1);
splitter->addWidget(table2);
splitter->addWidget(table3);
splitter->setOrientation(Qt::Vertical);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(splitter);
setLayout(layout);

Related

Making a layout in Qt

I just begin to work on making a layout with Grid. I tried to make it using the HBoxlayout and VBoxlayout. But How to set the position of the layout. I searched out and I found the setAlignment option but it isn't working on it.
So how to do its postioning of layouts like the image?
this is the layout I want to make
check this out
#include "mainscreen.h"
#include "ui_mainscreen.h"
#include<QLayout>
#include<QPushButton>
MainScreen::MainScreen(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainScreen)
{
ui->setupUi(this);
QGridLayout *layout=new QGridLayout;
QHBoxLayout *hlayout=new QHBoxLayout;
QPushButton *x=new QPushButton;
hlayout->setAlignment(Qt::AlignTop);
hlayout->addWidget(x);
layout->addChildLayout(hlayout);
this->setLayout(layout);
this->show();
}
MainScreen::~MainScreen()
{
delete ui;
}
You can find good information about Layout in this Tutorial from Qt: http://doc.qt.io/qt-5/qtwidgets-layouts-basiclayouts-example.html
Two things that are important for your Layout:
You need to nest several layout. Themain layout will be a VBoxlayout that contains the top and bottom Widget and one HBoxLayout in the middle. The HBoxLayout contain the other two widgets.
Two get different size for the two middle widgtes you need to give either a Stretch factor to the Layout or define sizes for the widgets.
You may consider doing the following
QHBoxLayout *TopLayout = new QHBoxLayout;
QHBoxLayout *BottomLayout = new QHBoxLayout;
QHBoxLayout *MiddleLayout = new QHBoxLayout;
QVBoxLayout *mainLayout = new QVBoxLayout;
QPushButton *topBtn = new QPushButton;
QPushButton *bottomBtn = new QPushButton;
QPushButton *LeftMiddleBtn = new QPushButton;
QPushButton *RightMiddleBtn = new QPushButton;
TopLayout->addWidget(topBtn);
BottomLayout->addWidget(bottomBtn);
// order matters here (i.e. the first addWidget will be placed in the left)
MiddleLayout->addWidget(LeftMiddleBtn);
MiddleLayout->addWidget(RightMiddleBtn);
// order matters here
mainLayout->addLayout(TopLayout);
mainLayout->addLayout(MiddleLayout);
mainLayout->addLayout(BottomLayout);
setLayout(mainLayout);
More convenient and right approach is to use Qt Designer or Qt Creator for this matter.
QMainWindow is a spatial case. It already has a layout set and it is impossible to change layout in widget! Reason is that QMainWindow has lots of other functionalities like menu, docking, status bar.
So how to make it work?
You have to set central widget:
MainScreen::MainScreen(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainScreen)
{
ui->setupUi(this);
auto widget = new QWidget();
setCentalWidget(widget);
auto vLayout = new QVBoxLayout(widget);
// add your stuff here
// some example for testing:
vLayout->addWidget(new QButton("Test button"));
vLayout->addWidget(new QLabel("Nice label"));
vLayout->addWidget(new QTextEdit);
}
Also you are doing something wrong since this line ui->setupUi(this); indicates that you are using Qt Designer (design ui by mouse) and this means that layout should not be setup directly by code!

QT. Add new layout to QLayout

I create interface dynamically when Application is run.
1) I have QTabWidget with 4 predefined tabs. But i must show only 1 or 2 tabs, in case of user shoice. On StackOverflow i learned, that i must keep all tabs in collection to add and destroit it.
I have QHash: twInputMethodsTabs = new QHash< int, QPair<QWidget*, QString> >();
First argument = index; Second = Tab Widget; Third = Tab Widget Caption Text;
2) I fill the collection like this:
for(int i = 0; i < ui->twInputMethods->children().length(); i++)
{
twInputMethodsTabs->insert(i, QPair<QWidget*, QString>(ui->twInputMethods->widget(i), ui->twInputMethods->tabText(i)));
}
3) I add new widget in the tab like this:
twInputMethodsTabs->value(1).first->layout()->addWidget(cmbbCommands);
4) How can i add new layout to this widget? I want to do like this:
QHBoxLayout *hblParams =new QHBoxLayout();
twInputMethodsTabs->value(1).first->layout()->addLayout(hblParams);
But it does not work, because layout() returns QLayout which havent addLayout() function. How i can do this?
Or how can i should change architecture of code to do this?
In this following code you get a widget (.first) and then select that widget's layout ->layout() and then add a Widget to that layout ->addWidget().
twInputMethodsTabs->value(1).first->layout()->addWidget(cmbbCommands);
In the following code you get a widget (.first) and then select that widget's layout ->layout() and try to set the layout on the layout.
twInputMethodsTabs->value(1).first->layout()->addLayout(hblParams);
Replacing the QLayout
To set the layout on the parent widget, you need to drop the ->layout():
twInputMethodsTabs->value(1).first->addLayout(hblParams);
Note that since you are now adding an empty layout to the widget, any widgets current in the previous layout will be lost, so you may need to re-add the widgets to the layout.
Adding new QLayout inside existing QLayout
If you want to add a layout into the existing layout, you cannot do this directly. QLayout can only accept QWidget via .addWidget(). However, you can apply a layout to an empty QWidget() and then add that to the layout. For example:
QWidget *w = new QWidget();
w.addLayout(hblParams);
twInputMethodsTabs->value(1).first->layout()->addWidget(w);
An alternative is to set the layout on the QWidget to a layout that does support .addLayout() such as QHBoxLayout or QVBoxLayout. For example:
QVBoxLayout *l = new QVBoxLayout();
cmbbCommands.setLayout(l); // Now has a layout that supports .addLayout
twInputMethodsTabs->value(1).first->layout()->addWidget(cmbbCommands);
Now the following should work because ->layout() returns a QVBoxLayout:
QHBoxLayout *hblParams =new QHBoxLayout();
twInputMethodsTabs->value(1).first->layout()->addLayout(hblParams);
I Hope, I get what you want to do:
twInputMethodsTabs->value(1).first->layout()->addWidget(cmbbCommands);
QHBoxLayout *hblParams =new QHBoxLayout();
QWidget *w = new QWidget(twInputMethodsTabs->value(1).first);
twInputMethodsTabs->value(1).first->layout()->addWidget(w);
w->addLayout(hblParams);
I just wrote the code here, so it is untested. However it should give you an idea what I tried to explain in my comment.
Cutted from "working" application:
WidgetA::WidgetA(QWidget *parent) : QWidget(parent)
{
QVBoxLayout *pLayout = new QVBoxLayout();
buildWidget(pLayout);
this->setLayout(pLayout);
}
void WidgetA::buildWidget(QVBoxLayout *layout){
for(int i=0; i<4; ++i){
this->buildSegments(layout);
}
}
void WidgetA::buildSegments(QVBoxLayout *layout){
QHBoxLayout *pHbl = new QHBoxLayout();
QLabel *pSegmentSize = new QLabel(this);
pSegmentSize->setText(tr("Segment Size(1,N)"));
QSpinBox *pSegments = new QSpinBox(this);
pHbl->addWidget(pSegmentSize);
pHbl->addWidget(pSegments);
layout->addItem(pHbl);
}
Read this one: Widgets Tutorial - Nested Layouts

Stop QWidgets from stacking on top of each other dynamically

I create all my QWidgets with code and put them in a tab. However all of the widgets are stacked on top of each other. Is there a way to move widgets dynamic?. It would be possible to move the widgets dynamic to how many there already is in the widget?.As it is know I have to move them with move() which could be hard to keep track on when more objects are added.
QTabWidget* MainWindow::CreateTabWidget(){
QTabWidget* tabWidget = new QTabWidget(ui->centralWidget);
tabWidget->setFixedSize(this->size().width(),this->size().height()- 40);
QWidget* tab = new QWidget();
QLabel* label = new QLabel("Sektionnamn",tab);
QLineEdit* line = new QLineEdit(tab);
line->move(0,20);
tabWidget->addTab(tab,"Tab 1");
return tabWidget;
}
Use QLayout:
QLabel* label = new QLabel("Sektionnamn");
QLineEdit* line = new QLineEdit();
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(label);
layout->addWidget(line);
tab->setLayout(layout);

Add widgets to a ScrollArea

I am creating a window dimanica to the downloads list.
But the scrollbar does not work and the "widgets children" are "cut".
Where can I be wrong? Thanks.
Source:
QWidget *central = new QWidget;
QScrollArea *scroll = new QScrollArea;
QVBoxLayout *layout = new QVBoxLayout(scroll);
scroll->setWidget(central);
scroll->setWidgetResizable(true);
int i=0;
while(i<10){
QWidget *p1 = new QWidget;
QHBoxLayout *hl = new QHBoxLayout(p1);
QLabel *label1 = new QLabel("test");
QLabel *label2 = new QLabel("0%");
hl->addWidget(label1);
hl->addWidget(label2);
layout->addWidget(p1);
i++;
}
QMainWindow *w = new QMainWindow;
w->setGeometry(50,50,480,320);
w->setCentralWidget(scroll);
w->show();
Found your mistake, you should set layout to widget central not to scroll:
QWidget *central = new QWidget;
QScrollArea *scroll = new QScrollArea;
QVBoxLayout *layout = new QVBoxLayout(central);
scroll->setWidget(central);
scroll->setWidgetResizable(true);
EDITED:
Your labels already take all available space, if you noticed, label1 begins at left border ends in the middle, where label2 starts and ends at the right border. If I understood you correctly, you want label1 to take all the space available, while label2 with percents to take only what space is needed, no more?
Read about QSizePolicy class and use setSizePolicy() on your labels. Try to insert this line right after label2 declaration:
QLabel *label2 = new QLabel("0%");
label2->setSizePolicy(QSizePolicy::QSizePolicy::Maximum,QSizePolicy::Maximum);
And add line layout->addStretch(); right before QMainWindow *w = new QMainWindow;

How to delete a space between QLabel and QLineEdit

I want to reduce space between label and QLineEdit (QLabel is above QLineEdit). How can I achieve it? In the code I'm creating items, that I later put in some layouts.
QLabel* lgamma = new QLabel("Gamma");
gamma = new QLineEdit();
QLabel* lmin_linie = new QLabel(QString::fromUtf8("Min. il. zmian linii"));
min_lin = new QLineEdit();
// ...
QLabel* lmax_kursy = new QLabel(QString::fromUtf8("Max zm. il. kursów"));
max_kursy = new QLineEdit();
QGridLayout *lay = new QGridLayout(this);
QVBoxLayout *box1 = new QVBoxLayout();
QVBoxLayout *box2 = new QVBoxLayout();
// ...
QVBoxLayout *box12 = new QVBoxLayout();
box1->addWidget(lmin_linie);
box1->addWidget(min_lin);
box2->addWidget(lmax_lin);
box2->addWidget(max_lin);
// ...
box12->addWidget(literacje);
box12->addWidget(iteracje);
verticalColumn1->addLayout(box1);
verticalColumn1->addLayout(box2);
// ...
verticalColumn3->addLayout(box12);
start = new QPushButton("Start", this);
QHBoxLayout *corn = new QHBoxLayout();
corn->addLayout(verticalColumn1);
corn->addLayout(verticalColumn2);
corn->addLayout(verticalColumn3);
QVBoxLayout *rup = new QVBoxLayout();
rup->addLayout(corn);
rup->addWidget(start);
You can simply add a spacer to your layout.
QSpacerItem *spacer = new QSpacerItem(1, 50, QSizePolicy::Ignored, QSizePolicy::Expanding);
box1.addItem(spacer);
Adapt the args or QSpacerItem for your needs, for examle QSizePolicy::Preferred could be better than QSizePolicy::Expanding, and reduce the preferred height (second argument).
Why don't you use the easy way to do that GUI with Qt designer ?
You can try to set QLabel and QLineEdit border:
lmax_kursy->setStyleSheet("border-width:0px");
max_kursy->setStyleSheet("border-width:0px");
or set spacing in layout. First check what is a current value of spacing:
box1->spacing();
If it's 0, try to set negative value like -2:
box1->setSpacing(-2); // or 0 or something else

Resources