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

從官網(wǎng)的tutorial學習PyQt5最合適不過站楚,最主要的是跟著走一遍官方教程后妹萨,對于整個PyQt有全方位的理解,這篇文章主要抽取比較典型的一個案例具體展開分析尝盼。
PyQt5 tutorial官網(wǎng)地址
PyQt5 examples源碼Github地址

此文章代碼示例位于 pyqt5_examples/dialogs/configdialog/configdialog.py模蜡,選這個示例漠趁,考慮到涵蓋布局管理、窗口切換忍疾、窗口自動調(diào)節(jié)這些常見的操作闯传,值的拿出來單獨講一下,廢話不多數(shù)卤妒,上圖:



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:")
        #定義下拉形態(tài)的組合框甥绿,并填充元素
        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)
        #調(diào)節(jié)各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網(wǎng)格布局
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)
           各參數(shù)表示分別為控件名,行共缕,列洗出,占用行數(shù),占用列數(shù)图谷,對齊方式
       '''
      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_())    

今天有些晚,待續(xù)俏竞。绸硕。。
CC

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末魂毁,一起剝皮案震驚了整個濱河市玻佩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌席楚,老刑警劉巖咬崔,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異烦秩,居然都是意外死亡垮斯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門榨惠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裸影,“玉大人莱预,你說我怎么就攤上這事⌒苎睿” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵盗舰,是天一觀的道長晶府。 經(jīng)常有香客問我,道長钻趋,這世上最難降的妖魔是什么川陆? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蛮位,結果婚禮上书劝,老公的妹妹穿的比我還像新娘进倍。我一直安慰自己,他們只是感情好购对,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布猾昆。 她就那樣靜靜地躺著,像睡著了一般骡苞。 火紅的嫁衣襯著肌膚如雪垂蜗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天解幽,我揣著相機與錄音贴见,去河邊找鬼。 笑死躲株,一個胖子當著我的面吹牛片部,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播霜定,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼档悠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了望浩?” 一聲冷哼從身側響起辖所,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磨德,沒想到半個月后缘回,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡典挑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年酥宴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您觉。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡幅虑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顾犹,到底是詐尸還是另有隱情倒庵,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布炫刷,位于F島的核電站擎宝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏浑玛。R本人自食惡果不足惜绍申,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧极阅,春花似錦胃碾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奔脐,卻和暖如春俄周,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背髓迎。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工峦朗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人排龄。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓波势,卻偏偏與公主長得像,于是被迫代替她去往敵國和親橄维。 傳聞我的和親對象是個殘疾皇子尺铣,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容