【问题标题】:Issues with sizing when I add widget to Vbox Layout将小部件添加到 Vbox 布局时出现大小问题
【发布时间】:2019-02-21 21:17:44
【问题描述】:

我遇到了 QLayouts 的问题。

class welcomeWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.initText()
        self.organize()

    def initText(self):
        self.welcome = QLabel("Welcome to Name!", self)
        self.info = QLabel("This program allows you to....", self)
        self.message = QLabel("First, you must enter some data...", self)
        self.proceed = QLabel("Click on 'Next >>' to proceed.", self)

    def organize(self):
        vbox = QVBoxLayout(self)
        scroll = QScrollArea(self)
        vbox.addWidget(scroll)
        wid = QWidget(self)
        vevobox = QVBoxLayout(wid)

        vv = QVBoxLayout()
        vv.addWidget(self.welcome)
        vv.addWidget(self.info)
        vevobox.addLayout(vv)
        self.show()

看起来像这样...

不知道该怎么做,每当我添加其他 QLabel 时,它们都会消失。

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qlayout


    【解决方案1】:

    在展示解决方案之前,您必须解释一些事情:

    • 有 3 种方法可以在小部件中设置布局:

      1. 创建没有父级的小部件,然后小部件通过setLayout() 指示它使用该布局:

        lay = QVBoxLayout()
        foo_widget.setLayout(lay)
        
      2. 指向构建布局时要管理的小部件。

        lay = QVBoxLayout(foo_widget)
        
      3. 前面的方法是等价的,但是第三种方法是建立一个已经建立的布局的儿子。

    • 一个小部件只能有一个布局作为顶层,所以如果只剩下最后一个:

      lay1 = QVBoxLayout(foo_widget)
      lay2 = QVBoxLayout(foo_widget)
      
      # The above is equivalent to:
      
      lay1 = QVBoxLayout()
      lay2 = QVBoxLayout(foo_widget)
      
    • 当一个小部件在构造函数中设置为父级时,它是另一个小部件的儿子,或者它被建立为处理小部件位置的布局的一部分:

      1.

      child_1 = Foo_Widget(some_widget)
      

      2.

      lay = Foo_Layout(some_widget)
      child_2 = Foo_Widget()
      lay.addWidget(child_2)
      

    因此,如果您考虑上述情况,您可以减少代码:

    ...
    def initText(self):
        self.welcome = QLabel("Welcome to Name!")
        self.info = QLabel("This program allows you to....")
        self.message = QLabel("First, you must enter some data...", self)
        self.proceed = QLabel("Click on 'Next >>' to proceed.", self)
    
    def organize(self):
        vbox = QVBoxLayout(self)
        scroll = QScrollArea()
        vbox.addWidget(scroll)
    
        wid = QWidget(self)
        vevobox = QVBoxLayout(wid)
    
        vv = QVBoxLayout()
        vv.addWidget(self.welcome)
        vv.addWidget(self.info)
        vevobox.addLayout(vv)
    
        self.show()
    

    使用上述方法,可以组装出以下树:

    welcomeWidget
    ├── message
    ├── proceed
    ├── vbox (QVBoxLayout)
    │   └── scroll
    └── wid 
        └── vevobox (QVBoxLayout)
            └──vv (QVBoxLayout)
               ├── info
               └── welcome
    

    正如您所看到的,这是预期的,例如,自从它们第一次在没有布局的情况下建立以来,所有内容后面都显示了 2 个标签,然后在放置 QScrollArea 的位置建立了一个布局,所以最后一个所有可用空间,最后放置了没有布局的wid小部件,因此它将位于左上角,并且在该小部件内建立了剩余的2个标签。

    这个想法是有以下结构:

    welcomeWidget
    └── vbox (QVBoxLayout)
        └── scroll
            └── wid
                └── vv (QVBoxLayout)
                    ├── info
                    ├── message
                    ├── proceed
                    └── welcome
    

    使用上面的你得到以下内容:

    class welcomeWidget(QWidget):
        def __init__(self):
            super().__init__()
            self.initText()
            self.organize()
    
        def initText(self):
            self.welcome = QLabel("Welcome to Name!")
            self.info = QLabel("This program allows you to....")
            self.message = QLabel("First, you must enter some data...")
            self.proceed = QLabel("Click on 'Next >>' to proceed.")
    
        def organize(self):
            vbox = QVBoxLayout(self)
            scroll = QScrollArea()
            scroll.setWidgetResizable(True)
    
            wid = QWidget()
            scroll.setWidget(wid)
    
            vv = QVBoxLayout(wid)
            vv.addWidget(self.welcome)
            vv.addWidget(self.info)
            vv.addWidget(self.message)
            vv.addWidget(self.proceed)
            vv.addStretch()
    
            vbox.addWidget(scroll)
            self.show()
    

    【讨论】: