I'm working on a C++ Qt GUI to remote control a ROS robot. The major part of the GUI is gonna be showing multiple camera images. So far I put a QGridLayout as central widget in which I added four QLabel. I want to show the camera installed in the front of the robot in a bigger label than the ones on the side or in the rear.
Camera layout:
I have tried to use this function
grid->addWidget(labelMid, 0, 5, 10, 6);
where the last two numbers indicate the rows and columns the widget is spanning. However that was not exactly convincing as the rows and columns don't seem to all have the same width/height.
Stretchfactors seem to be only existant for whole rows or columns not just certain cells so that is no option either.
Does someone know a way to set this kind of layout? I don't have to necessarily stick to the gridlayout.
Related
I'm working on application for embedded and we have 256x64 grayscale screen. Qt 5.3 perfectly renders on that screen with -platform linuxfb option. Obviously, we save every pixel of space, so I faced with trouble: Qt Designer adds excess 1 pixel spacing for every layout element deeper in hierarchy. So they accumulate for the most deep widgets. More precisely, for some reason child element of layout components gets coordinates (1,1) relative to parent. So, it's true for every widget except for root widget. Picture below demonstrates accumulated spacings (thin and thick red lines), and (1,1) coordinates of the very first child widget.
I believe it's Qt behavior itself, not just Qt Designer issue (not tested yet). But I can't work further even if it's shown in Designer only: I need to have pixel-exact view while designing.
Of course, every spacing and margin of every component in form set to 0.
Manual coordinates assigning (from code) eliminates the problem of course, but I need to generate code by uic.
So, my question is: how to avoid such spacings? Fixing Qt core sources can be (hard) option too, since anyway we recompile Qt for the project.
Mirror post on Qt forums
Thanks.
Ilia.
If you select Form > View Code, you can see that the geometry is not actually used for widgets which are inside a layout. So the numbers you see in the Property Editor are purely informational and have no relevance to the eventual code that is generated from the ui file (which is why they are greyed out).
The one pixel offset is there because Qt Designer needs space to draw the red boxes around layouts. They have to be be represented somehow, so I don't see how this can be avoided given the way Qt Designer currently works. If you want a more accurate reprentation of the final results, I suppose you will have to show a preview.
There is a facility in Settings > Preferences > Embedded Design that allows you to specify device profiles (which determine things like style, font, and screen resolution). This will add a new entry to the Preview In menu, which should allow you to refine the accuracy of the previews even further.
This is a screenshot of a QFormLayout holding a series of widgets. Note that the top and bottom input widgets are not horizontally aligned to the middle two rows. Note also that the labels on the left are not vertically aligned to the middle two rows.
The difference is that the top and bottom widgets are plain QLineEdit and QTextEdit widgets, the second row is a QWidget with a QHBoxLayout holding a QSpinBox and QDateTimeEdit, and the third is a QStackedLayout containing QWidgets each with a QHBoxLayout and API-supplied widgets inside those.
It looks like these middle two have extra margins. I can (partially) improve the situation by calling QLayout::setContentsMargins on the plain QWidgets' layouts. In fact, in the image above I already have, without that it's worse.
I haven't interfered with styles in the application, it's all system-default. This seems to affect Qt5 on Ubuntu 15.04, I don't think I saw this back when it was a Qt4 application.
I tried setStyleSheet ("QWidget {margin:0;}") in the top-level widget, that introduced all sorts of problems. I also tried the variation setStyleSheet (".QWidget {margin:0;}") but that had no effect. QLayout::setSpacing also had no effect, and setting padding:0 in the stylesheet doesn't fix it either.
Nothing I've tried seems to bring the spacing around these custom-layout QWidgets in line with the API-supplied widgets.
What have I missed? Thanks.
What you observe is both the struggle of multi-platform ui and the simple fact that some widgets are horrible. Given a limited amount of time and a big task, dev teams will not treat fairly the set of features. Powerful widgets and layouts like standard widgets, QGridLayout, will be maintained day and night to be defect free while legacy widgets like QStackedWidget will be pushed at the bottom of the maintenance queue.
I tried to reproduce your issue using designer alone and here is what I got (Qt 4.8) :
What you can see:
The second line with a widget container has great marging
The third line doesn't even show the combo box (I swear it's there!!).
My two cents :
There is a difference in behavior in the second row. Because I used Qt4 and you Qt5, and we both set the QHBoxLayout margin to zero then it means there is a potential regression at play, either in Qt5 or the linux implementation. So this confirms what you suspected.
QStackedWidget is horrible. It is the usual widget provided to give quick and basic functionality rather implementing the real deal. Here it would be a widget with a QStackedLayout. Like I said I suspect those kind of widgets to receive less love when big development efforts are required.
In these situations, use QGridLayout instead of a QStackedLayout of widgets with layout of widget. It will solve the issue of labels not being aligned. Difficult to set up at first but the result is usually neat.
By the way, I switched to a widget with a stackedlayout and here is the result :
I want to create a flexible layout, where the User can resize Widgets, but still give a good default layout. I'm using the Qt Designer for everything.
As a minimal example I used a simple Windows with a Widget and a plainTextEdit. The later one seems to cause the problems, which is why I choose it. At first I built it without the Splitter which worked just fine. The Stretching factors are 1:1 by the way.
Now I put both widgets in a Splitter (by breaking the main layout, putting both widgets in a Splitter and setting a new layout to the main widget). Resizing still works but the stretching factors behave weird:
The PlainTextEdit seems to take up far to much space. The Stretching Factors are still at 1:1. I found a workaournd, by changing the stretching of the upper widget to a much higher value (in this case 9:1), which looks good again:
So my question is: Why do the stretching factors begin to behave weird when I put the images in a Splitter? And how can I solve this without using arbitrary guessed stretching factors?
QSplitter::setSizes() can be used to set relative sizes. According to the documentation, "any additional/missing space is distributed amongst the widgets according to the relative weight of the sizes".
In this case, it is a bit ugly, since you have to add this in your code rather than editing your layout in QDesigner (normally, you would want to define your layout only at one place), but still it is quick and works:
MyWindow::MyWindow(QWidget* parent):
QWidget(parent)
{
m_Ui.setupUi(this);
m_Ui.splitter->setSizes({2000, 1000, 1000});
However, I had to use big numbers (instead of {2, 1, 1}), maybe because at this point, the window is not completely set up yet (apparently, Qt is not a big fan of RAII...). Also, this kind of notation works probably only with a recent C++ version, otherwise you can also define the QList in some extra lines.
I've a QMainWwindow, and I've fixed its size.
i.e. I've set Minimum and maximum size of the window to the same number.
Could anyone tell me whether this will be a problem if I'm to use this in another screen with a different resolution, and if so, how am I to handle it?
Kindly advise, and also if there's another way ( perhaps more elegant) to set the size of the QMainWindow.
UPDATE :
I have a QMainWindow with a QTableView as a widget, amongst others. When I expand the main Window, the tableview does not, and it leaves an ungainly blank space, so I fixed the size.
If I were to make it resizeable, how do I expand the QTableView widget, alongwith the QMainWindow. I have a Central Widget, this widget has a vertical box layout, and to this layout I've added the 3 widgets, one with QGridlayout, one horizontal line, and the other QTableView. The QTableView, on its own, is not inside a layout.
I'd imagined this would be sufficient to expand the table too, once QMainWindow were expanded, or reduced, but it doesn't happen.
How do i go about it, i.e., expanding the QTableView as well?
Thanks.
It will be a problem if you fix the size to one that is larger than the screen can handle. There are various ways to scale the size of a window according to the screen size. I recommend using QApplication::desktop(), which will return the desktop widget (you may need to #include <QDesktopWidget>. Note that this widget can actually encompass multiple screens, so if you just want the current screen, you can just do:
QRect screenGeometry = QApplication::desktop()->screenGeometry();
You could alternatively use QDesktopWidget::availableGeometry().
It is worth mentioning that among Qt users, I think there is a general dislike of fixed size windows. Most recommend taking full advantage of the Qt layout system, which provides lots of flexibility for resizing windows. I'm not saying you should definitely do this, because all projects are different, but it could be worth looking into.
What I'm trying to achieve is that a widget could exist in two different layouts, in this case in QHBoxLayout and in QVBoxLayout. I'm implementing a system which dynamically switches between the two layouts when a device's screen orientation changes.
Currently I'm creating, let's say a complex composite widget called MyWidget and adding it into a two different layouts:
MyWidget *wgt = new QWidget();
QVBoxLayout vlayout;
QHBoxLayout hlayout;
vlayout->addWidget(wgt);
hlayout->addWidget(wgt);
Now imagine that both layouts are hosted within a 'root' layout, and that this root layout can resize into a more wide than tall 'landscape' mode, and into a more tall than wide 'portrait' mode.
The MyWidget shows correctly in only the first layout it is added into, and when the layouts are switched, it shows all wrong or not at all.
I don't know if I'm making any sense here, but this is my problem. Maybe when the switch event is called all child widgets and layouts should be resized, so it would always look right. Only problem is that I don't know how.
This isn't a general solution for changing layouts, but an easy solution in your case: Just change the boxlayout's direction.
hlayout->setDirection(QBoxLayout::TopToBottom);
// now your hboxlayout works as vertical layout
hlayout->setDirection(QBoxLayout::LeftToRight);
// and now it is horizontal again
This isn't particularly easy to do, but is possible.
First of all, I'd recommend that you actually create two different widgets, one for the vertical and one for the horizontal, and manage things that way. If the source data is properly separated from the UI class, you should be able to do so without too much trouble, but by incurring some memory overhead.
One way to do as you desire would be to completely remove the widgets from one layout and add them to the other when you need to change the arrangement on the screen, and change the layout that is added to the widget. This should cause the same widgets to be drawn in a different way.
A different, more intricate way of handling this (although potentially more efficient) would be to write your own layout and have it handle rearranging widgets based on the orientation change.