PyQt 布局創建具有專業外觀的 GUI 應用程序

      網友投稿 986 2022-05-30

      目錄

      在 GUI 上布置圖形元素

      掌握 PyQt 布局庫

      使用通用布局管理器

      構建水平布局:QHBoxLayout

      構建垂直布局:QVBoxLayout

      在網格中排列小部件:QGridLayout

      快速創建表單:QFormLayout

      嵌套布局以構建復雜的 GUI

      使用多頁布局和小部件

      創建一堆小部件

      使用 PyQt 的 Tab 小部件

      布置應用程序的主窗口

      PyQt 布局:創建具有專業外觀的 GUI 應用程序

      布置應用程序的對話框

      在 PyQt 布局中管理空間

      管理框布局中的空間

      管理網格和表單布局中的空間

      結論

      PyQt 的布局管理器提供了一種在 GUI 上排列圖形組件或小部件的用戶友好且高效的方式。正確布置小部件將使您的GUI 應用程序看起來精美和專業。學習高效地這樣做是您開始使用 Python 和 PyQt 進行 GUI 應用程序開發的一項基本技能。

      在本教程中,您將學習:

      使用 PyQt 的布局管理器有什么好處

      如何使用 PyQt 的布局管理器以編程方式在 GUI 上布置小部件

      如何為您的 GUI 應用程序選擇正確的布局管理器

      如何鋪陳在小部件主窗口為基礎的和基于對話框的應用程序

      憑借這些知識和技能,您將能夠使用 Python 和 PyQt 創建具有專業外觀的 GUI 應用程序。

      為了更好地理解如何使用布局管理器,一些關于如何創建PyQt GUI 應用程序以及如何使用PyQt 小部件的先前知識會有所幫助。

      在 GUI 上布置圖形元素

      當您創建圖形用戶界面 (GUI)應用程序時,一個常見的問題是如何讓您的圖形組件(按鈕、菜單、工具欄、標簽等)在您的窗體和窗口上連貫地布置。此過程稱為GUI 布局,它是創建 GUI 應用程序的重要步驟。

      過去,如果您想在窗口上布置圖形組件或小部件,則可以采用以下方法之一:

      決定并手動設置窗口上每個小部件的靜態大小和位置。

      動態計算和設置每個小部件的大小和位置。

      第一種方法相當直接,但它至少有以下缺點:

      您的窗口將無法調整大小,這可能會導致在不同屏幕分辨率上顯示它們時出現問題。

      您的標簽可能無法正確支持本地化,因為給定文本的長度因語言而異。

      您的小部件在不同平臺上的顯示方式不同,這使得編寫看起來不錯的多平臺應用程序變得困難。

      第二種方法更靈活。但是,它也有缺點:

      您必須進行大量手動計算才能確定每個小部件的正確大小和位置。

      您必須進行一些額外的計算才能正確響應窗口大小調整。

      每次修改窗口布局時,都必須重做所有計算。

      盡管您仍然可以使用這兩種方法中的任何一種來布置您的 GUI,但大多數時候您會想要使用大多數現代GUI 框架或工具包實現的第三種更方便的方法:布局管理器。

      注意:在一些 GUI 框架中,例如Tkinter,布局管理器也被稱為幾何管理器。

      布局管理器會根據您的特定需求在 GUI 上自動排列小部件。它們避免了第一種方法的兼容性缺陷以及第二種方法的煩人和復雜的計算。

      在以下部分中,您將了解 PyQt 的內置布局管理器以及如何使用它們來有效地布置 GUI 應用程序的圖形組件。

      掌握 PyQt 布局庫

      在 PyQt 中,小部件是用作 GUI 應用程序構建塊的圖形組件。當你在一個窗口上放置一堆小部件來創建一個 GUI 時,你需要給它們一些順序。您需要設置窗口小部件的大小和位置,還需要定義它們在用戶調整底層窗口大小時的行為。

      注意:不幸的是,PyQt5 的官方文檔有一些不完整的部分。要解決此問題,您可以查看PyQt4 文檔、Qt for Python 文檔或原始Qt 文檔。

      在本教程中,您會發現大多數鏈接都會將您帶到原始 Qt 文檔,在大多數情況下,這是更好的信息來源。

      要在 PyQt 中的窗口或表單上排列小部件,您可以使用以下技術:

      在您的小部件上使用.resize()和.move()以提供絕對大小和位置。

      重新實現.resizeEvent()并動態計算小部件的大小和位置。

      使用布局管理器,讓他們為您完成所有的計算和繁重的工作。

      這些技術通常對應于您在上一節中看到的用于布置 GUI 的三種不同方法。

      同樣,動態計算大小和位置可能是一個很好的方法,但大多數時候使用布局管理器會更好。在 PyQt 中,布局管理器是提供所需功能以自動管理布局中小部件的大小、位置和調整大小行為的類。

      使用布局管理器,您可以在任何父或容器、小部件中自動排列子小部件。使用布局管理器將確保您充分利用 GUI 上的可用空間,并且當用戶調整窗口大小時,您的應用程序仍然可用。

      布局管理器用作小部件和其他布局的容器。要將小部件添加到布局管理器,您可以調用.addWidget()手頭的布局。要將布局添加到另一個布局,請調用.addLayout()手頭的布局。您將在嵌套布局以構建復雜 GUI部分中更深入地研究嵌套布局。

      將所有必需的小部件添加到布局管理器后,您可以使用.setLayout().?您可以在 的任何子類上設置布局管理器QWidget,包括窗口或表單。

      注意:?QMainWindow是一個 PyQt 類,可用于創建主要寡婦風格的應用程序。這個類有它自己的內置布局管理器。因此,如果您使用的是QMainWindow,那么您通常不需要在主窗口對象上設置布局管理器。

      布局中的所有小部件都會自動設置為安裝布局的小部件的子代,而不是布局本身的子代。那是因為小部件只能將其他小部件而不是布局作為其父級。

      PyQt 的布局管理器提供了一些很酷的功能,讓您在創建漂亮的 GUI 應用程序時變得更加輕松:

      無需任何計算即可處理小部件的大小和位置

      當用戶調整底層窗口大小時處理小部件的調整大小和重新定位

      調整標簽大小以更好地支持國際化

      為多平臺應用程序提供本機窗口布局

      從長遠來看,使用布局管理器還可以顯著提高您的生產力并提高代碼的可維護性。

      PyQt 提供了四個通用布局管理器類:

      QHBoxLayout?在水平框中排列小部件。

      QVBoxLayout?在垂直框中排列小部件。

      QGridLayout?在網格中排列小部件。

      QFormLayout?在兩列中排列小部件。

      在接下來的幾節中,您將學習如何使用這些通用布局管理器的基礎知識。

      使用通用布局管理器

      使用 PyQt 創建 GUI 應用程序時,您通常會使用您在上一節末尾看到的四種通用布局中的一種或多種, 以在窗口和窗體上布置小部件。

      在接下來的幾節中,您將在一些示例的幫助下學習如何創建和使用四個通用布局管理器。

      建筑水平布局:?QHBoxLayout

      框布局管理器從父布局或小部件中獲取空間,將其劃分為多個框或單元格,并使布局中的每個小部件填充一個框。

      QHBoxLayout是 PyQt 中兩種可用的框布局之一。此布局管理器允許您水平排列小部件,一個挨著另一個。小部件從左到右添加到布局中。這意味著您首先在代碼中添加的小部件將是布局中最左側的小部件。

      要將小部件添加到QHBoxLayout對象,請調用.addWidget(widget, stretch, alignment)布局對象。此方法采用一個必需參數和兩個可選參數:

      widget?是一個必需參數,用于保存要添加到布局中的特定小部件。

      stretch是一個可選參數,它包含一個整數,表示要應用于的拉伸因子widget。具有更高拉伸系數的小部件在調整窗口大小時增長得更多。它默認為0,這意味著小部件沒有分配拉伸因子。

      alignment是一個可選參數,用于保存水平和垂直標志。您可以組合這些標志以在其包含的單元格內生成所需的小部件對齊方式。它默認為0,這意味著小部件將填充整個單元格。

      這是一個小應用程序,展示了如何使用QHBoxLayout.?在此示例中,您將使用QPushButton對象根據將小部件添加到代碼中的順序更好地可視化每個小部件在布局中的放置位置:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QHBoxLayout, 6 QPushButton, 7 QWidget, 8) 9 10class Window(QWidget): 11 def __init__(self): 12 super().__init__() 13 self.setWindowTitle("QHBoxLayout Example") 14 # Create a QHBoxLayout instance 15 layout = QHBoxLayout() 16 # Add widgets to the layout 17 layout.addWidget(QPushButton("Left-Most")) 18 layout.addWidget(QPushButton("Center"), 1) 19 layout.addWidget(QPushButton("Right-Most"), 2) 20 # Set the layout on the application's window 21 self.setLayout(layout) 22 print(self.children()) 23 24if __name__ == "__main__": 25 app = QApplication(sys.argv) 26 window = Window() 27 window.show() 28 sys.exit(app.exec_())

      在第 15 行,您創建了一個QHBoxLayout名為的對象layout。在第 17 到 19 行,您將三個按鈕添加到layoutusing?.addWidget()。請注意,您分別將1和傳遞2到Center和Right-Most按鈕中的stretch參數。在第 21 行,您使用.layout.setLayout()

      注意:如果您不熟悉使用 PyQt 進行 GUI 編程,那么您可以查看Python 和 PyQt:構建 GUI 桌面計算器,以更好地了解如何使用 PyQt 創建 GUI 應用程序。

      如果您運行此應用程序,您將在屏幕上看到以下窗口:

      該窗口包含以水平方式排列的三個按鈕。請注意,最左側按鈕對應于您在代碼中添加的第一個按鈕。因此,按鈕的顯示順序(從左到右)與您在代碼中添加的順序(從上到下)相同。

      該中心和最右邊的按鈕具有不同的拉伸因素的影響,所以他們按比例這些因素擴大,當你調整窗口的大小。

      此外,其中的所有按鈕layout和布局本身都設置為Window.?這是由內部調用.setParent()每個小部件的布局對象自動完成的。print()對第 22 行的調用Window在您的終端上打印了 的子項列表作為此行為的證據。

      建筑垂直布局:?QVBoxLayout

      QVBoxLayout垂直排列小部件,一個在另一個下方。您可以使用此類來創建垂直布局并從上到下排列您的小部件。由于QVBoxLayout是另一種盒子布局,它的.addWidget()方法與QHBoxLayout.

      這是一個 PyQt 應用程序,它展示了如何創建和使用QVBoxLayout對象來在您的 GUI 中創建垂直排列的小部件:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QPushButton, 6 QVBoxLayout, 7 QWidget, 8) 9 10class Window(QWidget): 11 def __init__(self): 12 super().__init__() 13 self.setWindowTitle("QVBoxLayout Example") 14 self.resize(270, 110) 15 # Create a QVBoxLayout instance 16 layout = QVBoxLayout() 17 # Add widgets to the layout 18 layout.addWidget(QPushButton("Top")) 19 layout.addWidget(QPushButton("Center")) 20 layout.addWidget(QPushButton("Bottom")) 21 # Set the layout on the application's window 22 self.setLayout(layout) 23 24if __name__ == "__main__": 25 app = QApplication(sys.argv) 26 window = Window() 27 window.show() 28 sys.exit(app.exec_())

      在第 16 行,您創建了一個QVBoxLayout.?在第 18 到 20 行,您將三個按鈕添加到layout。最后,您設置layout為窗口的頂級布局。

      如果您運行此應用程序,您將看到以下窗口:

      您的窗口顯示垂直排列的三個按鈕,一個在另一個下方。這些按鈕的顯示順序(從上到下)與您在代碼中添加它們的順序(從上到下)相同。

      在網格中排列小部件:?QGridLayout

      您可以使用在行和列QGridLayout的網格中排列小部件。每個小部件在網格中都有一個相對位置。要定義小部件的位置或網格中的單元格,您可以使用表單的一對坐標(row, column)。這些坐標應該是從零開始的整數。

      QGridLayout獲取其父級上的可用空間,將其劃分為行和列,并將每個小部件放入其自己的單元格或框中。QGridLayout根據小部件的數量及其坐標自動計算出最終布局將有多少行和列。如果您不向給定單元格添加小部件,則QGridLayout將該單元格留空。

      要將小部件添加到網格布局,請調用.addWidget()布局。該方法有兩種不同的重載實現:

      addWidget(widget, row, column, alignment)添加widget到 (?row,?column)處的單元格。

      addWidget(widget, fromRow, fromColumn, rowSpan, columnSpan, alignment)添加widget到單元格,跨越多行、多列或兩者兼而有之。

      第一個實現采用以下參數:

      widget?是一個必需參數,用于保存您需要添加到布局中的特定小部件。

      row?是一個必需的參數,它保存一個整數,表示網格中一行的坐標。

      column?是一個必需的參數,它包含一個表示網格中列坐標的整數。

      alignment是一個可選參數,用于保存小部件在其包含單元格內的對齊方式。它默認為0,這意味著小部件將填充整個單元格。

      以下是如何使用QGridLayout創建小部件網格的示例:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QGridLayout, 6 QPushButton, 7 QWidget, 8) 9 10class Window(QWidget): 11 def __init__(self): 12 super().__init__() 13 self.setWindowTitle("QGridLayout Example") 14 # Create a QGridLayout instance 15 layout = QGridLayout() 16 # Add widgets to the layout 17 layout.addWidget(QPushButton("Button at (0, 0)"), 0, 0) 18 layout.addWidget(QPushButton("Button at (0, 1)"), 0, 1) 19 layout.addWidget(QPushButton("Button at (0, 2)"), 0, 2) 20 layout.addWidget(QPushButton("Button at (1, 0)"), 1, 0) 21 layout.addWidget(QPushButton("Button at (1, 1)"), 1, 1) 22 layout.addWidget(QPushButton("Button at (1, 2)"), 1, 2) 23 layout.addWidget(QPushButton("Button at (2, 0)"), 2, 0) 24 layout.addWidget(QPushButton("Button at (2, 1)"), 2, 1) 25 layout.addWidget(QPushButton("Button at (2, 2)"), 2, 2) 26 # Set the layout on the application's window 27 self.setLayout(layout) 28 29if __name__ == "__main__": 30 app = QApplication(sys.argv) 31 window = Window() 32 window.show() 33 sys.exit(app.exec_())

      在第 15 行,您創建了QGridLayout對象。然后,在第 17 到 25 行,您使用 將小部件添加到布局中.addWidget()。要查看網格布局如何在沒有分配小部件的情況下管理單元格,請注釋掉其中的一行或多行并再次運行應用程序。

      如果你從命令行運行這段代碼,你會得到一個這樣的窗口:

      QGridLayout對象中的每個小部件占用由您在 中提供的坐標對定義的單元格.addWidget()。每個按鈕上的文本反映了這些坐標。坐標從零開始,因此第一個單元格位于(0, 0)。

      在 的第二個實現中.addWidget(),參數widget和alignment保持不變,您還有四個額外的參數,允許您將小部件放置在多行或多列中:

      fromRow?采用一個整數表示小部件將在其中開始的行。

      fromColumn?采用一個整數表示小部件將在其中啟動的列。

      rowSpan?采用一個整數表示小部件將在網格中占據的行數。

      columnSpan?采用一個整數表示小部件將在網格中占據的列數。

      這是一個應用程序,顯示了這種變體的.addWidget()工作原理:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QGridLayout, 6 QPushButton, 7 QWidget, 8) 9 10class Window(QWidget): 11 def __init__(self): 12 super().__init__() 13 self.setWindowTitle("QGridLayout Example") 14 # Create a QGridLayout instance 15 layout = QGridLayout() 16 # Add widgets to the layout 17 layout.addWidget(QPushButton("Button at (0, 0)"), 0, 0) 18 layout.addWidget(QPushButton("Button at (0, 1)"), 0, 1) 19 layout.addWidget(QPushButton("Button Spans two Cols"), 1, 0, 1, 2) 20 # Set the layout on the application's window 21 self.setLayout(layout) 22 23if __name__ == "__main__": 24 app = QApplication(sys.argv) 25 window = Window() 26 window.show() 27 sys.exit(app.exec_())

      在第 19 行,您使用 的第二個實現.addWidget()添加一個占據網格中兩列的按鈕。該按鈕從第二行 (?fromRow=1) 和第一列 (?fromColumn=0) 開始。最后,按鈕占據一行 (?rowSpan=1) 和兩列 (?columnSpan=2)。

      注意:由于PyQt 是Qt的 Python 綁定,Qt是一組C++庫,因此有時在調用 PyQt 方法時不能使用關鍵字參數。上一段中使用的關鍵字參數的唯一目的是顯示分配給每個參數的值。

      如果您運行此應用程序,您將在屏幕上看到以下窗口:

      在這種布局中,您可以使一個小部件占據多個單元格,就像您使用Button Spas two Cols按鈕所做的那樣。

      快速創建表單:?QFormLayout

      如果您經常創建表單來執行諸如將數據輸入數據庫之類的操作,那么QFormLayout適合您。此類以兩列布局排列小部件。第一列通常顯示一個標簽描述預期輸入,和第二列通常包含輸入窗口小部件,例如QLineEdit,QComboBox,或QSpinBox允許用戶輸入或編輯的數據。

      要將小部件添加到表單布局,請使用.addRow().?此方法有多種變體,但大多數情況下,您將從以下兩種中進行選擇:

      .addRow(label, field)在表單布局的底部添加一個新行。該行應包含一個QLabel對象 (?label) 和一個輸入小部件 (?field)。

      .addRow(labelText, field)自動創建并添加一個新QLabel對象labelText作為其文本。field持有一個輸入小部件。

      這是一個使用QFormLayout對象來排列小部件的示例應用程序:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QFormLayout, 6 QLabel, 7 QLineEdit, 8 QWidget, 9) 10 11class Window(QWidget): 12 def __init__(self): 13 super().__init__() 14 self.setWindowTitle("QFormLayout Example") 15 self.resize(270, 110) 16 # Create a QFormLayout instance 17 layout = QFormLayout() 18 # Add widgets to the layout 19 layout.addRow("Name:", QLineEdit()) 20 layout.addRow("Job:", QLineEdit()) 21 emailLabel = QLabel("Email:") 22 layout.addRow(emailLabel, QLineEdit()) 23 # Set the layout on the application's window 24 self.setLayout(layout) 25 26if __name__ == "__main__": 27 app = QApplication(sys.argv) 28 window = Window() 29 window.show() 30 sys.exit(app.exec_())

      在第 17 行,您創建了一個QFormLayout對象。然后,在第 19 到 22 行,向布局添加一些行。請注意,在第 19 行和第 20 行,您使用了該方法的第二個變體,而在第 22 行,您使用了第一個變體,將一個QLabel對象作為第一個參數傳遞給.addRow()。

      如果您運行此代碼,您將在屏幕上看到以下窗口:

      使用QFormLayout,您可以將小部件組織成兩列排列。第一列包含要求用戶提供一些信息的標簽。第二列顯示允許用戶輸入或編輯該信息的小部件。

      嵌套布局以構建復雜的 GUI

      您可以使用嵌套布局來創建使用通用 PyQt 布局管理器之一難以創建的復雜 GUI。要做到這一點,你需要調用.addLayout()上的外部布局。這樣,內部布局就成為外部布局的子項。

      假設您需要創建一個對話框,在表單布局中顯示標簽和行編輯,并且您希望在這些小部件下方以垂直布局放置多個復選框。這是您的對話框應該是什么樣子的模型:

      藍色矩形代表您的外部布局。綠色矩形是用于保存標簽和行編輯的表單布局。紅色矩形是用于放置選項復選框的垂直布局。綠色布局和紅色布局都嵌套在藍色布局中,這是一種垂直布局。

      以下是如何使用 PyQt 構建此布局的示例:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QCheckBox, 6 QFormLayout, 7 QLineEdit, 8 QVBoxLayout, 9 QWidget, 10) 11 12class Window(QWidget): 13 def __init__(self): 14 super().__init__() 15 self.setWindowTitle("Nested Layouts Example") 16 # Create an outer layout 17 outerLayout = QVBoxLayout() 18 # Create a form layout for the label and line edit 19 topLayout = QFormLayout() 20 # Add a label and a line edit to the form layout 21 topLayout.addRow("Some Text:", QLineEdit()) 22 # Create a layout for the checkboxes 23 optionsLayout = QVBoxLayout() 24 # Add some checkboxes to the layout 25 optionsLayout.addWidget(QCheckBox("Option one")) 26 optionsLayout.addWidget(QCheckBox("Option two")) 27 optionsLayout.addWidget(QCheckBox("Option three")) 28 # Nest the inner layouts into the outer layout 29 outerLayout.addLayout(topLayout) 30 outerLayout.addLayout(optionsLayout) 31 # Set the window's main layout 32 self.setLayout(outerLayout) 33 34if __name__ == "__main__": 35 app = QApplication(sys.argv) 36 window = Window() 37 window.show() 38 sys.exit(app.exec_())

      這是您在此代碼中所做的事情:

      在第 17 行,您創建外部或頂級布局,您將使用它作為父布局和窗口的主要布局。在這種情況下,您使用QVBoxLayout是因為您希望小部件在表單上垂直排列。在您的模型中,這是藍色布局。

      在第 19 行,您創建了一個表單布局來保存標簽和行編輯。

      在第 21 行,您將所需的小部件添加到布局中。這相當于您的綠色布局。

      在第 23 行,您創建了一個垂直布局來放置復選框。

      在第 25 到 27 行,添加所需的復選框。這是你的紅色布局。

      在第 29 和 30 行,您嵌套topLayout并optionsLayout在outerLayout.

      就是這樣!如果您運行該應用程序,您將看到如下所示的窗口:

      在此應用程序中,您將兩個不同的布局嵌套在外部布局下以創建窗口的總體布局。在窗口頂部,您使用水平布局放置標簽和行編輯。然后使用垂直布局在其下方放置一些復選框。

      使用多頁布局和小部件

      到目前為止,您已經了解了如何使用傳統的或通用的布局管理器來排列應用程序窗口中的小部件。這些布局管理器將在單頁布局上排列小部件。換句話說,您的 GUI 將始終向用戶顯示相同的小部件集。

      有時,您需要創建一個布局來顯示一組不同的小部件,以響應 GUI 上的某些用戶操作。例如,如果您正在為給定的應用程序創建首選項對話框,那么您可能希望向用戶顯示基于選項卡或多頁的布局,其中每個選項卡或頁面都包含一組不同的密切相關的選項。每次用戶單擊選項卡或頁面時,應用程序都會顯示一組不同的小部件。

      PyQt 提供了一個名為的內置布局QStackedLayout和一些方便的小部件,例如QTabWidget,將允許您創建這種多頁布局。接下來的幾節將帶您了解其中的一些工具。

      創建一堆小部件

      QStackedLayout提供了一個布局管理器,允許您將小部件排列在一個堆棧上,一個在另一個之上。在這種布局中,在給定時間只有一個小部件可見。

      要使用小部件填充堆疊布局,您需要調用.addWidget()布局對象。這會將每個小部件添加到布局的內部小部件列表的末尾。您還可以使用.insertWidget(index)或.removeWidget(widget)分別在小部件列表中的給定位置插入或刪除小部件。

      小部件列表中的每個小部件都顯示為一個獨立的頁面。如果要在頁面上顯示多個小部件,QWidget則為每個頁面使用一個對象,并為頁面小部件設置適當的小部件布局。如果需要獲取布局中的小部件(頁面)總數,則可以調用.count().

      使用QStackedLayout對象時要記住的一個重要點是您需要明確提供一種機制來在頁面之間切換。否則,您的布局將始終向用戶顯示相同的頁面。要在頁面之間切換,您需要調用.setCurrentIndex()布局對象。

      下面的示例展示了如何使用帶有組合框的堆疊布局在頁面之間切換:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QComboBox, 6 QFormLayout, 7 QLineEdit, 8 QStackedLayout, 9 QVBoxLayout, 10 QWidget, 11) 12 13class Window(QWidget): 14 def __init__(self): 15 super().__init__() 16 self.setWindowTitle("QStackedLayout Example") 17 # Create a top-level layout 18 layout = QVBoxLayout() 19 self.setLayout(layout) 20 # Create and connect the combo box to switch between pages 21 self.pageCombo = QComboBox() 22 self.pageCombo.addItems(["Page 1", "Page 2"]) 23 self.pageCombo.activated.connect(self.switchPage) 24 # Create the stacked layout 25 self.stackedLayout = QStackedLayout() 26 # Create the first page 27 self.page1 = QWidget() 28 self.page1Layout = QFormLayout() 29 self.page1Layout.addRow("Name:", QLineEdit()) 30 self.page1Layout.addRow("Address:", QLineEdit()) 31 self.page1.setLayout(self.page1Layout) 32 self.stackedLayout.addWidget(self.page1) 33 # Create the second page 34 self.page2 = QWidget() 35 self.page2Layout = QFormLayout() 36 self.page2Layout.addRow("Job:", QLineEdit()) 37 self.page2Layout.addRow("Department:", QLineEdit()) 38 self.page2.setLayout(self.page2Layout) 39 self.stackedLayout.addWidget(self.page2) 40 # Add the combo box and the stacked layout to the top-level layout 41 layout.addWidget(self.pageCombo) 42 layout.addLayout(self.stackedLayout) 43 44 def switchPage(self): 45 self.stackedLayout.setCurrentIndex(self.pageCombo.currentIndex()) 46 47if __name__ == "__main__": 48 app = QApplication(sys.argv) 49 window = Window() 50 window.show() 51 sys.exit(app.exec_())

      在第 21 到 23 行,您創建了一個QComboBox對象,允許您在布局中的頁面之間切換。然后將兩個選項添加到列表中的組合框并將其連接到.switchPage(),用于處理頁面切換。

      在內部.switchPage(),您調用.setCurrentIndex()布局對象,將組合框的當前索引作為參數傳遞。這樣,當用戶更改組合框中的選項時,堆疊布局上的頁面也會相應更改。

      在第 25 行,您創建了QStackedLayout對象。在第 27 到 32 行,您將第一頁添加到布局,并在第 34 到 39 行,您添加第二頁。每個頁面都由一個QWidget對象表示,該對象在一個方便的布局中包含多個小部件。

      使一切正常工作的最后一步是將組合框和布局添加到應用程序的主布局中。

      以下是您的應用程序現在的行為方式:

      在這種情況下,您的應用程序布局中有兩個頁面。每個頁面都由一個QWidget對象表示。當您在窗口頂部的組合框中選擇新頁面時,布局會更改以顯示所選頁面。

      注意:?PyQt 提供了一個名為 的方便類QStackedWidget,它構建在QStackedLayout.?您還可以使用此類來創建多頁布局。

      此類提供了一堆小部件,其中一次只能看到一個小部件。就像堆疊布局一樣,QStackedWidget不提供在頁面之間切換的內在機制。

      除了堆疊布局和堆疊小部件,您還可以使用它QTabWidget來創建多頁用戶界面。您將在下一節中了解如何操作。

      使用 PyQt 的 Tab 小部件

      在 PyQt 中創建多頁排列的另一種流行方法是使用名為QTabWidget.?這個類提供了一個標簽欄和一個頁面區域。您可以使用標簽欄在頁面之間切換,使用頁面區域來顯示與所選標簽關聯的頁面。

      標簽欄默認位于頁面區域的頂部。但是,您可以使用.setTabPosition()和 四個可能的選項卡位置之一更改此行為:

      要將選項卡添加到選項卡小部件,請使用.addTab().?此方法有兩種變體或重載實現:

      .addTab(page, label)

      .addTab(page, icon, label)

      在這兩種情況下,該方法都會添加一個新選項卡,label作為選項卡的標題。page需要是一個小部件,代表與手頭標簽關聯的頁面。

      在方法的第二個變體中,icon需要是一個QIcon對象。如果您將圖標傳遞給.addTab(),則該圖標將顯示在選項卡標題的左側。

      創建選項卡小部件時的常見做法是QWidget為每個頁面使用一個對象。這樣,您就可以使用包含所需小部件的布局向頁面添加額外的小部件。

      大多數情況下,您將使用選項卡小部件為 GUI 應用程序創建對話框。這種布局允許您在相對較小的空間中向用戶呈現多個選項。您還可以利用選項卡系統根據某些分類標準來組織您的選項。

      這是一個示例應用程序,展示了如何創建和使用QTabWidget對象的基礎知識:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QCheckBox, 6 QTabWidget, 7 QVBoxLayout, 8 QWidget, 9) 10 11class Window(QWidget): 12 def __init__(self): 13 super().__init__() 14 self.setWindowTitle("QTabWidget Example") 15 self.resize(270, 110) 16 # Create a top-level layout 17 layout = QVBoxLayout() 18 self.setLayout(layout) 19 # Create the tab widget with two tabs 20 tabs = QTabWidget() 21 tabs.addTab(self.generalTabUI(), "General") 22 tabs.addTab(self.networkTabUI(), "Network") 23 layout.addWidget(tabs) 24 25 def generalTabUI(self): 26 """Create the General page UI.""" 27 generalTab = QWidget() 28 layout = QVBoxLayout() 29 layout.addWidget(QCheckBox("General Option 1")) 30 layout.addWidget(QCheckBox("General Option 2")) 31 generalTab.setLayout(layout) 32 return generalTab 33 34 def networkTabUI(self): 35 """Create the Network page UI.""" 36 networkTab = QWidget() 37 layout = QVBoxLayout() 38 layout.addWidget(QCheckBox("Network Option 1")) 39 layout.addWidget(QCheckBox("Network Option 2")) 40 networkTab.setLayout(layout) 41 return networkTab 42 43if __name__ == "__main__": 44 app = QApplication(sys.argv) 45 window = Window() 46 window.show() 47 sys.exit(app.exec_())

      在此示例中,您使用選項卡小部件向用戶呈現一個簡潔的對話框,其中顯示與假設首選項菜單的常規和網絡部分相關的選項。在第 20 行,您創建了QTabWidget對象。然后使用 將兩個選項卡添加到選項卡小部件.addTab()。

      在.generalTabUI()和 中networkTabUI(),您為每個選項卡創建特定的 GUI。為此,您可以使用一個QWidget對象、一個QVBoxLayout對象和一些復選框來保存選項。

      如果您現在運行該應用程序,您將在屏幕上看到以下對話框:

      就是這樣!您有一個功能齊全的基于選項卡的 GUI。請注意,要在頁面之間切換,您只需單擊相應的選項卡。

      布置應用程序的主窗口

      如果您使用 PyQt 來創建您的 GUI 應用程序,那么大部分時間您將用于QMainWindow在它之上創建一個 GUI。此類允許您創建主窗口樣式的應用程序。QMainWindow帶有自己的預定義布局。此布局將允許您將以下圖形組件添加到主窗口:

      一個菜單欄在窗口頂部

      窗口四邊任意一側的一個或多個工具欄

      一個狀態欄在窗口底部

      一個或多個停靠窗口小部件位于窗口的四個側面(但不占用工具欄區域)

      一個中央物件在窗口的中心

      對于大多數應用程序,所有這些圖形組件都是可選的,除了中央小部件,它是使您的應用程序工作所必需的。

      注意:如果您使用 來創建 GUI 應用程序QMainWindow,那么您必須有一個中央小部件,即使它只是一個占位符。

      某些應用程序使用獨特且功能齊全的小部件作為其中心小部件。例如,如果您正在編寫一個文本編輯器,那么您可能會使用一個QTextEdit對象作為您編輯器的中央小部件。

      其他類型的 GUI 應用程序可能需要更精細的中央小部件。在這種情況下,您可以使用一個QWidget對象作為中央小部件,然后創建一個布局,其中包含應用程序 GUI 所需的特定小部件排列。最后一步是將該布局設置為中央小部件的布局。

      大多數時候,QMainWindow提供的布局足以創建任何類型的 GUI 應用程序。這種布局將有效地管理窗口小部件的行為,因此您不必擔心。

      布置應用程序的對話框

      GUI 應用程序通常使用一個主窗口和一個或多個對話框構建。對話框是允許您與用戶交流的小窗口。PyQt 提供QDialog處理對話框的創建。

      與 不同QMainWindow,QDialog沒有預定義或默認的頂級布局。那是因為對話框可以非常多樣化,并且包括范圍廣泛的小部件排列和組合。

      將所有小部件放置在對話框的 GUI 上后,您需要在該對話框上設置頂級布局。為此,您必須.setLayout()像使用任何其他小部件一樣調用對話框對象。

      這是一個對話框樣式的應用程序,展示了如何為對象設置頂級布局QDialog:

      1import sys 2 3from PyQt5.QtWidgets import ( 4 QApplication, 5 QDialog, 6 QDialogButtonBox, 7 QFormLayout, 8 QLineEdit, 9 QVBoxLayout, 10) 11 12class Dialog(QDialog): 13 def __init__(self): 14 super().__init__() 15 self.setWindowTitle("QDialog's Top-Level Layout Example") 16 dlgLayout = QVBoxLayout() 17 # Create a form layout and add widgets 18 formLayout = QFormLayout() 19 formLayout.addRow("Name:", QLineEdit()) 20 formLayout.addRow("Job:", QLineEdit()) 21 formLayout.addRow("Email:", QLineEdit()) 22 # Add a button box 23 btnBox = QDialogButtonBox() 24 btnBox.setStandardButtons( 25 QDialogButtonBox.Ok | QDialogButtonBox.Cancel 26 ) 27 # Set the layout on the dialog 28 dlgLayout.addLayout(formLayout) 29 dlgLayout.addWidget(btnBox) 30 self.setLayout(dlgLayout) 31 32if __name__ == "__main__": 33 app = QApplication(sys.argv) 34 dlg = Dialog() 35 dlg.show() 36 sys.exit(app.exec_())

      在這種情況下,應用程序的窗口繼承自QDialog,因此您有一個對話框樣式的應用程序。在第 16 行,您創建了將用作對話框頂級布局的布局。在第 18 到 21 行,您創建了一個表單布局來在表單中排列一些小部件。

      在第 24 行,您添加了一個QDialogButtonBox對象。您將經常使用QDialogButtonBox來處理對話框上的按鈕。在本例中,您使用兩個按鈕,一個確定按鈕和一個取消按鈕。這些按鈕沒有任何功能——它們只是為了使對話框更逼真。

      一旦您準備好所有小部件和布局,您就可以將它們添加到頂級布局中。這就是您在第 28 行和第 29 行所做的。最后一步,在第 30 行,是使用 將頂層布局設置為對話框的布局.setLayout()。

      如果您運行此應用程序,您將在屏幕上看到以下窗口:

      為所有對話框設置頂級布局是最佳實踐。這確保了當用戶調整底層窗口大小時,對話框的 GUI 將行為一致。否則,您的對話框在用戶眼中可能會顯得雜亂無章。

      在 PyQt 布局中管理空間

      當談到使用 PyQt 的布局管理器在窗口或窗體上排列小部件時,管理空間——空白空間、小部件之間的空間等等——是一個常見的問題。能夠管理這個空間是一項重要的技能。

      在內部,布局使用以下一些小部件屬性管理窗口上的可用空間:

      .sizeHint()?包含小部件的推薦大小

      .minimumSizeHint()?包含小部件在保持可用的同時可以具有的最小尺寸

      .sizePolicy()?在布局中保存小部件的默認行為

      布局使用這些屬性自動定位和調整小部件的大小,根據可用空間為每個小部件分配給定的空間量。這確保了小部件的排列一致并保持可用。

      在接下來的三個部分中,您將了解 PyQt 中不同類型的布局如何管理空間。

      管理框布局中的空間

      盒子布局在小部件之間分配可用空間方面做得很好。但是,有時它們的默認行為還不夠,您需要手動處理可用空間。為了幫助您解決這種情況,PyQt 提供了QSpacerItem.?此類允許您向框布局添加空格(或空框)。

      通常,您不需要QSpacerItem直接使用。相反,您可以在框布局對象上調用以下一些方法:

      .addSpacing(i)i向布局添加固定大小的不可拉伸空間(或空框)。i必須是一個整數,以像素為單位表示空間的大小。

      .addStretch(i)為框布局添加一個最小尺寸0和拉伸因子的可拉伸空間i。i必須是整數。

      .insertSpacing(index, size)在位置 插入一個不可拉伸的空間index,大小為size。如果index是負數,則在框布局的末尾添加空格。

      insertStretch(index, stretch)在位置 插入一個可拉伸的空間,index最小尺寸為0,拉伸系數為stretch。如果index是負數,則在框布局的末尾添加空格。

      當用戶調整底層窗口的大小時,可拉伸的墊片將膨脹或收縮以填充空白空間。無論底層窗口的大小如何變化,不可拉伸的間隔物都將保持相同的大小。

      回到如何使用垂直布局的示例并再次運行該應用程序。如果您拉下窗口的邊框,您會注意到拉得越遠,按鈕之間會出現更多空間:

      發生這種情況是因為布局通過自動擴展其框來處理新的可用空間。您可以通過QSpacerItem在布局末尾添加一個可拉伸對象來更改此行為。

      在您的示例代碼中,Window按如下方式更新初始值設定項:

      class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QVBoxLayout Example") self.resize(270, 110) # Create a QVBoxLayout instance layout = QVBoxLayout() # Add widgets to the layout layout.addWidget(QPushButton("Top")) layout.addWidget(QPushButton("Center")) layout.addWidget(QPushButton("Bottom")) layout.addStretch() # Set the layout on the application's window self.setLayout(layout)

      在突出顯示的行中,您QSpacerItem通過調用布局將可拉伸對象添加到布局的末尾.addStretch()。如果您再次運行該應用程序,您將獲得以下行為:

      現在所有額外的空間都會自動分配給QSpacerItem布局底部的可拉伸對象,而不會影響其余小部件的位置或大小。您可以使用這種和其他空間管理技術來使您的 GUI 應用程序看起來更漂亮、更精致。

      管理網格和表單布局中的空間

      網格和表單布局以不同的方式處理可用空間。在這些類型的布局中,您只能處理小部件之間的垂直和水平空間。這些布局提供了三種方法來管理這些空間:

      setSpacing(spacing)將小部件之間的垂直和水平間距設置為spacing。

      setVerticalSpacing(spacing)僅將布局中小部件之間的垂直間距設置為spacing。

      setHorizontalSpacing(spacing)僅將布局中小部件之間的水平間距設置為spacing。

      在所有情況下,spacing是表示像素的整數。現在回到關于如何創建表單布局并Window像這樣更新初始值設定項的示例:

      class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QFormLayout Example") self.resize(270, 110) # Create a QHBoxLayout instance layout = QFormLayout() # Add widgets to the layout layout.setVerticalSpacing(30) layout.addRow("Name:", QLineEdit()) layout.addRow("Job:", QLineEdit()) emailLabel = QLabel("Email:") layout.addRow(emailLabel, QLineEdit()) # Set the layout on the application's window self.setLayout(layout)

      在突出顯示的行中,您將小部件之間的垂直空間設置為30像素。如果您再次運行該應用程序,您將看到以下窗口:

      現在小部件行之間有更多空間。您還可以嘗試通過添加一些垂直或水平空間來修改如何使用網格布局的示例,以查看所有這些間距機制是如何工作的。

      結論

      創建高質量的GUI 應用程序需要將所有圖形組件以連貫和優美的排列方式布置。在 PyQt 中,一種有效的方法是使用 PyQt 的布局管理器,它提供了一種用戶友好且高效的方式來完成這項任務。

      在本教程中,您學習了:

      在 GUI 上正確布置小部件有什么好處

      如何使用 PyQt 的內置布局管理器以編程方式排列小部件

      哪個布局管理器用于您的特定用例

      如何在 PyQt 中布置主窗口風格和對話框風格的應用程序

      有了這些知識,您將能夠使用 PyQt 的內置布局創建美觀且專業的 GUI 應用程序。

      GUI 容器

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:JDK8部分JVM參數說明(二)
      下一篇:《深度實踐OpenStack:基于Python的OpenStack組件開發》
      相關文章
      亚洲Av综合色区无码专区桃色| 久久亚洲最大成人网4438| 亚洲∧v久久久无码精品| 亚洲人成网站在线观看播放| 亚洲国产成人久久综合碰| yy6080久久亚洲精品| 综合一区自拍亚洲综合图区| 亚洲依依成人亚洲社区| 亚洲免费福利在线视频| 中文字幕无码亚洲欧洲日韩| 99999久久久久久亚洲| 亚洲理论在线观看| 亚洲国产精品综合久久久| 亚洲成a人片毛片在线| 亚洲精品国产情侣av在线| 亚洲精品亚洲人成在线麻豆| 亚洲第一成年人网站| 亚洲午夜电影一区二区三区| 亚洲AV无码乱码麻豆精品国产| 亚洲午夜精品在线| 亚洲影院天堂中文av色| 亚洲а∨精品天堂在线| 苍井空亚洲精品AA片在线播放 | 亚洲国产高清国产拍精品| 亚洲精华国产精华精华液网站| 亚洲精品理论电影在线观看| 噜噜综合亚洲AV中文无码| 亚洲成a人片在线观看国产| 亚洲精品无码成人片在线观看| 久久久久无码专区亚洲av | avtt天堂网手机版亚洲| 一本色道久久88—综合亚洲精品| 亚洲日本VA中文字幕久久道具| 亚洲国产成人AV网站| 久久国产成人亚洲精品影院 | 亚洲av成人一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 亚洲女子高潮不断爆白浆| 国产亚洲男人的天堂在线观看| 国产精品亚洲二区在线观看| 国产亚洲综合色就色|