Qt - How to put existing widgets and qscrollbar inside a QScrollArea - c++

I'm a newbie in Qt.
I'm making a notepad with a ribbon:
And I wanted to make appear a QScrollBar when I resize the Window and I know that I have to use a QScrollArea for it.
My question is, how do I add existing widgets to a QScrollArea and make appear a QScrollBar when needed?

It doesn't look to me like your widgets are aligned in any form of layout. From designer, these button at the top allow you to put widgets in layouts:
Once your widgets are in their necessary layouts, make a new QScrollArea (either by doing QScrollArea *myArea = new QScrollArea() and adding it to a layout manually, or by dragging and dropping it in the designer). It should be as drag and drop as everything else you've encountered so far. You will want to set the vertical scroll policy to never scroll and set the contents margins of the scroll area's widget to 0.
But this begs the question, how savvy are you with GUI programming outside of Qt? You will run into a lot of obstacles from here on out if you can't grasp the concept of layouts and so on.
In case you don't know how layouts work, I suggest you look at the documentation. It's a good rule of thumb to check the docs and look for existing questions before asking. Manually setting the X and Y of widgets is a long-gone practice.

Related

How to create QSplitter ui class via qt designer?

I am new to Qt and I need to implement a monitoring interface with the following considerations:
I have a main window, on which I should put multiple screens, qsplitter appears to be the best solution.
The interface provides user with the option of changing the number of cameras, so QSplitter should be created/re-created during run time.
The problem is that I have too many cameras to pre-define widgets for them, so I need to create QSplitter UI instances dynamically.
The problem is that I can't find QSplitter classes when using Qt Designer and creating QSplitter class programatically is not working as MainWindow has been created through Qt Designer (.ui).
I would like to hear any suggestions regarding this issue, if there are better approaches, please let me know.
In Qt Designer, the QSplitter is not a widget, but a Layout.
Select the widgets you want to include in the two splitter areas, then select Layout from the context menu (right mouse button) - you will find two entries Layout Horizontally in splitter and Layout Vertically in splitter to group the widgets in a vertical or in a horizontal splitter.
QSplitter isn't a strict UI element, it's essentially a parent element that controls child elements. If you want to do it through Designer you'd probably run into headaches, but the basic gist is you select a number of widgets to be controlled by it, and click the Layout Horizontally/Vertically in splitter button which is in the layout buttons group.
What you might be best doing is creating your child elements programmatically, creating your splitter programmatically, adding the child widgets with someSplitter->addWidget(...). In the Qt docs there's some sample code for this:
QSplitter *splitter = new QSplitter(parent);
QListView *listview = new QListView;
QTreeView *treeview = new QTreeView;
QTextEdit *textedit = new QTextEdit;
splitter->addWidget(listview);
splitter->addWidget(treeview);
splitter->addWidget(textedit);
http://doc.qt.io/qt-5/qsplitter.html#details
And if you really want to do it in Designer there's a guide here: http://www.bogotobogo.com/Qt/Qt5_Splitter.php
Although QSplitter is a widget, you can't create one directly in Qt Designer. It is only available for laying out pre-existing widgets - which does not fit your use-case, since you need to create child widgets dynamically.
However, you can work around this limitation by using widget promotion. This is a simple mechanism that allows you to add substitute classes to represent widgets that are not directly available in Qt Designer. The idea is that you add a widget that is most similar to the one you actually want (e.g. a QFrame is most similar to QSplitter) and then promote that to the substitute class which you have defined in your own header file. When uic finally generates the code, it will use your substitute class instead of the class of the widget added in Qt Designer (which just acts as a placeholder).
Note that when you create your substitute class in the Promoted Widgets dialog, the base class should be a QFrame, not a QSplitter. This is because you are extending a QFrame (i.e. your placeholder widget), rather than a QSplitter. Of course, you can define your substitute class to be anything you like.
Image is easier to understand.

Allow user to resize widgets at runtime in QT5

I have an application written in C++/QT5 with a QListView widget within a QHBoxLayout within a QGroupBox. There is also a QTabWidget in the main window. I would like the user to be able to resize the QListView widget by clicking and dragging and for the other items to automatically resize themselves accordingly.
I feel like this should be something that is easily done within the framework of QT5, but I can't for the life of me find a way. Even having a border on the list view that I can resize within the code of my application would be a start.
Thanks to jhnnslschnr I was able to solve this via the QSplitter widget. If you're using QtCreator as I was, you can use QSplitter simply by Ctrl-clicking the widgets you want in the splitter and then selecting "Lay out horizontally (vertically) in splitter". The user can now select the partitioning at run-time.

Make QVBoxLayout scrollable using QScrollArea

I have a QVBoxLayout which has content dynamically added to it. I simply want to make that layout scrollable as the content overflows. What is the correct way to achieve this in Qt Designer, or do I need code as well?
I've seen a mixed bag of examples, but none get low level enough to show exactly what needs to be done.
Thanks!
I have found a solution by doing the following.
In Qt Design view, create a QScrollArea. Then drag your existing QVBoxLayout into the QScrollArea. Right-click inside the QScrollArea (not inside the layout) and select "Apply Layout". Then choose a layout (I chose a vertical layout). That's it.
Hope this helps!

Qt window resize problem

