Creating a scrollable window without Layouts - c++

I am trying to achieve something what, I thought, would be a super easy thing to do. But for some reason QtDesigner is driving me crazy, it simply won't work...
I created a GUI and freely arranged different elements in the window, without layout or anything like that. At some point there were to many elements, so all I wanted to to, was to make it scrollable up and down, to see all elements.
So I added a ScrollArea in QtDesigner and added all elements as children of this ScrollArea (which btw also was a pain in the ass, because apparently drag and drop in the Object viewer is not a thing, and editing the .ui file by hand, is also not allowed... great).
So the result I have now is the following:
before resize - no scrollbar, elements at bottom inaccessible
resized vertically - some stuff still snapped off at the bottom
So as you see, although I created a ScrollArea... There is no scroll area. So I googled a little bit and found out that you can add layouts to your scrollarea, and yey, finally, a scroll bar! But how in this world am I supposed to arrange the elements in the way you see in the screenshots, with layouts. They are so super restrictive.
How am I supposed to simply get a vertical scrollbar, without this restrictive layout stuff?!
Here is how my object viewer looks
And here is what is called upon GUI creation:
ui->setupUi(this);
//setCentralWidget(ui->scrollArea);
//ui->scrollArea->setWidgetResizable(true);
I tried it with, and without the commented lines. No scrollbar, no matter what I do.

Try this to fix it:
In Qt Designer:
Select QScrollArea object.
Uncheck the QScrollArea properties widgetResizable.
In C++:
// If you want to set `widgetResizable` programmaticly
ui->scrollArea->setWidgetResizable(false); // Optional if you did it in Qt Designer
ui->scrollArea->widget()->adjustSize();

Related

QGridLayouts within a QGridLayout

Is it possible to have QGridLayouts within another QGridLayout? I have been trying to do this using the UI designer, so that I can resize all QGridLayouts uniformly.
This is for an Ultimate-Tic-Tac-Toe game I am creating for fun.
Here, I have nine QGridlayouts. I want to group them together. If I want to expand the boxes, I have to go through each one and expand them. Or I have to copy/paste the first box and make sure they are all aligned again.
I tried selecting all of them and clicking Lay Out in a Grid , but that messes up how they are displayed. Especially the lines that separate the layouts. Am I not doing this correctly?
This just looks weird:
Yes, there is no any problems inserting QGridLayout into another QGridLayout. Here is a demonstration how it can be done in the designer.
Pay attention that there are no any lines when you open the widget in the Preview: they are visible only for design purposes.
Buttons are added to the layouts just to see how they are places in the Preview.

Qt - Make QMainWindow to non resizible in Qt Designer

Is it there a way to set a QMainWindow to be non-resizible in Qt Designer? I am seeing lots of coding examples but I want to do as much UI customization in Qt Designer as I can. So far I can only get this by setting the minimum size and maximum size to be equal, but still there is the resize arrow in the corner of the window and a "maximize" button on the top of the window.
When you select the QMainWindow, the properties of the object does contain a field for sizePolicy, both horizontal and vertical, as mentioned by the answer of #jester and you can set those to fixed.
I have found that doesn't always work and was never sure why (perhaps to due to layouts), but as you've found out, if you set the minimumSize and maximumSize fields to the same value, it does what you want.
As for the resize arrow and maximize button, I have never been able to do that from Qt Creator (designer), so I would say it's not possible. However, just one line of code is all you should need in the constructor of your class: -
setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
By default, the window flags include Qt::WindowMaximizeButtonHint. By setting the above flags, you're stating that you want to customise the window to include the specified elements. This will also remove the minimise button, so if you want that too, you should add Qt::WindowMinimizeButtonHint
I am not using Qt Designer; I am just writing a subclass of QMainWindow made from scratch. The solution I found for having a non-resizable window is to call setFixedSize on the QMainWindow after you have set up all your widgets and layouts. If you have set things up well, then you don't have to pick a size manually; you can just get the size from sizeHint. The line of code I used inside my subclass of QMainWindow is:
setFixedSize(sizeHint());
I tested this in Qt 5.5 on Windows 8.1 and everything looks fine: the maximize button gets disabled but the other buttons are still there, and the cursor does not indicate the possibility of resizing when the user moves it to the border.
use the setFixedSize property for the QMainWindow. In designer, if I remember correctly, you can set the horizontal and vertical sizePolicy to Fixed.
Sadly there is no option to do that; in VS you may find an option in the editor, to remove the mouse trigger that resize the window; but for some reason, QT5 does not have one.
I tried to use sizePolicy and set it as fixed for mainWindow; but this does nothing for both the horizontal and vertical policy.
To solve the problem, I did set my mainwindow minimum and maximum size as the same values; and when you run the application, the mouse cursor won't be enabled for resizing.
It is an ugly way to do something so simple, but this is the only way I found in QT designer, without use code.
I solved the problem of Qt5 which is displaying mouse arrow resize window even with window having fixed size, but in Python, but you can make modifications for C++.
MainWindow.setWindowFlags(QtCore.Qt.MSWindowsFixedSizeDialogHint)
It's an old post but I want to help if someone need it.
I found a way (not so beautiful) but it works directly from QTDesigner.
You can lock the resize by writing the values of height and width also inside "MinimumSize" and "MaximumSize" property.
Oviously also set "Fixed" on vertical and horizontal as told by other users.
This will remove the button to enlarge the window.

