[Qt-interest] Dynamic Layout Management

John Posner jjposner at optimum.net
Tue Dec 29 19:43:09 CET 2009


Frank Mertens wrote:
> Shawn Badger wrote:
>   
>> Hi,
>>
>> I am running into a problem that I can't seem to find an answer to.
>> My scenario is simple.  I have a central widget that contains two
>> child widgets in a horizontal layout, like so:
>>
>> ------------------------------
>> |         |                           |
>> |         |                           |
>> |    1   |            2             |
>> |         |                           |
>> |         |                           |
>> ------------------------------
>>
>> I need the ability to show only widget #1, or #2, or both at the same
>> time, and have the window grow/shrink accordingly.  When I hide #1 and
>> then call resize(0,0), the window correctly shrinks to the size of #2.
>>  And when I show #1, it grows back to the size of #1+#2.  However, if
>> I hide #2, I cannot get the window to shrink down to the size of #1.
>> It's like the size hint does not get updated correctly.
>>
>> Does anyone know how to get the behaviour I am looking for, without
>> having to force a fixed geometry?
>>
>>     
>
> Yes, Qt4's layout system has bugs.
> Maybe try a QSplitter, at least it keeps the sizes correctly
> and if it doesn't you can call setSizes().
>   

This Python code implements four child widgets, and handles their 
removal (via click) correctly. Clicking the frame background restores 
the removed widgets, in random order. As far as I can tell, all four 
statements in ClickLabel.mousePressEvent() are necessary.

#----------------------
import random
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class ClicklLabel(QLabel):
    """
    label that disappears when clicked
    """
    def __init__(self, color, wid, hgt):
        super(ClicklLabel, self).__init__()
        self.setText(color)
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: %s;" % color)
        self.setMinimumSize(wid, hgt)
        self.setMaximumSize(wid, hgt)
       
    def mousePressEvent(self, evt):
        """
        remove label from top-level window's layout
        resize top-level window
        """
        topwin.layout().removeWidget(self)
        self.setParent(None)
        app.sendPostedEvents()
        topwin.resize(1,1)

class ClickFrame(QFrame):
    """
    click frame background to restore removed
    labels, in random order
    """
    def __init__(self):
        super(ClickFrame, self).__init__()
    def mousePressEvent(self, evt):
        random.shuffle(widgets)
        map(topwin.layout().addWidget, widgets)       
   
app = QApplication([])
topwin = ClickFrame()
topwin.setStyleSheet("background-color: #ddeeff")

# create label widgets
widgets = [ClicklLabel("cyan", 150, 150),
           ClicklLabel("red", 75, 50),
           ClicklLabel("green", 200, 200),
           ClicklLabel("yellow", 50, 75)]

# lay them out horizontally
topwin.setLayout(QHBoxLayout())
map(topwin.layout().addWidget, widgets)

topwin.show()
app.exec_()
#----------------------


-John




More information about the Qt-interest-old mailing list