Small panel at the bottom of a QTreeWidget - qt

I'm using QT 5.4.2 and trying to create a small panel at the bottom
of a subclassed QTreeWidget.
Here is the code:
void HmiScenarioAutoscriptPanel::searchEmitter() {
QWidget *child = new QWidget(ui->emitterTreeWidget);
//QMainWindow* child = new QMainWindow;
QLabel *labelSearch = new QLabel("Search");
QLineEdit *lineSearch = new QLineEdit();
lineSearch->setFixedSize(100, 20);
QHBoxLayout* layout = new QHBoxLayout(ui->emitterTreeWidget);
layout->setAlignment(Qt::AlignBottom);
layout->addWidget(child);
layout->addWidget(labelSearch);
layout->addWidget(lineSearch);
}
The label and search field correctly appear at the bottom of the tree,
however the fields overlap with the tree nodes (see image below).
Any idea why this behavior?
Ciao
Alf
enter image description here

It is not recommended to set layout on the tree widget. It is like other controls like a button, label etc..
I see that you are using designer. Add a blank widget (searchWidget) under the tree widget and then
void HmiScenarioAutoscriptPanel::searchEmitter() {
QWidget *child = new QWidget(ui->searchWidget);
//QMainWindow* child = new QMainWindow;
QLabel *labelSearch = new QLabel("Search", searchWidget);
QLineEdit *lineSearch = new QLineEdit(searchWidget);
lineSearch->setFixedSize(100, 20);
QHBoxLayout* layout = new QHBoxLayout(ui->searchWidget);
layout->setAlignment(Qt::AlignBottom);
layout->addWidget(child);
layout->addWidget(labelSearch);
layout->addWidget(lineSearch);
}
Just out of curiosity, why don't you add these using the designer as well?

Related

Can we shift widget between the cells of a table widget

I've created a a widget in which I've placed two buttons using a layout and placed it inside a table widget's cell. The thing is that I'm changing the size of the table and I want to shift the placement of the widget without deleting them and re-initializing them from the beginning because I already assigned them actions on click (I think that the application would crash in this situation)
Code:
btn = new QPushButton[horzHeaders.size()];
btn[j].setParent(ui->tableWidget);
btn[j].setIcon(QIcon("./save.png"));
btn[j].setVisible(true);
btn_Load = new QPushButton[horzHeaders.size()];
btn_Load[j].setParent(ui->tableWidget);
btn_Load[j].setIcon(QIcon("./upload.png"));
btn_Load[j].setVisible(true);
lay = new QHBoxLayout[horzHeaders.size()];
lay[j].addWidget(&btn[j]);
lay[j].addWidget(&btn_Load[j]);
QWidget *w = new QWidget[horzHeaders.size()];
w[j].setLayout(&lay[j]);
ui->tableWidget->setCellWidget(j,vertHeaders.size() - 1, &w[j]);
You can add and remove widgets from a layout anytime you want
QWidget *widget = new QWidget();
QPushButton *button = new QPushButton();
QHBoxLayout *Hbox = new QHBoxLayout();
QVBoxLayout *Vbox= new QVBoxLayout();
Hbox->addWidget(button);
// use it till the window is resized
//and then check with an if-statement if the window is resized or not
Hbox->removeWidget(button); // remove from the button from layout
layout()->removeAt(widget); //remove the widget's current layout
Vbox->addWidget(button); // add button widget to vertical layout
widget->setLayout(Vbox); // Give it a new layout
widget->setLayout(Vbox);
If this didn't answer your question then ask in the comments.

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

How to add widgets to QToolbox item