Resizing a gtk2 widget with the mouse inside an area (window) with scroll?

I wanted to develop a widget container (still on python 2.7 and gtk2), which would be placed in a scrolled window, and could be freely moved and resized in the window, such that: click & drag within the widget would move it inside the window; and when widget's corners / edges are visible in the window, it would expose drag handles for resizing - otherwise, if it is bigger than the window area, it would scale up and down (zoom in and out) on middle-click.
Of course, I want to keep the amount of custom coding of this widget to a minimum, so I though looking into what's available in gtk2 first. It turns out, the only element exposing resize drag handles is gtk.Window - and at that, only if it is a main (or root) window; otherwise, if a window is placed inside a widget, its size is apparently set by the widget, and so there are no drag handles (not menus, titlebars etc). I was wandering why this is - and it seems it is due to multiple document interface (MDI) being considered evil by gtk developers, see e.g. Re: [gtk-list] Resizing widgets with a mouse or Does GTK support MDI? - Linux/BSD whirlpool.net.au.
Just to demonstrate the behavior that I want, I used a PyQt4 code from Python PyQt/PySide QMdiArea subwindows scroll not working in TabbedView - Stack Overflow, since as it turns out, Qt does have an MDI area. So here's the gist of it - if a corner is visible, a resize drag handle appears, and resize drag action can be started:
When you thus drag the corner outside of the window - the scrollbars automatically indicate the new size/position of the inner widget (note the window got also moved a bit in this screenshot below, that was manual and unintended):
Again, I don't really need a window (as in titlebars, menus) - just a widget container that would behave in this way, so I could put e.g. a table (e.g. TreeView) or an image in it, as the situation demands - and at least not worry about recalculating the "outer" scrollbars (naturally, I'd expect I'd have to code the rest of my custom behavior myself). Also, I just need a single widget placed in a window like that for now (so no "multiple document"s).
While Qt seems to offer this in a way, I don't have the possibility right now to get into it to the level of doing something like this; and the same goes for WxWindows (see e.g. wxPython-users - How to resize Widgets? - possible, but as there is no code there, I cannot see if geometry calculation coding is required or not).
So I was wondering - is there a widget I may have missed, that would implement the above behavior, and that I could take as a base for customization? If not, what options do I have to implement something like the above on gtk2 (eventually with Python)?
I'm not sure this would work, but I suggest looking into GtkOffscreenWindow; put the inner widget into that, and render it to a GtkDrawingArea inside a GtkScrolledWindow. This would probably make the scrollbars behave properly depending on the size of the drawing area.
What you won't get:
window titlebars, you'll have to render those yourself because GTK doesn't know about them, they're part of the window manager. (Note, the inner window in the Qt example has a different titlebar than the outer window - I suspect this is the same thing.)
drag handles to resize the window, you'll have to code those yourself, as you expected.
You might also want to look at how the Glade GUI designer does this.

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()

QListWidget that resizes instead of scrolls

How do you change the behavior of a QListWidget so that it resizes its height instead of choosing a (seemingly arbitrary) height and adding scrollbars? See screenshot:
The QListView's should fill up as much space horizontally as they can (creating as many "columns," if you will.) Then they wrap and make as many rows as necessary to fit all the items. These calculations should be adjusted as the window is resized. This is all working fine.
However, what I want to happen is that instead of the height staying the same, the QListView should grow or shrink vertically and never need any scrollbars. The scrolling, if necessary, will be handled on the parent QWidget that hosts all of the labels and lists. It seems like once the height of the QListWidget is established (not sure where its default is coming from), it never changes. It is too big in some cases (see second "Test" list above) and too small in others (see first "blank maps" list above.)
The layout above is nothing surprising: two QLabel's and two QListWidget's in a QVBoxLayout. Here are the properties I have set on the QListWidget's:
setMovement(QListView::Static);
setResizeMode(QListView::Adjust);
setViewMode(QListView::IconMode);
setIconSize(QSize(128, 128));
(I already tried setting the horizontal and vertical scrollbar policies, but that just turns the scrollbars off, clipping the content. Not what I want.)
Maybe you could this without using QListWidget. The Qt's examples contain a new layout class, QFlowLayout, which could be useful. With the following kind of widget hierarchy you could get multiple groups with labels and they all would be inside one QScrollArea.
QScrollBox
QVBoxLayout
QLabel "Blank maps"
QWidget
QFlowLayout
your own widgets showing map images and labels
QLabel "Text"
QWidget
QFlowLayout
your own widgets
The problem is that this kind of solution would create much more widgets than QListWidget based solution. So if you have hundreds of items in your list, this might not be the best solution.
There is a protected member function called contentsSize() in QListView. It is used to calculate the required minimum(), maximum(), and pageStep() for the scrollbars (as mentioned here).
Can you subclass the QListView class and make use of that information? I suggest you recalculate the size of your widget in the same function where you add contents to it. While somewhat lacking elegance, this appears to be a pretty reliable solution.