I'm using a subclass of QMainWindow, in which I declared a central widget. This widget contains, among other things, a QGridLayout, which holds a set of buttons. The amount of buttons can grow or shrink, depending on the user's input. The spacing is set to zero, so that all buttons are clumped together. By default, it looks like this:
If the amount of buttons is increased, the grid and window will grow too just fine; if, however, the amount of buttons is reduced, it will look like this:
Now I would like to resize the window/layout/widget so that all buttons may use the minimal space. I've tried various things, but all to no avail. I had a look at this and this question, as well at various threads in the Qt board, but none of them worked for me.
My layout is build as follows:
self.grid = QtGui.QGridLayout()
self.grid.setSpacing(0)
hBox = QtGui.QHBoxLayout()
hBox.addWidget(...)
vBox = QtGui.QVBoxLayout(self.widget)
vBox.addLayout(hBox)
vBox.addLayout(self.grid)
self.setCentralWidget(self.widget)
I tried resizing it with ...
self.widget.layout().activate()
self.resize(self.minimumSize())
# self.resize(self.sizeHint())
... and various other methods. I also tried setting the size policy of my window and grid.
You can resize the window to minimumSizeHint() after the number of widgets is changed :
self.resize(minimumSizeHint())
This will shrink the window to minimum size. But you should consider that the minimum size is not computed until some events are processed in the event loop. So when the number of buttons are changed, just process the event loop for some iterations and then resize to minimum.
It's like :
for i in range(0, 10):
QApplication.processEvents()
self.resize(minimumSizeHint())
Another option is to single shot a QTimer which calls a slot in which you resize the window to minimum. This way when you resize the window, the minimum size hint is computed correctly.
Though this was already answered, I found a very simple, elegant solution here. It was hard to find because the question is for this issue in Qt not PySide. You will have to translate it to PySide but it's really simple.
Essentially you want to set the size constraint of the layout you want to have automatically resized to QtGui.QLayout.SetFixedSize like so:
vBox = QtGui.QVBoxLayout(self.widget)
vBox.setSizeConstraint(QtGui.QLayout.SetFixedSize)
The code is not intuitive AT ALL but it works.
for those who, like me, don't immediately get how to use the QTimer:
def function_with_blown_window_size(self)
...
# 1 ms was too low for a refresh -> singleShot timer with 10ms delay
QTimer.singleShot(10, self.window_size_readjust)
def window_size_readjust(self):
self.adjustSize() # worked in my case
#self.resize(self.minimumSizeHint()) # alternative worked equally well
Related
So Qt Designer has this feature where you can resize the window you're working on. And that's fine and dandy, but every now and then, I accidentally drag it, and the window gets larger or smaller than I wanted it to be. The undo action doesn't undo the resizing, so that's a bummer. Also setting max and min sizes for the central widget doesn't do anything to fix this issue.
Is there a way I can have the window size locked?
Here's a demo:
Use QWidget::setFixedSize(w, h) for explicitly set width and height or QLayout::setSizeConstraint(QLayout::SetFixedSize) if you want the fixed size to be determined automatically based on content.
I know you can't use pack and grid together, but why? Why does it raise an error?
_tkinter.TclError: cannot use geometry manager pack inside . which already has slaves managed by grid
The reason is that each one wants to control the geometry of all widgets inside a given container (Frame, Toplevel, etc), and each one will reapply its rules when it detects that a widget it is controlling changes size.
For example, if you start by using pack, pack will add widgets to the window according to its own algorithm. Depending on the size and orientation of the widgets, this may cause the window to grow or shrink and may cause other widgets with the same master to grow or shrink.
Now, if you add a widget using grid, it's going to do the same thing -- it will add widgets using its own algorithm. Like pack, this might cause the window to grow or shrink, or the widget to change size.
Next, because pack is managing some widgets, when it detects that the window has changed size, it will reapply its own algorithm, possibly changing the size or position of some widgets.
Next, because some of the widgets are managed by grid it will detect that they have changed size and it will try to reapply its algorithm. This might cause the window to grow or shrink, or change the size of some widgets.
Next, because some of the widgets are managed by pack it will detect that they have changed size so it will try to reapply its algorithm. This might cause the window to grow or shrink, or change the size of some widgets.
Next, because some of the widgets are managed by grid it will detect that they have changed size so it will try to reapply its algorithm. This might cause the window to grow or shrink, or change the size of some widgets.
Next, because some of the widgets are managed by pack it will detect that they have changed size so it will try to reapply its algorithm. This might cause the window to grow or shrink, or change the size of some widgets.
... and so on until the end of time, or until something causes this cycle to end.
It actually is possible to use both for widgets that share a common parent if you are very careful and know exactly what will happen, but I've never come across a valid reason to do so.
You also absolutely can (and should) use both pack and grid in an application as a whole. Both have strengths and weaknesses. For example, you might use pack to add a full width toolbar, a full width statusbar, and middle section for the rest of the app. If the rest of the app is a form, it might make sense to use grid for the widgets inside the middle section of the GUI.
Is it possible that when a Tkinter window is made bigger or larger, everyhting in the window is scaled?
So all the proportions stay the same but their sizes vary.
Now when the window is resized all the buttons etc stay the same so I disabled resize because there is no point, it just looks bad.
No, it is likely not possible, depending on what you mean by "everything" and what you mean by "scaled". Any widget can be made to stretch to fill its allotted space. Text widgets and canvas widgets, for example, scale nicely. A button or label will fill the space it's in, but the text inside the widget won't change (that is also true of text and canvas widgets).
It's possible to organize your GUI so that when the window resizes, everything remains in its proper place at its original size. Having buttons that automatically scale is not something most people would expect. Disabling resizing usually results in a poor user experience -- users should have the ability to make a window larger or smaller.
I have made a small app with a GUI in python using the wxpython toolkit. It consists of a frame as the top window and 100 StaticText child widgets. I have bind their size events (wx.EVT_SIZE) to a OnResize function which changes their font according to the size of the StaticText widgets. (This helps to increase or decrease the size of the font of the widgets when I resize my frame window accordingly at runtime.)
Now the poblem is that the OnResize function gets called 4 times every time I resize my frame. This considerably slowsdown the startup of my app (and also its resizing.) What I want is that the OnResize function must get called only once.
Is this possible in any way?
Consider an alternative approach.
Keep a variable of the previously processed size. Then, in your size handler, only change the font size if the size of the widget actually changed since the last size event.
def OnResize(self, event):
w, h = size = self.GetSize()
if size != self.previous_size:
# update font size
self.previous_size = size
I'm working with several widgets but the solution just won't come out. What I have is a series of buttons in series of QHBoxLayouts. Some buttons are hidden by default, but they will appear when needed. To solve space issues, all buttons have a minimum and maximum size so they always look well packed. Also I have a QTextEdit, visible by default, which is in a QVBoxLayout with the QHBoxLayout that hold the buttons
So the problem is this: When I hide the QTextEdit and show the other buttons, the window won't resize.
After searching I found that using self.ui.layout().setSizeConstraint(QtGui.QLayout.SetFixedSize) will do the trick, but the problem is that it takes the maximum size from all widgets, therefore I end a huge window. Doing self.ui.layout().setSizeConstraint(QtGui.QLayout.SetMinAndMaxSize) won't resize the window
I already tried using self.ui.resize(0,0), and when doing a self.ui.layout().update() I got False (which I find odd, http://doc.trolltech.com/4.6/qlayout.html#activate), and also tried to override sizeHint() but it keeps using the max size for all widgets.
Is there a way to resize the window and while taking care of the min and max size of a widget?
Thanks in advance
The answer was quite lame... Just needed to change the QVBoxLayout for a QGridLayout and use self.ui.layout().setSizeConstraint(QtGui.QLayout.SetFixedSize)