I need to auto generate some UI forms in code to display message contents.
I want to use QToolbox, with an item for each message type. I then want to add labels and line edit to the contents of each tab, depending on the message protocol. I cannot seem to programaticaly add widget items to the toolbox item.
Below is my current code segment. The ui->frame is just a container for the toolbox. I will worry later about layout.
In my code, I create a frame and then some labels with parent set to the frame. Then I add the frame as an item to the toolbox.
QToolBox *qtbMainToolbox = new QToolBox(ui->frame);;
qtbMainToolbox->setGeometry(0,0,2000,900);
QFrame *frm1 = new QFrame;
QLabel *lbl1 = new QLabel(frm1);
QLabel *lbl2 = new QLabel(frm1);
QLabel *lbl3 = new QLabel(frm1);
QLabel *lbl4 = new QLabel(frm1);
iRetVal - qtbMainToolbox->addItem(frm1 ,"Test");
There is no visible element in your widgets; icon or any text.
You have to Set icon or Text to Your QLabel.
QToolBox *qtbMainToolbox = new QToolBox(ui->frame);;
qtbMainToolbox->setGeometry(0,0,2000,900);
QFrame *frm1 = new QFrame;
QLabel *lbl1 = new QLabel("Hello World",frm1);
iRetVal - qtbMainToolbox->addItem(frm1 ,"Test");
try above code.

QDialog and scroll areas: how to merge them?

From the ImageViewer example:
ImageViewer::ImageViewer()
{
imageLabel = new QLabel;
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
scrollArea = new QScrollArea;
scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setWidget(imageLabel);
setCentralWidget(scrollArea);
resize(500, 400);
}
I need the scroll area to appear not in the central widget, but in a dialog inside the central widget.
I tried with:
ImageViewer::ImageViewer()
{
QImage image(fileName);
plotImg = new QLabel;
plotImg->setBackgroundRole(QPalette::Base);
plotImg->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
plotImg->setScaledContents(true);
plotImg->setPixmap(QPixmap::fromImage(image));
scrollArea = new QScrollArea(this);
scrollArea->setWidget(plotImg);
scrollArea->setBackgroundRole(QPalette::Dark);
printAct->setEnabled(true);
fitToWindowAct->setEnabled(true);
if(!fitToWindowAct->isChecked())
plotImg->adjustSize();
return true;
}
From this code, I get the dialog inside the central widget. This dialog, however, does not contain the image itself, but the scroll area which contains the image.
I would like the dialog and the scroll area to be "the same thing"...
Easy. Don't use a dialog, simply have ImageViewer inherit directly from QScrollArea.

Displaying Images Side-by-Side in Qt with Scrollbars

I'm a Qt newbie. I want to display 2 images side-by-side using Qt. Using Qt's Image Viewer Example, I want to add another scrollable image display, such that both images are displayed side-by-side.
The example code has this snippet for the ctor:
ImageViewer::ImageViewer()
{
imageLabel = new QLabel;
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
scrollArea = new QScrollArea;
scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setWidget(imageLabel);
setCentralWidget(scrollArea);
...
If I understand it correctly, I want to get imageLabel to be only half width of the screen while another QLabel is displayed on the other half.
How can I do this?
Thanks.
If I understand correctly, this here should suffice:
// Left image
imageLabelLeft = new QLabel;
imageLabelLeft->setBackgroundRole(QPalette::Base);
imageLabelLeft->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabelLeft->setScaledContents(true);
scrollAreaLeft = new QScrollArea;
scrollAreaLeft->setBackgroundRole(QPalette::Dark);
scrollAreaLeft->setWidget(imageLabelLeft);
// Right image
imageLabelRight = new QLabel;
imageLabelRight->setBackgroundRole(QPalette::Base);
imageLabelRight->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabelRight->setScaledContents(true);
scrollAreaRight = new QScrollArea;
scrollAreaRight->setBackgroundRole(QPalette::Dark);
scrollAreaRight->setWidget(imageLabelRight);
// Do the layout
QWidget *centralWidget = new QWidget;
QHBoxLayout *layout = new QHBoxLayout(centralWidget);
layout->addWidget(scrollAreaLeft);
layout->addWidget(scrollAreaRight);
setCentralWidget(centralWidget);

Resources