从PyQt5官方示例了解布局管理

从官网的tutorial学习PyQt5最合适不过,最主要的是跟着走一遍官方教程后,对于整个PyQt有全方位的理解,这篇文章主要抽取比较典型的一个案例具体展开分析。
PyQt5 tutorial官网地址
PyQt5 examples源码Github地址

此文章代码示例位于 pyqt5_examples/dialogs/configdialog/configdialog.py,选这个示例,考虑到涵盖布局管理、窗口切换、窗口自动调节这些常见的操作,值的拿出来单独讲一下,废话不多数,上图:



configdialog.py:

from PyQt5.QtCore import QDate, QSize, Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QDateTimeEdit,
        QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit,
        QListView, QListWidget, QListWidgetItem, QPushButton, QSpinBox,
        QStackedWidget, QVBoxLayout, QWidget)

import configdialog_rc

# 定义ConfigurationPage UI
class ConfigurationPage(QWidget):
    def __init__(self, parent=None):
        super(ConfigurationPage, self).__init__(parent)

        configGroup = QGroupBox("Server configuration")

        # 定义一个名为Server.的label
        serverLabel = QLabel("Server:")
        #定义下拉形态的组合框,并填充元素
        serverCombo = QComboBox()                         
        serverCombo.addItem("Trolltech (Australia)")
        serverCombo.addItem("Trolltech (Germany)")
        serverCombo.addItem("Trolltech (Norway)")
        serverCombo.addItem("Trolltech (People's Republic of China)")
        serverCombo.addItem("Trolltech (USA)")

        # 横向布局
        serverLayout = QHBoxLayout()
        serverLayout.addWidget(serverLabel)
        serverLayout.addWidget(serverCombo)
        # 纵向布局
        configLayout = QVBoxLayout()
        configLayout.addLayout(serverLayout)
        configGroup.setLayout(configLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(configGroup)
        #调节各Widget的比例,此处的addStretch(1)作用使得configGroup置顶
        mainLayout.addStretch(1)

        self.setLayout(mainLayout)

# CheckBox候选框+ListWidget
class UpdatePage(QWidget):
    def __init__(self, parent=None):
        super(UpdatePage, self).__init__(parent)
        
        updateGroup = QGroupBox("Package selection")
        #定义三组多选框
        systemCheckBox = QCheckBox("Update system")
        appsCheckBox = QCheckBox("Update applications")
        docsCheckBox = QCheckBox("Update documentation")

        packageGroup = QGroupBox("Existing packages")
         # ListWidget列表视图
        packageList = QListWidget()
        qtItem = QListWidgetItem(packageList)
        qtItem.setText("Qt")
        qsaItem = QListWidgetItem(packageList)
        qsaItem.setText("QSA")
        teamBuilderItem = QListWidgetItem(packageList)
        teamBuilderItem.setText("Teambuilder")
        # 定义启动Push Button 
        startUpdateButton = QPushButton("Start update")

        updateLayout = QVBoxLayout()
        updateLayout.addWidget(systemCheckBox)
        updateLayout.addWidget(appsCheckBox)
        updateLayout.addWidget(docsCheckBox)
        updateGroup.setLayout(updateLayout)

        packageLayout = QVBoxLayout()
        packageLayout.addWidget(packageList)
        packageGroup.setLayout(packageLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(updateGroup)
        mainLayout.addWidget(packageGroup)
        mainLayout.addSpacing(12)
        mainLayout.addWidget(startUpdateButton)
        mainLayout.addStretch(1)

        self.setLayout(mainLayout)

# 采用GridLayout网格布局
class QueryPage(QWidget):
    def __init__(self, parent=None):
        super(QueryPage, self).__init__(parent)

        packagesGroup = QGroupBox("Look for packages")

        nameLabel = QLabel("Name:")
        nameEdit = QLineEdit()

        dateLabel = QLabel("Released after:")
        dateEdit = QDateTimeEdit(QDate.currentDate())

        releasesCheckBox = QCheckBox("Releases")
        upgradesCheckBox = QCheckBox("Upgrades")

        hitsSpinBox = QSpinBox()
        hitsSpinBox.setPrefix("Return up to ")
        hitsSpinBox.setSuffix(" results")
        hitsSpinBox.setSpecialValueText("Return only the first result")
        hitsSpinBox.setMinimum(1)
        hitsSpinBox.setMaximum(100)
        hitsSpinBox.setSingleStep(10)

        startQueryButton = QPushButton("Start query")
       '''        
           void QGridLayout::addWidget(QWidget * widget, int fromRow, int 
           fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0)
           各参数表示分别为控件名,行,列,占用行数,占用列数,对齐方式
       '''
      packagesLayout = QGridLayout()
        packagesLayout.addWidget(nameLabel, 0, 0)
        packagesLayout.addWidget(nameEdit, 0, 1)
        packagesLayout.addWidget(dateLabel, 1, 0)
        packagesLayout.addWidget(dateEdit, 1, 1)
        packagesLayout.addWidget(releasesCheckBox, 2, 0)
        packagesLayout.addWidget(upgradesCheckBox, 3, 0)
        packagesLayout.addWidget(hitsSpinBox, 4, 0, 1, 2)
        packagesGroup.setLayout(packagesLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(packagesGroup)
        mainLayout.addSpacing(12)
        mainLayout.addWidget(startQueryButton)
        mainLayout.addStretch(1)

        self.setLayout(mainLayout)

# 主UI界面
class ConfigDialog(QDialog):
    def __init__(self, parent=None):
        super(ConfigDialog, self).__init__(parent)

        self.contentsWidget = QListWidget()
        self.contentsWidget.setViewMode(QListView.IconMode)
        self.contentsWidget.setIconSize(QSize(150, 180))
        self.contentsWidget.setMovement(QListView.Static)
        self.contentsWidget.setMaximumWidth(128)
        self.contentsWidget.setSpacing(12)

        '''
            QStackedWidget继承自QFrame。
            QStackedWidget类提供了多页面切换的布局,一次只能看到一个界面。
        '''
        self.pagesWidget = QStackedWidget()
        self.pagesWidget.addWidget(ConfigurationPage())
        self.pagesWidget.addWidget(UpdatePage())
        self.pagesWidget.addWidget(QueryPage())

        closeButton = QPushButton("Close")

        self.createIcons()
        self.contentsWidget.setCurrentRow(0)

        # 点击close Button关闭界面
        closeButton.clicked.connect(self.close)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.contentsWidget)
        horizontalLayout.addWidget(self.pagesWidget, 1)

        buttonsLayout = QHBoxLayout()
        buttonsLayout.addStretch(1)
        buttonsLayout.addWidget(closeButton)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(horizontalLayout)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(12)
        mainLayout.addLayout(buttonsLayout)

        self.setLayout(mainLayout)

        self.setWindowTitle("Config Dialog")
    #如果上一张Page与当前的Page不同,将pagesWidget设定为当前Page
    def changePage(self, current, previous):
        if not current:
            current = previous

        self.pagesWidget.setCurrentIndex(self.contentsWidget.row(current))

    #为config/update/query制作图片logo,注意import configdialog_rc,否者图片加载不到
    def createIcons(self):
        configButton = QListWidgetItem(self.contentsWidget)
        configButton.setIcon(QIcon(':/images/config.png'))
        configButton.setText("Configuration")
        configButton.setTextAlignment(Qt.AlignHCenter)
        configButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        updateButton = QListWidgetItem(self.contentsWidget)
        updateButton.setIcon(QIcon(':/images/update.png'))
        updateButton.setText("Update")
        updateButton.setTextAlignment(Qt.AlignHCenter)
        updateButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        queryButton = QListWidgetItem(self.contentsWidget)
        queryButton.setIcon(QIcon(':/images/query.png'))
        queryButton.setText("Query")
        queryButton.setTextAlignment(Qt.AlignHCenter)
        queryButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        #为contentsWidget界面切换添加changePage响应
        self.contentsWidget.currentItemChanged.connect(self.changePage)


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)
    dialog = ConfigDialog()
    sys.exit(dialog.exec_())    

今天有些晚,待续。。。
CC

你可能感兴趣的:(从PyQt5官方示例了解布局管理)