I am having a problem redrawing a QWidget window after its size has been adjusted. I have tried update(), repaint(), adjustSize(), but all seem to suffer from the same thing: only part of the window is redrawn, resulting in the window frame on the bottom and right sides to not show. The window is also not resized entirely.
Just in case it makes a difference, the window is in a QMdiArea.
Thanks.
// ... some subwidget resizing and moving.
calibrationWindowUIs[activeWindow].layoutWidget2->move(QPoint(oldXLeft, 30 + height + 21));
calibrationWindowUIs[activeWindow].layoutWidget1->move(QPoint(oldXRight, 30 + height + 21));
// Set window size.
calibrationWindows[activeWindow]->setMinimumSize(calibrationWindowUIs[activeWindow].tabWidget->geometry().width() + 40, calibrationWindowUIs[activeWindow].tabWidget->geometry().height() + 40);
calibrationWindows[activeWindow]->update();
Note: I'm new to Qt; perhaps I'm doing something wrong with layouts?
Edit: I may have not given enough information. Alright, to be quite honest, I still have to delve deeper into layouts and related material. What I had tried to do here was to use Qt Designer in order to design the window. I've done what perhaps amounts to a stupid mistake: I didn't use an overall parent layout for the entire window, but hacked it with a couple of smaller layouts that I therefore have to move about and resize individually. See the Qt Designer screen (the red rectangles are the sole layouts): .
What is happening is that in the frame to the right, I am playing a video clip that can be of various resolutions. I want the frame to resize depending on this resolution, which also means that the buttons and window have to move/resize accordingly. That is where the window resize comes in. I'm sure there is a more elegant solution than what I am doing here, but I am trying to handle several other scenarios here and hence the lack of quality of code.
The result is that when I load a clip, the window attempts to resize, but does so badly; the following is the result:
If the window is dragged, it 'pops' into its correct size; in the meantime, however, it just looks ugly.
A couple further questions: do you use the Qt Designer to design your UIs? I found that programmatically you can achieve much better control of your interfaces. One thing which I could not do in the designer was to have a layout parented by the main widget, i.e. the equivalent of having the following bit of code:
QVBoxLayout* layout = new QVBoxLayout;
this->setLayout(layout);
A layout placed in the designer always seems to create this 'layoutWidget' subwidget, which the layout you placed is then parented to. Any way around that?
We use a mix of designer and code to create layouts, the Qt layout system can be very unintuitive at times. But I would probably not layout a full series of tabs in one designer ui file, i would make each tab each own widget and then assemble them either through code or in the designer by promoting to custom classes. This gives you better separation of responsibilities, by putting all the functionality of all the tabs into one file you almost guarantee a large unwieldy class.
When a widget has child widgets in designer you can assign a layout to it by adding it from the context menu. Make sure nothing is selected and click on the background of the widget in which you want to create a layout, select the layout and all of the widgets children will be assigned the layout.
What does help is creating hierarchies of layouts. Looking at your first screenshot, i would probably use a vertical layout with spacers on top and bottom for the items on the right, an horizontal layout with spacers left and right for the button bar and a grid layout for all the items together. Without the spacers your items will extend when the window grows. The spacers will let you control the behavior under resizing better.
you are calling setMinimumSize(). That's fine, but you should also call resize()

How should I use a QGraphicsScene with layouts and widgets

I'm creating some graphic data displaying widget in Qt4 and I was tempted to use the QGraphicsScene for it, create QGraphicsItems for the data items etc.
However, I wanted to add some layer of controls (eg. scrollbars, zoom+other buttons - I want to make it in a similar style as eg. Google Maps, that is, the data would be displayed all over the widget, and the buttons would be shown atop of them) to the widget. So I thought it might be feasible to add them to the scene (perhaps as a child of a QGraphicsGroupItem that would be shown over the data). But I want them to move & resize when I resize the whole widget, so I should use a QGraphicsLayout for managing them. But at this point, I discovered things are pretty complicated.
The problem is that when using QGraphicsLayout, the following constraints hold:
Only a QGraphicsWidget can be managed by a layout
QGraphicsLayout can only be used to manage children of a QGraphicsWidget
Which means that I would have to create my controls as QGraphicsWidgets, add a top level QGraphicsWidget to the data widget, and manage the size of this top level widget myself.
So I want to ask:
Wouldn't a classic approach (ie. use plain old widgets for all controls, and use QGraphicsScene only for displaying the data) be more reasonable?
Is there any advantage in using QGraphicsScene in this case (performance or simplicity...)?
How should I use QGraphicsScene to exploit its strengths?
Since Qt 4.4 you can embed classic widgets in a QGraphicsScene by using QGraphicsProxyWidget :
QWidget *widget = new QWidget;
QGraphicsScene scene;
QGraphicsProxyWidget *proxy = scene.addWidget(widget);
If you think that QGraphicsScene (or whatever other widget you have) is appropriate for most of your display, use that. What we have done in the past for somewhat similar things is to make a custom widget that inherits (one way or another) from QWidget, and put the control widgets in a layout on top of that widget. This means that the whole widget is drawing whatever it is you want drawn, and the control widgets are on top of that, resizing as the whole widget is resized.
Alternatively, a couple of times we've had layouts that were just a bit too complicated for the layout widgets to easily handle. Rather than create a custom layout, we just positioned them with no layout, and moved them in code on the resize event. It works just as well.