PyQt5中進行界面佈局管理的方法主要由兩種,一種是絕對定位,一種是使用佈局管理器。Qt中使用絕對定位的佈局方式沒法自適應窗口的變化,所以Qt中提供了對界面組件進行佈局管理的類,用於對界面組件進行管理,可以自動排列窗口中的界面組件,窗口大小變化後自動更新界面組件的大小。
QLayout是Qt中佈局管理器的抽象基類,經過對QLayout的繼承,實現了功能各異且互補的佈局管理器。佈局管理器不是界面組件,而是界面組件的定位策略;任意容器類型的組件均可以指定佈局管理器;同一個佈局管理器管理中的組件擁有相同的父組件,在設置佈局管理器的同時已經隱式指定了父子關係。
Qt佈局管理器的addWidget用於向佈局管理器中插入控件,addLayout用於向佈局管理器插入子佈局管理器。app
QHBoxLayout提供了水平方式對控件進行佈局管理。ide
import sys from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QSizePolicy class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QHBoxLayout() self.layout.setSpacing(20) button = QPushButton("Button1") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addWidget(button) button = QPushButton("Button2") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addWidget(button) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QVBoxLayout提供了垂直方式對控件進行佈局管理。函數
import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QSizePolicy class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QVBoxLayout() self.layout.setSpacing(20) button = QPushButton("Button1") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addWidget(button) button = QPushButton("Button2") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addWidget(button) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
佈局管理器能夠相互嵌套,造成複雜的佈局管理方式。QBoxLayout佈局管理器的嵌套使用實例以下:
佈局
import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QSizePolicy class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QVBoxLayout() self.layout.setSpacing(20) # 第一行按鈕佈局管理 hLayout1 = QHBoxLayout() button = QPushButton("Button1") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hLayout1.addWidget(button) button = QPushButton("Button2") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hLayout1.addWidget(button) # 第二行按鈕佈局管理 hLayout2 = QHBoxLayout() button = QPushButton("Button1") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hLayout2.addWidget(button) button = QPushButton("Button2") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hLayout2.addWidget(button) # 總體垂直佈局管理 self.layout.addLayout(hLayout1) self.layout.addLayout(hLayout2) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QGridLayout佈局管理器以網格的方式管理界面組件。3d
import sys from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QPushButton, QSizePolicy class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QGridLayout() self.layout.setSpacing(5) button = QPushButton("Button1") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.layout.addWidget(button, 0, 0, 1, 1) button = QPushButton("Button2") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.layout.addWidget(button, 0, 1, 1, 1) button = QPushButton("Button3") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.layout.addWidget(button, 1, 0, 1, 1) button = QPushButton("Button4") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.layout.addWidget(button, 1, 1, 1, 1) button = QPushButton("Button5") button.setMinimumSize(60, 30) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # 列擴展,定位在第2行第1列位置,佔1行2列 self.layout.addWidget(button, 2, 0, 1, 2) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QFormLayout佈局管理器使用表單的方式管理界面組件,表單中的標籤和組件是相互對應的關係,支持嵌套使用。
code
import sys from PyQt5.QtWidgets import QApplication, QWidget, QFormLayout, QVBoxLayout, QLineEdit from PyQt5.QtCore import Qt class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QFormLayout() self.layout.setSpacing(20) self.layout.setLabelAlignment(Qt.AlignLeft) self.layout.setFormAlignment(Qt.AlignRight) nameEdit = QLineEdit() mailEdit = QLineEdit() vLayout = QVBoxLayout() vLayout.setSpacing(6) addrEdit1 = QLineEdit() addrEdit2 = QLineEdit() vLayout.addWidget(addrEdit1) vLayout.addWidget(addrEdit2) self.layout.addRow("Name:", nameEdit) self.layout.addRow("Mail:", mailEdit) self.layout.addRow("Address:", vLayout) self.setLayout(self.layout) self.setWindowTitle("FTP") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QStackedLayout棧式佈局管理器管理的全部組件在垂直於屏幕的方向上,每次只有一個界面組件會顯示在屏幕上,只要最頂層的界面組件會被顯示。
QStackedLayout棧式佈局管理器的特色以下:
A、組件大小一致,且充滿父組件的顯示區
B、不能直接嵌套其它佈局管理器
C、可以自由切換須要顯示的組件
D、每次僅能顯示一個界面組件
orm
import sys from PyQt5.QtWidgets import QApplication, QWidget, QStackedLayout, QVBoxLayout, QPushButton class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QStackedLayout() self.layout.addWidget(QPushButton("Button1")) self.layout.addWidget(QPushButton("Button2")) self.layout.addWidget(QPushButton("Button3")) self.layout.addWidget(QPushButton("Button4")) self.setLayout(self.layout) self.setWindowTitle("Stack Layout") # 設置棧頂顯示第2個組件 self.layout.setCurrentIndex(2) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QStackedLayout棧式佈局管理器不能直接嵌套其它佈局管理器,但能夠經過QWidget容器組件間接嵌套使用其它佈局管理器。blog
import sys from PyQt5.QtWidgets import QApplication, QWidget, QStackedLayout, QVBoxLayout, QPushButton class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QStackedLayout() self.layout.addWidget(QPushButton("Button1")) # 容器型組件 widget = QWidget() vLayout = QVBoxLayout() vLayout.addWidget(QPushButton("Button2")) vLayout.addWidget(QPushButton("Button3")) widget.setLayout(vLayout) self.layout.addWidget(widget) self.layout.addWidget(QPushButton("Button4")) self.setLayout(self.layout) self.setWindowTitle("Stack Layout") # 設置棧頂顯示第1個組件 self.layout.setCurrentIndex(1) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())
QSplitter是一個帶切分條(splitter handle)的佈局管理器,能夠經過setHandleWidth()函數來設置切分條的寬帶。QSplitter能夠經過setOrientation()函數來指定分割方向,子組件按加載順序進行指定方向排列。繼承
import sys from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit, QVBoxLayout, QSplitter from PyQt5.QtCore import Qt class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QVBoxLayout() self.mainSplitter = QSplitter(self) self.layout.addWidget(self.mainSplitter) self.setLayout(self.layout) # 水平線分割 self.mainSplitter.setOrientation(Qt.Horizontal) rightSplitter = QSplitter(self) # 垂直線分割 rightSplitter.setOrientation(Qt.Vertical) textEdit = QTextEdit() textEdit.setText("Window2") rightSplitter.addWidget(textEdit) textEdit = QTextEdit() textEdit.setText("Window3") rightSplitter.addWidget(textEdit) textEdit = QTextEdit() textEdit.setText("Window1") self.mainSplitter.addWidget(textEdit) self.mainSplitter.addWidget(rightSplitter) # 分割比例 self.mainSplitter.setStretchFactor(0, 1) self.mainSplitter.setStretchFactor(1, 2) self.mainSplitter.show() self.setWindowTitle("Splitter") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.resize(400, 200) window.show() sys.exit(app.exec_())