前言
本系列介紹如何在 Python 中使用 Qt for Python 進行 GUI 應用程序開發。
本文是《Qt for Python 學習筆記》系列第十三篇,對 Qt for Python 布局的内容邊距和間距進行介紹,讓讀者對此部分知識有個基本的認識和掌握。
術語表
在使用布局管理器開發 GUI 應用程序時,通常會發現一個現象:部件不能占滿整個窗口客戶區域(四周會留一些空隙),而且各個部件之間也留有一些空隙。
可能有初學者會對此現象感到不解,為什麼四周以及各部件之間會有空隙呢?
問題的答案就是:Qt 布局管理器中存在默認的内容邊距和默認的間距,這些内容邊距和間距是可以進行設置的,如果均設置為0,則這些空隙就沒了(也就看不見了)。
下面我們來看一個布局(含默認邊距和間距)示例窗口(如下圖示)。
布局默認邊距和間距示意窗口
——該窗口中含一個垂直布局區域(上圖黑框區域)。
——在垂直布局的内容區域(上圖紅色虛框區域)中從上往下依次放置部件1和部件2。
——在上圖紅色虛框(布局内容矩形)與黑框(布局周圍的4個邊)之間的(4個方向上)空隙,表示該布局的邊距,包括左側邊距、頂部邊距、右側邊距和底部邊距。
——在上圖紅色虛框(布局内容)内部件1和部件2之間的空隙,表示兩個部件之間的間距。
布局的内容邊距(簡稱布局邊距),指的是布局中的内容區域(裡面放置各部件或子布局)與該布局周圍四個邊的空隙距離。
在Windows平台上,Qt 提供的默認布局邊距值為9px。
布局邊距的相關屬性和方法介紹如下:
2.1 獲取布局邊距的函數一、函數聲明
def contentsMargins(self) -> PySide6.QtCore.QMargins: ...
def contentsRect(self) -> PySide6.QtCore.QRect: ...
def getContentsMargins(self) -> typing.Tuple: ...
上述函數繼承自 QLayout 類。
二、函數1說明
——功能:該函數返回布局的内容邊距,類型為 QMargins。
三、函數2說明
——功能:該函數返回布局的内容區域,類型為 QRect。
四、函數3說明
——功能:該函數返回布局的内容邊距元組,類型為 Tuple。
可以通過調用 setContentsMargins() 方法來設置布局的内容邊距。
一、函數聲明
@typing.overload
def setContentsMargins(self, left:int, top:int, right:int, bottom:int) -> None: ...
@typing.overload
def setContentsMargins(self, margins:PySide6.QtCore.QMargins) -> None: ...
上述函數來自 QLayout 類。
二、函數1說明
——功能:該函數通過4個傳入參數設置布局中的内容(各部件)離該布局周圍四個邊的距離值,4個傳入參數依次為左側、頂部、右側和底部邊距值。
——參數(left):表示布局中的内容(各部件)離該布局左側邊的距離值,類型為 int。
——參數(top):表示布局中的内容(各部件)離該布局頂部邊的距離值,類型為 int。
——參數(right):表示布局中的内容(各部件)離該布局右側邊的距離值,類型為 int。
——參數(bottom):表示布局中的内容(各部件)離該布局底部邊的距離值,類型為 int。
二、函數2說明
——功能:該函數通過傳入參數(margins)設置布局中的内容(各部件)離該布局周圍四個邊的距離值。
——參數(margins):表示布局中的内容(各部件)離該布局,類型為 QMargins。
當利用 Qt Designer 可視化界面設計工具開發 GUI 應用程序時,可以通過 Qt Designer 主窗口中的【屬性編輯器】對指定布局對象的(4個)邊距屬性直接進行設置(如下圖示)。
屬性編輯器中的布局邊距屬性
其中:
——layoutLeftMargin 對應左側邊距值;
——layoutTopMargin 對應頂部邊距值;
——layoutRightMargin 對應右側邊距值;
——layoutBottomMargin 對應底部邊距值。
注:通過上圖也可以發現在Windows平台上,Qt 提供的默認布局邊距值為9px。
3. 布局間距介紹布局的間距指的是布局中各部件之間的間隔(空隙距離)。
在Windows平台上,Qt 提供的默認布局間距值為6px。
布局間距的相關屬性和方法介紹如下:
3.1 獲取布局間距的函數一、函數聲明
def spacing(self) -> int: ...
上述函數來自 QLayout 類。
二、函數說明
——功能:該函數返回布局内部各部件之間的間距值,類型為 int。
如果程序中沒有設置間距值,則返回 -1。
3.2 設置布局間距的函數可以通過調用 setSpacing() 方法來設置指定布局中各部件之間的間距值。
一、函數聲明
def setSpacing(self, spacing:int) -> None: ...
上述函數來自 QLayout 類。
二、函數說明
——功能:該函數通過傳入參數( spacing)設置布局内部各部件之間的間距值。
——參數( spacing):表示布局内部各部件之間的間距值,類型為 int。該參數可省略,缺省值為0。
注:間距并不是布局中的一個項目(item),因此布局并不會為其分配索引号。
3.3 通過 Qt Designer 設置布局間距當利用 Qt Designer 可視化界面設計工具開發 GUI 應用程序時,可以通過 Qt Designer 主窗口中的【屬性編輯器】對指定布局對象的 layoutSpacing 屬性值(即該布局的間距值)直接進行設置。
屬性編輯器中的布局間距屬性
注:通過上圖也可以發現在Windows平台上,Qt 提供的默認布局間距值為6px。
4. 間隔部件介紹可以通過向該布局兩個部件之間增加(或插入)一個間隔部件的方法來達到設置布局間距的效果。
4.1 标準間隔部件當利用 Qt Designer 可視化界面設計工具開發 GUI 應用程序時,可以在 Qt Designer 主窗口中的【窗口部件盒】中的【間隔分組類别(Spacers)】看到有2個對應界面部件(如下圖示)。
間隔分組類别(Spacers)
其中:
——Horizontal Spacer 為水平間隔界面部件,Spacer 類,用于類似彈簧的水平間隔。
——Vertical Spacer 垂直間隔界面部件,Spacer 類,用于類似彈簧的垂直間隔。
從 Qt Designer 主窗口中的【對象檢查器】中可以得知這2個界面部件對應的均為 Spacer 類。
對象檢查器中的 Spacer類
但是當我們想對 Spacer 類進一步探索時,卻發現在 Qt 中竟然找不到 Spacer 類的定義。實際上 Qt Designer 中 Spacer 類就是 QtWidgets 模塊下的 QSpacerItem 類。
4.2 QSpacerItem 類一、QSpacerItem 類的作用
使用 QSpacerItem 類可以在布局中創建一個間隔部件(相當于一個自定義的布局間距)。該間隔部件是布局中的一個項目(item),會在布局中占據一個位置,布局會為其分配一個索引号,也就是說由 QSpacerItem 類創建的對象是可以由布局管理器進行管理的。
注:通常情況下我們并不需要使用該類,因為在各布局管理器中有相應的函數代替了該類的功能。
二、QSpacerItem 類的基本信息
class QSpacerItem(PySide6.QtWidgets.QLayoutItem): def __init__(self, w:int, h:int, hData:PySide6.QtWidgets.QSizePolicy.Policy=..., vData:PySide6.QtWidgets.QSizePolicy.Policy=...) -> None: ... def changeSize(self, w:int, h:int, hData:PySide6.QtWidgets.QSizePolicy.Policy=..., vData:PySide6.QtWidgets.QSizePolicy.Policy=...) -> None: ... def expandingDirections(self) -> PySide6.QtCore.Qt.Orientations: ... def geometry(self) -> PySide6.QtCore.QRect: ... def isEmpty(self) -> bool: ... def maximumSize(self) -> PySide6.QtCore.QSize: ... def minimumSize(self) -> PySide6.QtCore.QSize: ... def setGeometry(self, arg__1:PySide6.QtCore.QRect) -> None: ... def sizeHint(self) -> PySide6.QtCore.QSize: ... def sizePolicy(self) -> PySide6.QtWidgets.QSizePolicy: ... def spacerItem(self) -> PySide6.QtWidgets.QSpacerItem: ...
QSpacerItem 類構造函數表示構造或修改一個具有寬度為w,高度為h,水平方向的尺寸策略為hData,垂直方向尺寸策略為 vData 的間隔(即 QSpacerItem 實例)。
4.3 添加/插入固定尺寸的間隔部件的函數一、函數聲明
def addSpacing(self, size:int) -> None: ... def insertSpacing(self, index:int, size:int) -> None: ...
上述函數來自 QBoxLayout 類。
二、函數1說明
——功能:該函數在布局末尾添加一個指定尺寸(傳入參數 size)的間隔部件。
——參數(size):表示指定尺寸,類型為 int。
三、函數2說明
——功能:該函數在布局指定位置(傳入參數 index)插入一個指定尺寸(傳入參數 size)的間隔部件。
——參數(index):表示指定位置,類型為 int。索引從0開始,0表示第一個位置(水平布局從左往右,垂直布局從上往下);若索引為負值表示插入到布局末尾。
——參數(size):表示指定尺寸,類型為 int。
注:向布局中插入間隔部件後,該間隔部件就稱為了布局中的一個項目(item),因此布局會為該間隔部件分配一個索引号,進而會改變布局内各部件之間的原有索引号。請注意與布局間距屬性的區别。
4.4 添加/插入可伸縮的間隔部件的函數一、函數聲明
def addSpacerItem(self, spacerItem:PySide6.QtWidgets.QSpacerItem) -> None: ... def insertSpacerItem(self, index:int, spacerItem:PySide6.QtWidgets.QSpacerItem) -> None: ...
上述函數來自 QBoxLayout 類。
二、函數1說明
——功能:該函數在布局末尾添加一個可伸縮(傳入參數 spacerItem)的間隔部件。
——參數(spacerItem):表示最小尺寸為0,伸縮因子為0的,可伸縮間隔部件,類型為 QSpacerItem。
三、函數2說明
——功能:該函數在布局指定位置(傳入參數 index)插入一個可伸縮(傳入參數 spacerItem)的間隔部件。
——參數(index):表示指定位置,類型為 int。索引從0開始,0表示第一個位置(水平布局從左往右,垂直布局從上往下);若索引為負值表示插入到布局末尾。
——參數(spacerItem):表示最小尺寸為0,伸縮因子為0的,可伸縮空白部件,類型為 QSpacerItem。
注:向布局中插入間隔部件後,該間隔部件就稱為了布局中的一個項目(item),因此布局會為該間隔部件分配一個索引号,進而會改變布局内各部件之間的原有索引号。請注意與布局間距屬性的區别。
4.5 添加/插入可指定伸縮因子的可伸縮間隔部件的函數一、函數聲明
def addStretch(self, stretch:int=...) -> None: ... def insertStretch(self, index:int, stretch:int=...) -> None: ...
上述函數來自 QBoxLayout 類。
二、函數1說明
——功能:該函數在布局末尾添加一個指定伸縮因子(傳入參數 stretch)的可伸縮間隔部件(最小尺寸為0)。
——參數(stretch):表示指定的伸縮因子,類型為 int,取值範圍[0,255]。
三、函數2說明
——功能:該函數在布局指定位置(傳入參數 index)插入一個指定伸縮因子(傳入參數 stretch)的可伸縮間隔部件(最小尺寸為0)。
——參數(index):表示指定位置,類型為 int。索引從0開始,0表示第一個位置(水平布局從左往右,垂直布局從上往下);若索引為負值表示插入到布局末尾。
——參數(stretch):表示指定的伸縮因子,類型為 int,取值範圍[0,255]。
注:向布局中插入間隔部件後,該間隔部件就稱為了布局中的一個項目(item),因此布局會為該間隔部件分配一個索引号,進而會改變布局内各部件之間的原有索引号。請注意與布局間距屬性的區别。
5. 布局邊距示例5.1 示例原型在進行 GUI 應用程序編碼之前,一般建議先勾畫出 GUI 框架(窗體及各部件的布局等)。本示例原型如下:
布局内容邊距示例原型
5.2 示例目标本示例目标是創建一個 Python GUI 應用程序,在主窗口中如原型圖示放置6個标簽。
主窗口及部件的位置、尺寸及其他屬性如下:
- 主窗口
——(1) 窗口位置及尺寸采用尺寸提示(默認大小)
——(2) 标題:布局内容邊距示例程序
——(3) 具有窗口最小化、最大化、關閉快捷按鈕
- 6個标簽
——(1) 位置:如原型圖示放置排列
——(2) 尺寸:采用尺寸提示(默認大小)
——(3) 尺寸:6個标簽文本依次為:“标簽一”、"标簽二"、"标簽三"、"标簽四"、"标簽五"、"标簽六"
——(4) 背景色:6個标簽依次為“SkyBlue”、“Pink”、“PaleGreen”、“Cyan”、“Gold”、“Orange”
- 各布局内容邊距
——最外層紅框表示水平布局,該布局4個方向上的内容邊距均為0。
——裡面最左側是一個垂直布局(放置标簽1),該布局4個方向上的内容邊距依次為(0, 0, 0, 20)。
——裡面中間的藍框是一個垂直布局(其中從上往下依次放置标簽2和标簽3),該布局4個方向上的内容邊距依次為(10, 10, 20, 10)。
——裡面右側的綠框是一個垂直布局(其中從上往下依次放置标簽4、标簽5和标簽6),該布局4個方向上的内容邊距依次為(0, 20, 0, 0)。
- 窗口縮放時各部件按默認的尺寸策略自動進行自适應調整
——在拉伸(或壓縮)窗口時,各标簽安裝默認的尺寸策略進行自适應同步縮放。
——在拉伸(或壓縮)窗口時,标簽四周的内容邊距以及各個标簽之間的間距始終保持不變。
5.3 示例代碼利用 Visual Studio Code 編輯代碼,并保存為文件(如:C:\MyPySide6\MyPySide6LayoutContentMarginApp.py)。
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLabel) class MyMainWindow(QMainWindow): def __init__(self): super(MyMainWindow, self).__init__() window = QWidget() label_1 = QLabel("标簽一") label_2 = QLabel("标簽二") label_3 = QLabel("标簽三") label_4 = QLabel("标簽四") label_5 = QLabel("标簽五") label_6 = QLabel("标簽六") label_1.setStyleSheet("background-color: SkyBlue;") label_2.setStyleSheet("background-color: Pink;") label_3.setStyleSheet("background-color: PaleGreen;") label_4.setStyleSheet("background-color: Cyan;") label_5.setStyleSheet("background-color: Gold;") label_6.setStyleSheet("background-color: Orange;") vBoxLayout1 = QVBoxLayout() vBoxLayout1.addWidget(label_1) vBoxLayout2 = QVBoxLayout() vBoxLayout2.addWidget(label_2) vBoxLayout2.addWidget(label_3) vBoxLayout3 = QVBoxLayout() vBoxLayout3.addWidget(label_4) vBoxLayout3.addWidget(label_5) vBoxLayout3.addWidget(label_6) hBoxLayout = QHBoxLayout() hBoxLayout.addLayout(vBoxLayout1) hBoxLayout.addLayout(vBoxLayout2) hBoxLayout.addLayout(vBoxLayout3) vBoxLayout1.setContentsMargins(0, 5, 0, 20) vBoxLayout2.setContentsMargins(0, 0, 0, 0) vBoxLayout3.setContentsMargins(15, 20, 0, 5) hBoxLayout.setContentsMargins(0, 0, 0, 0) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局内容邊距示例程序") if __name__ == '__main__': import sys app = QApplication(sys.argv) gui = MyMainWindow() gui.show() sys.exit(app.exec_())
5.4 代碼解析本示例代碼共分三部分:
一、導入模塊(或類)部分
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLabel)
——第1行代碼:表示從 PySide6.QtWidgets 模塊導入後續代碼中會用到的 QApplication 類、QMainWindow 類、QWidget 類、QHBoxLayout 類、QVBoxLayout 類、QLabel 類。
二、自定義MyMainWindow類部分
其次,自定義 MyMainWindow 類(即主窗口,繼承自 QMainWindow 類):
class MyMainWindow(QMainWindow): def __init__(self): super(MyMainWindow, self).__init__() window = QWidget() label_1 = QLabel("标簽一") label_2 = QLabel("标簽二") label_3 = QLabel("标簽三") label_4 = QLabel("标簽四") label_5 = QLabel("标簽五") label_6 = QLabel("标簽六") label_1.setStyleSheet("background-color: SkyBlue;") label_2.setStyleSheet("background-color: Pink;") label_3.setStyleSheet("background-color: PaleGreen;") label_4.setStyleSheet("background-color: Cyan;") label_5.setStyleSheet("background-color: Gold;") label_6.setStyleSheet("background-color: Orange;") vBoxLayout1 = QVBoxLayout() vBoxLayout1.addWidget(label_1) vBoxLayout2 = QVBoxLayout() vBoxLayout2.addWidget(label_2) vBoxLayout2.addWidget(label_3) vBoxLayout3 = QVBoxLayout() vBoxLayout3.addWidget(label_4) vBoxLayout3.addWidget(label_5) vBoxLayout3.addWidget(label_6) hBoxLayout = QHBoxLayout() hBoxLayout.addLayout(vBoxLayout1) hBoxLayout.addLayout(vBoxLayout2) hBoxLayout.addLayout(vBoxLayout3) vBoxLayout1.setContentsMargins(0, 5, 0, 20) vBoxLayout2.setContentsMargins(0, 0, 0, 0) vBoxLayout3.setContentsMargins(15, 20, 0, 5) hBoxLayout.setContentsMargins(0, 0, 0, 0) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局内容邊距示例程序")
——第1行代碼:自定義 MyMainWindow 類的聲明語句。類名為 MyMainWindow,該類繼承自 QMainWindow 類。
——第2行代碼:聲明一個類構造函數( __init__(self)),有1個傳遞參數(self,表示類實例對象本身):
——第3行代碼:通過 super() 方法繼承了父類(QMainWindow)構造函數中的全部屬性。
——第5行代碼:通過實例化 QWidget 類創建一個窗口對象(window)。
——第7-12行代碼:通過實例化 QLabel 類依次創建6個标簽對象(這4個标簽會添加到布局中,故無需設置其父部件)
——第13-18行代碼:通過調用标簽對象的 setStyleSheet() 方法依次設置6個标簽的背景色。
——第20行代碼:通過實例化 QVBoxLayout 類創建一個垂直布局對象(vBoxLayout1)。
——第21行代碼:調用 addwidget() 方法依次将标簽1添加到垂直布局對象(vBoxLayout1)末尾。
——第23行代碼:通過實例化 QVBoxLayout 類創建一個垂直布局對象(vBoxLayout2)。
——第24-25行代碼:調用 addwidget() 方法依次将标簽2和标簽3添加到垂直布局對象(vBoxLayout2)末尾。
——第27行代碼:通過實例化 QVBoxLayout 類創建一個垂直布局對象(vBoxLayout3)。
——第28-30行代碼:調用 addwidget() 方法依次将标簽4、标簽5和标簽6添加到垂直布局對象(vBoxLayout3)末尾。
——第32行代碼:通過實例化 QHBoxLayout 類創建一個水平布局對象(hBoxLayout)。
——第33-35行代碼:調用 addLayout() 方法依次将垂直布局對象(vBoxLayout1、vBoxLayout2、vBoxLayout3)添加到水平布局對象(hBoxLayout)末尾。
——第37行代碼:通過調用 setContentsMargins() 方法設置垂直布局對象(vBoxLayout1)的4個方向上的内容邊距(左側邊距=0,頂部邊距=0,右側邊距=0,底部邊距=20)。
——第38行代碼:通過調用 setContentsMargins() 方法設置垂直布局對象(vBoxLayout2)的4個方向上的内容邊距(左側邊距=10,頂部邊距=10,右側邊距=20,底部邊距=10)。
——第39行代碼:通過調用 setContentsMargins() 方法設置垂直布局對象(vBoxLayout3)的4個方向上的内容邊距(左側邊距=0,頂部邊距=20,右側邊距=0,底部邊距=0)。
——第40行代碼:通過調用 setContentsMargins() 方法設置水平布局對象(hBoxLayout)的4個方向上的内容邊距(左側邊距=0,頂部邊距=0,右側邊距=0,底部邊距=0)。
——第42行代碼:通過調用窗口對象(window)的 setLayout() 方法将水平布局對象(hBoxLayout)設置為窗口對象的布局管理器。
——第44行代碼:調用窗口的 setCentralWidget() 方法設置主窗口的中央部件為窗口對象(window)。
——第45行代碼:調用窗口的 setWindowTitle() 方法設置主窗口的标題為"布局内容邊距示例程序"。
三、設置文件運行入口部分
最後,在設置文件運行入口部分,完成創建應用程序、創建和顯示自定義主窗口、運行應用程序直至退出。
if __name__ == "__main__": import sys app = QApplication(sys.argv) win = MyMainWindow() win.show() sys.exit(app.exec_())
——第1行代碼:通過 if __name__ == "__main__": 語句來設置文件運行入口。
——第2行代碼:導入 Python 内置的 sys 模塊,接下的 sys.argv 和 sys.ext() 會用到該模塊。
——第4行代碼:使用 QApplication 類創建一個應用程序對象(app),括号内的 sys.argv 表示構造時含的傳遞參數。
——第5行代碼:使用自定義的 MyMainWindow 類創建應用程序的主窗口對象(win)。
——第6行代碼:調用主窗口對象(win)的 show() 方法來顯示該主窗口。
——第7行代碼:運行應用程序,直至退出。
5.5 示例程序運行直接在 Visual Studio Code 上點擊主窗體上運行圖标按鈕來運行該示例程序。
布局内容邊距示例程序運行窗口
上圖是程序運行後的窗口,可以看到已經實現布局内容邊距示例目标:
——最外層紅框表示水平布局,該布局4個方向上的内容邊距均為0,所以看不見水平布局内容邊距。
——裡面最左側是一個垂直布局(放置标簽1),該布局4個方向上的内容邊距依次為(0, 0, 0, 20),所以隻能看見該垂直布局的底部邊距。
——裡面中間的藍框是一個垂直布局(其中從上往下依次放置标簽2和标簽3),該布局4個方向上的内容邊距依次為(10, 10, 20, 10),所以能看見該垂直布局的4個方向上的内容邊距。
——裡面右側的綠框是一個垂直布局(其中從上往下依次放置标簽4、标簽5和标簽6),該布局4個方向上的内容邊距依次為(0, 20, 0, 0),所以隻能看見該垂直布局的頂部邊距。
——在拉伸(或壓縮)窗口時,各标簽安裝默認的尺寸策略進行自适應同步縮放。
——在拉伸(或壓縮)窗口時,标簽四周的内容邊距以及各個标簽之間的間距始終保持不變。
注:上圖運行窗口中并沒有紅框、藍框,均為進行說明後加的。
6. 布局間距示例6.1 示例原型在進行 GUI 應用程序編碼之前,一般建議先勾畫出 GUI 框架(窗體及各部件的布局等)。本示例原型如下:
布局間距示例原型
6.2 示例目标本示例目标是創建一個 Python GUI 應用程序,在主窗口中如原型圖示放置6個标簽。
主窗口及部件的位置、尺寸及其他屬性如下:
- 主窗口
——(1) 窗口位置及尺寸采用尺寸提示(默認大小)
——(2) 标題:布局内容邊距示例程序
——(3) 具有窗口最小化、最大化、關閉快捷按鈕
- 6個标簽
——(1) 位置:如原型圖示放置排列
——(2) 尺寸:采用尺寸提示(默認大小)
——(3) 尺寸:6個标簽文本依次為:“标簽一”、"标簽二"、"标簽三"、"标簽四"、"标簽五"、"标簽六"
——(4) 背景色:6個标簽依次為“SkyBlue”、“Pink”、“PaleGreen”、“Cyan”、“Gold”、“Orange”
- 各布局内容邊距
——最外層紅框表示水平布局,該布局4個方向上的内容邊距均為0。其他布局的内容邊距為默認值。
- 各布局間距
——最外層紅框表示水平布局,該布局間距為5。
——裡面最左側是一個垂直布局(放置标簽1),該布局間距為0。
——裡面中間的藍框是一個垂直布局(其中從上往下依次放置标簽2和标簽3),該布局間距為10。
——裡面右側的綠框是一個垂直布局(其中從上往下依次放置标簽4、标簽5和标簽6),該布局間距為15。
- 窗口縮放時各部件按默認的尺寸策略自動進行自适應調整
——在拉伸(或壓縮)窗口時,各标簽安裝默認的尺寸策略進行自适應同步縮放。
——在拉伸(或壓縮)窗口時,标簽四周的内容邊距以及各個标簽之間的間距始終保持不變。
6.3 示例代碼利用 Visual Studio Code 編輯代碼,并保存為文件(如:C:\MyPySide6\MyPySide6LayoutSpacingApp.py)。
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLabel) class MyMainWindow(QMainWindow): def __init__(self): super(MyMainWindow, self).__init__() window = QWidget() label_1 = QLabel("标簽一") label_2 = QLabel("标簽二") label_3 = QLabel("标簽三") label_4 = QLabel("标簽四") label_5 = QLabel("标簽五") label_6 = QLabel("标簽六") label_1.setStyleSheet("background-color: SkyBlue;") label_2.setStyleSheet("background-color: Pink;") label_3.setStyleSheet("background-color: PaleGreen;") label_4.setStyleSheet("background-color: Cyan;") label_5.setStyleSheet("background-color: Gold;") label_6.setStyleSheet("background-color: Orange;") vBoxLayout1 = QVBoxLayout() vBoxLayout1.addWidget(label_1) vBoxLayout2 = QVBoxLayout() vBoxLayout2.addWidget(label_2) vBoxLayout2.addWidget(label_3) vBoxLayout3 = QVBoxLayout() vBoxLayout3.addWidget(label_4) vBoxLayout3.addWidget(label_5) vBoxLayout3.addWidget(label_6) hBoxLayout = QHBoxLayout() hBoxLayout.addLayout(vBoxLayout1) hBoxLayout.addLayout(vBoxLayout2) hBoxLayout.addLayout(vBoxLayout3) hBoxLayout.setContentsMargins(0, 0, 0, 0) vBoxLayout1.setSpacing(0) vBoxLayout2.setSpacing(10) vBoxLayout3.setSpacing(15) hBoxLayout.setSpacing(5) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局間距示例程序") if __name__ == '__main__': import sys app = QApplication(sys.argv) gui = MyMainWindow() gui.show() sys.exit(app.exec_())
6.4 代碼解析本示例代碼共分三部分:
一、導入模塊(或類)部分
此部分代碼解析請參見本文第5.4章節中對應部分的代碼解析内容(完全一樣)。
二、自定義MyMainWindow類部分
其次,自定義 MyMainWindow 類(即主窗口,繼承自 QMainWindow 類):
class MyMainWindow(QMainWindow): def __init__(self): super(MyMainWindow, self).__init__() window = QWidget() label_1 = QLabel("标簽一") label_2 = QLabel("标簽二") label_3 = QLabel("标簽三") label_4 = QLabel("标簽四") label_5 = QLabel("标簽五") label_6 = QLabel("标簽六") label_1.setStyleSheet("background-color: SkyBlue;") label_2.setStyleSheet("background-color: Pink;") label_3.setStyleSheet("background-color: PaleGreen;") label_4.setStyleSheet("background-color: Cyan;") label_5.setStyleSheet("background-color: Gold;") label_6.setStyleSheet("background-color: Orange;") vBoxLayout1 = QVBoxLayout() vBoxLayout1.addWidget(label_1) vBoxLayout2 = QVBoxLayout() vBoxLayout2.addWidget(label_2) vBoxLayout2.addWidget(label_3) vBoxLayout3 = QVBoxLayout() vBoxLayout3.addWidget(label_4) vBoxLayout3.addWidget(label_5) vBoxLayout3.addWidget(label_6) hBoxLayout = QHBoxLayout() hBoxLayout.addLayout(vBoxLayout1) hBoxLayout.addLayout(vBoxLayout2) hBoxLayout.addLayout(vBoxLayout3) hBoxLayout.setContentsMargins(0, 0, 0, 0) vBoxLayout1.setSpacing(0) vBoxLayout2.setSpacing(10) vBoxLayout3.setSpacing(15) hBoxLayout.setSpacing(5) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局間距示例程序")
——第1-35行代碼:請參見本文第5.4章節的代碼解析内容(完全一樣)。
——第37行代碼:通過調用 setContentsMargins() 方法設置水平布局對象(hBoxLayout)的4個方向上的内容邊距(左側邊距=0,頂部邊距=0,右側邊距=0,底部邊距=0)。
——第38行代碼:通過調用 setSpacing() 方法設置垂直布局對象(vBoxLayout1)的間距為0。
——第39行代碼:通過調用 setSpacing() 方法設置垂直布局對象(vBoxLayout2)的間距為10。
——第40行代碼:通過調用 setSpacing() 方法設置垂直布局對象(vBoxLayout3)的間距為15。
——第41行代碼:通過調用 setSpacing() 方法設置水平布局對象(hBoxLayout)的間距為5。
——第43行代碼:通過調用窗口對象(window)的 setLayout() 方法将水平布局對象(hBoxLayout)設置為窗口對象的布局管理器。
——第45行代碼:調用窗口的 setCentralWidget() 方法設置主窗口的中央部件為窗口對象(window)。
——第46行代碼:調用窗口的 setWindowTitle() 方法設置主窗口的标題為"布局間距示例程序"。
三、設置文件運行入口部分
此部分代碼解析請參加本文第5.4章節中對應部分的代碼解析内容(完全一樣)。
6.5 示例程序運行直接在 Visual Studio Code 上點擊主窗體上運行圖标按鈕來運行該示例程序。
布局間距示例程序運行窗口
上圖是程序運行後的窗口,可以看到已經實現布局間距示例目标:
——最外層紅框表示水平布局,其間距為5(即裡面的3個垂直布局之間的間距為5,有2處)。
——裡面最左側是一個垂直布局(放置标簽1),其間距為0。
——裡面中間的藍框是一個垂直布局(其中從上往下依次放置标簽2和标簽3),其間距為10(即裡面的标簽2和标簽3之間的間距為10,有1處)。
——裡面右側的綠框是一個垂直布局(其中從上往下依次放置标簽4、标簽5和标簽6),其間距為15(即裡面的标簽4、标簽5和标簽6之間的間距為15,有2處)。
——在拉伸(或壓縮)窗口時,各标簽安裝默認的尺寸策略進行自适應同步縮放。
——在拉伸(或壓縮)窗口時,标簽四周的内容邊距以及各個标簽之間的間距始終保持不變。
注:上圖運行窗口中并沒有紅框、藍框,均為進行說明後加的。
7. 布局間隔部件示例7.1 示例原型在進行 GUI 應用程序編碼之前,一般建議先勾畫出 GUI 框架(窗體及各部件的布局等)。本示例原型如下:
布局間隔部件示例原型
7.2 示例目标本示例目标是創建一個 Python GUI 應用程序,在主窗口中如原型圖示放置6個标簽。
本示例目标基于第6.2章節示例目标,不同之處在于用間隔部件實現相同效果。
7.3 示例代碼本示例代碼基于第6.3章節示例代碼修改。
利用 Visual Studio Code 編輯代碼,并另存為文件(如:C:\MyPySide6\MyPySide6LayoutQSpacerItemApp.py)。
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QSpacerItem) class MyMainWindow(QMainWindow): def __init__(self): super(MyMainWindow, self).__init__() window = QWidget() label_1 = QLabel("标簽一") label_2 = QLabel("标簽二") label_3 = QLabel("标簽三") label_4 = QLabel("标簽四") label_5 = QLabel("标簽五") label_6 = QLabel("标簽六") label_1.setStyleSheet("background-color: SkyBlue;") # 135 206 255 #87CEFF label_2.setStyleSheet("background-color: Pink;") # 255 192 203 #FFC0CB label_3.setStyleSheet("background-color: PaleGreen;") # 152 251 152 #98FB98 label_4.setStyleSheet("background-color: Cyan;") # 0 255 255 #00FFFF label_5.setStyleSheet("background-color: Gold;") # 255 215 0 #FFD700 label_6.setStyleSheet("background-color: Orange;") # 255 165 0 #FFA500 vBoxLayout1 = QVBoxLayout() vBoxLayout1.addWidget(label_1) vBoxLayout2 = QVBoxLayout() vBoxLayout2.addWidget(label_2) vBoxLayout2.addWidget(label_3) vBoxLayout3 = QVBoxLayout() vBoxLayout3.addWidget(label_4) vBoxLayout3.addWidget(label_5) vBoxLayout3.addWidget(label_6) hBoxLayout = QHBoxLayout() hBoxLayout.addLayout(vBoxLayout1) hBoxLayout.addLayout(vBoxLayout2) hBoxLayout.addLayout(vBoxLayout3) hBoxLayout.setContentsMargins(0, 0, 0, 0) hBoxLayout.setSpacing(0) vBoxLayout2.insertSpacing(1, 10) vBoxLayout3.insertSpacing(1, 15) vBoxLayout3.insertSpacing(3, 15) hBoxLayout.insertSpacing(1, 5) spacerItem = QSpacerItem(5, 5) hBoxLayout.insertSpacerItem(3, spacerItem) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局間隔部件示例程序") if __name__ == '__main__': import sys app = QApplication(sys.argv) gui = MyMainWindow() gui.show() sys.exit(app.exec_())
7.4 代碼解析本示例代碼基于第6.3章節示例代碼修改,所以就隻對有變化的代碼語句進行解析了。
本示例代碼共分三部分:
一、導入模塊(或類)部分
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QSpacerItem)
——第1行代碼:表示從 PySide6.QtWidgets 模塊導入後續代碼中會用到的 QApplication 類、QMainWindow 類、QWidget 類、QHBoxLayout 類、QLabel 類、QSpacerItem 類。
二、自定義MyMainWindow類部分
其次,自定義 MyMainWindow 類(即主窗口,繼承自 QMainWindow 類):
class MyMainWindow(QMainWindow): def __init__(self): ...... hBoxLayout.setContentsMargins(0, 0, 0, 0) hBoxLayout.setSpacing(0) vBoxLayout2.insertSpacing(1, 10) vBoxLayout3.insertSpacing(1, 15) vBoxLayout3.insertSpacing(3, 15) hBoxLayout.insertSpacing(1, 5) spacerItem = QSpacerItem(5, 5) hBoxLayout.insertSpacerItem(3, spacerItem) window.setLayout(hBoxLayout) self.setCentralWidget(window) self.setWindowTitle("布局間隔部件示例程序")
在原示例代碼上第39行(hBoxLayout.setContentsMargins(0, 0, 0, 0))與第45行代碼(window.setLayout(hBoxLayout))之間新增相關代碼語句:
——第40行代碼:通過調用 setSpacing(spacing) 方法設置水平布局内各子布局或部件之間的間距值(為0)。
——第42行代碼:通過調用 insertSpacing() 方法在垂直布局對象2的指定位置(索引值為1,即标簽2和标簽3之間)插入一個固定尺寸(10px)的間隔部件。
——第43行代碼:通過調用 insertSpacing() 方法在垂直布局對象3的指定位置(索引值為1,即标簽4和标簽5之間)插入一個固定尺寸(15px)的間隔部件。
——第44行代碼:通過調用 insertSpacing() 方法在垂直布局對象3的指定位置(索引值為3,即标簽5和标簽6之間)插入一個固定尺寸(15px)的間隔部件。
——第45行代碼:通過調用 insertSpacing() 方法在水平布局對象的指定位置(索引值為1,即垂直布局對象1和垂直布局對象2之間)插入一個固定尺寸(5px)的間隔部件。
——第46行代碼:通過實例化 QSpacerItem 類創建一個間隔部件對象(spacerItem),構造時設置其寬度和高度均為5px。
——第47行代碼:通過調用 insertSpacerItem() 方法在水平布局對象的指定位置(索引值為3,即垂直布局對象2和垂直布局對象3之間)插入一個指定的間隔部件對象(spacerItem)。
——第52行代碼:調用窗口的 setWindowTitle() 方法設置主窗口的标題為"布局間隔部件示例程序"。
三、設置文件運行入口部分
此部分代碼解析請參加本文第5.4章節中對應部分的代碼解析内容(完全一樣)。
7.5 示例程序運行直接在 Visual Studio Code 上點擊主窗體上運行圖标按鈕來運行該示例程序。
布局間隔部件示例程序運行窗口
上圖是程序運行後的窗口,對比第6.5章節的示例程序運行窗口,發現實現了相同效果。
結束語本文是《Qt for Python 學習筆記》系列第十三篇,較為詳細地介紹了 Qt for Python 布局管理中的布局内容邊距和布局間距相關内容,讓讀者對此有個較為全面的了解和掌握。
接下來會介紹 Qt for Python 布局管理中的網格布局,敬請期待!
希望本文能對您有所幫助!若文中存在疏忽不足或錯誤,還請不吝賜教!
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!