使用Python的QBoxLayouts

1 投票
1 回答
914 浏览
提问于 2025-04-18 05:54

因为它们的高度可定制性,我在构建应用程序的图形界面时一直依赖使用多个GroupBox。但看起来QGroupBox会影响界面构建的速度。现在通过布局的.insertLayout()方法,我可以在任何我想要的位置构建整个图形界面。对话框感觉非常轻便,重绘速度极快。不幸的是,我找不到控制它们外观的方法。如果你能给我一些关于如何控制布局视觉属性的线索,我将非常感激。我特别想知道:

  1. 如何绘制布局边框,如何控制边框线的宽度,

  2. 如何放置布局标题(类似于QGroupBox的.setTitle()功能)

  3. 如何控制布局的外边距和内边距。

  4. 如何让布局可以最小化/恢复大小(这样用户可以点击某个减号/箭头图标来折叠/展开布局,以便在需要或不需要某些属于同一布局的控件时使用)。

下面是一个包含三个嵌套布局的示例。正如对话框截图所示,无法在视觉上区分一个布局和另一个布局,因为没有边框、没有标题、没有分隔线等等。

enter image description here

from PyQt4 import QtGui, QtCore

class Dialog_01(QtGui.QMainWindow):
    def __init__(self):
        super(QtGui.QMainWindow,self).__init__()

        tabWidget = QtGui.QTabWidget()
        tabGroupBox = QtGui.QGroupBox()
        tabLayout = QtGui.QVBoxLayout()

        tabLayout.setContentsMargins(0, 0, 0, 0)
        tabLayout.setSpacing(0)    

        subLayoutA=QtGui.QVBoxLayout()
        tabLayout.insertLayout(0, subLayoutA)

        tabGroupBox.setLayout(tabLayout)
        tabWidget.addTab(tabGroupBox,' Tab A ')

        listWidgetA = QtGui.QListWidget()
        for i in range(3): 
            QtGui.QListWidgetItem( 'Item '+str(i), listWidgetA )

        subLayoutA.addWidget(listWidgetA)

        subLayoutB=QtGui.QHBoxLayout()
        tabLayout.insertLayout(1, subLayoutB)

        subLayoutB.addWidget(QtGui.QLineEdit('LineEdit 1'))
        subLayoutB.addWidget(QtGui.QLineEdit('LineEdit 2'))

        subLayoutC=QtGui.QVBoxLayout()
        tabLayout.insertLayout(2, subLayoutC)

        subLayoutC.addWidget(QtGui.QPushButton('PushButton 1'))
        subLayoutC.addWidget(QtGui.QPushButton('PushButton 2'))
        self.setCentralWidget(tabWidget)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())

后续编辑

我在示例代码中插入了两行,以实现sebastian提出的建议之一。可以有效地使用间距-边距方法组合来进行一些额外的调整。这里是一个截图(仍然无法去掉pushButtons周围的间距):

enter image description here

1 个回答

3

QLayout 的子类没有视觉表现,这一点很明显,因为 QLayout 类并不继承 QWidget。它们只是负责计算自己所管理的控件在其“父”控件中的位置。

所以对于问题 1、2 和 4 的回答基本上是:你不能。

你总是需要将 QWidgetQLayout 结合使用。比如,要把两个按钮放在一个有框的区域里,可以使用 QFrame

    subLayoutC=QtGui.QVBoxLayout()
    buttonFrame = QtGui.QFrame()
    buttonFrame.setFrameStyle(QtGui.QFrame.Plain |QtGui.QFrame.Box)
    buttonFrame.setLayout(subLayoutC)

    subLayoutC.addWidget(QtGui.QPushButton('PushButton 1'))
    subLayoutC.addWidget(QtGui.QPushButton('PushButton 2'))

    # now we add the QFrame widget - not subLayoutC to the tabLayout
    tabLayout.addWidget(buttonFrame) # I think your suggested edit was correct here
    self.setCentralWidget(tabWidget)

关于问题 3,可以查看文档:

http://qt-project.org/doc/qt-4.8/qlayout.html#setContentsMargins

http://qt-project.org/doc/qt-4.8/qboxlayout.html#setSpacing

撰写回答