用PyQt打造具有專業(yè)外觀的GUI(中篇)
快速創(chuàng)建表單:QFormLayout
如果您一直在創(chuàng)建表單以執(zhí)行將數(shù)據(jù)輸入數(shù)據(jù)庫等操作,那么QFormLayout適合您。此類將小部件布置為兩列布局。第一列通常顯示描述預(yù)期輸入的標(biāo)簽,第二列通常包含允許用戶輸入或編輯數(shù)據(jù)的輸入小部件,例如QLineEdit,QComboBox或QSpinBox。
要將小部件添加到表單布局,請使用.addRow()。此方法有多種變量,但是在大多數(shù)情況下,您可以從以下兩種進行選擇:
- .addRow(label,field)將新行添加到表單布局的底部。該行應(yīng)包含一個QLabel對象(label)和一個輸入小部件(field))。
- .addRow(labelText,field)自動創(chuàng)建并添加帶有l(wèi)abelText作為其文本的新QLabel對象。字段. field包含一個輸入小部件。
這是一個使用QFormLayout對象排列小部件的示例應(yīng)用程序:
- import sys
- from PyQt5.QtWidgets import (
- QApplication,
- QFormLayout,
- QLabel,
- QLineEdit,
- QWidget,
- )
- 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.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)
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = Window()
- window.show()
- sys.exit(app.exec_())
在第17行,創(chuàng)建一個QFormLayout對象。然后,在第19至22行上,向布局中添加一些行。請注意,在第19行和第20行,您使用方法的第二個變量,在第22行,您使用第一個變量,將QLabel對象作為第一個參數(shù)傳遞給.addRow()。
如果您運行此代碼,則會在屏幕上看到以下窗口:
使用QFormLayout,可以以兩列的方式組織小部件。第一列包含標(biāo)簽,要求用戶提供一些信息。第二列顯示允許用戶輸入或編輯該信息的小部件。
嵌套布局以構(gòu)建復(fù)雜的GUI
您可以使用嵌套布局來創(chuàng)建復(fù)雜的GUI,而使用通用PyQt的布局管理器之一很難創(chuàng)建這些GUI。為此,您需要在外部布局上調(diào)用.addLayout()。這樣,內(nèi)部布局成為外部布局的子級。
假設(shè)您需要創(chuàng)建一個對話框,該對話框在表單布局中顯示標(biāo)簽和行編輯,并且在這些小部件下方您要在垂直布局中放置多個復(fù)選框。這是您的對話框外觀的模型:
藍(lán)色矩形代表您的外部布局。綠色矩形是將保留標(biāo)簽和行編輯的表單布局。紅色矩形是用于容納選項復(fù)選框的垂直布局。綠色布局和紅色布局都嵌套在藍(lán)色布局中,藍(lán)色布局是垂直布局。
這是一個如何使用PyQt構(gòu)建此布局的示例:
- import sys
- from PyQt5.QtWidgets import (
- QApplication,
- QCheckBox,
- QFormLayout,
- QLineEdit,
- QVBoxLayout,
- QWidget,
- )
- class Window(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("Nested Layouts Example")
- # Create an outer layout
- outerLayout = QVBoxLayout()
- # Create a form layout for the label and line edit
- topLayout = QFormLayout()
- # Add a label and a line edit to the form layout
- topLayout.addRow("Some Text:", QLineEdit())
- # Create a layout for the checkboxes
- optionsLayout = QVBoxLayout()
- # Add some checkboxes to the layout
- optionsLayout.addWidget(QCheckBox("Option one"))
- optionsLayout.addWidget(QCheckBox("Option two"))
- optionsLayout.addWidget(QCheckBox("Option three"))
- # Nest the inner layouts into the outer layout
- outerLayout.addLayout(topLayout)
- outerLayout.addLayout(optionsLayout)
- # Set the window's main layout
- self.setLayout(outerLayout)
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = Window()
- window.show()
- sys.exit(app.exec_())
這是您在此代碼中執(zhí)行的操作:
- 在第17行,您將創(chuàng)建外部或頂層布局,將其用作父布局和窗口的主布局。在這種情況下,使用QVBoxLayout是因為您希望將小部件垂直排列在窗體上。在您的模型中,這是藍(lán)色布局。
- 在第19行,您創(chuàng)建一個表單布局來保存標(biāo)簽和行編輯。
- 在第21行,將所需的小部件添加到布局中。這等效于您的綠色布局。
- 在第23行,您將創(chuàng)建一個垂直布局來容納復(fù)選框。
- 在第25至27行上,添加所需的復(fù)選框。這是您的紅色布局。
- 在第29和30行上,將topLayout和optionsLayout嵌套在outsideLayout下。
如果您運行該應(yīng)用程序,則會看到類似以下的窗口:
在此應(yīng)用程序中,您將兩個不同的布局嵌套在外部布局下,以為窗口創(chuàng)建常規(guī)布局。在窗口頂部,使用水平布局放置標(biāo)簽和行編輯。然后,使用垂直布局在其下方放置一些復(fù)選框。
使用多頁布局和小部件
到目前為止,您已經(jīng)了解了如何使用傳統(tǒng)或通用布局管理器在應(yīng)用程序的窗口中排列小部件。這些布局管理器將小部件安排在單頁布局上。換句話說,您的GUI將始終向用戶顯示相同的窗口小部件集。
有時您需要創(chuàng)建一個布局,以顯示一組不同的窗口小部件,以響應(yīng)GUI上的某些用戶操作。例如,如果要為給定的應(yīng)用程序創(chuàng)建首選項對話框,則可能需要向用戶顯示基于選項卡或多頁的布局,其中每個選項卡或頁面都包含一組不同的緊密相關(guān)的選項。每次用戶單擊選項卡或頁面時,應(yīng)用程序都會顯示一組不同的小部件。
PyQt提供了一個稱為QStackedLayout的內(nèi)置布局以及一些方便的小部件(例如QTabWidget),這些小部件將允許您創(chuàng)建這種多頁布局。接下來的幾節(jié)將帶您逐步了解其中一些工具。
創(chuàng)建小部件堆棧
QStackedLayout提供了一個布局管理器,該管理器允許您將小部件排列在一個堆棧上,一個放在另一個上。在這種布局中,給定時間僅可見一個小部件。
要使用小部件填充堆疊的布局,您需要在布局對象上調(diào)用.addWidget()。這會將每個小部件添加到布局內(nèi)部小部件列表的末尾。您還可以分別使用.insertWidget(index)或.removeWidget(widget)在小部件列表中的給定位置插入或刪除小部件。
小部件列表中的每個小部件都顯示為獨立頁面。如果要在頁面上顯示多個窗口小部件,請對每個頁面使用QWidget對象,并為頁面窗口小部件設(shè)置適當(dāng)?shù)拇翱谛〔考季帧H绻枰@取布局中小部件(頁面)的總數(shù),則可以調(diào)用.count()。
使用QStackedLayout對象時要記住的重要一點是,您需要顯式提供一種在頁面之間切換的機制。否則,您的布局將始終向用戶顯示同一頁面。要在頁面之間切換,您需要在布局對象上調(diào)用.setCurrentIndex()。
這是一個示例,展示了如何使用帶有組合框的堆疊式布局在頁面之間進行切換:
- import sys
- from PyQt5.QtWidgets import (
- QApplication,
- QComboBox,
- QFormLayout,
- QLineEdit,
- QStackedLayout,
- QVBoxLayout,
- QWidget,
- )
- class Window(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("QStackedLayout Example")
- # Create a top-level layout
- layout = QVBoxLayout()
- self.setLayout(layout)
- # Create and connect the combo box to switch between pages
- self.pageCombo = QComboBox()
- self.pageCombo.addItems(["Page 1", "Page 2"])
- self.pageCombo.activated.connect(self.switchPage)
- # Create the stacked layout
- self.stackedLayout = QStackedLayout()
- # Create the first page
- self.page1 = QWidget()
- self.page1Layout = QFormLayout()
- self.page1Layout.addRow("Name:", QLineEdit())
- self.page1Layout.addRow("Address:", QLineEdit())
- self.page1.setLayout(self.page1Layout)
- self.stackedLayout.addWidget(self.page1)
- # Create the second page
- self.page2 = QWidget()
- self.page2Layout = QFormLayout()
- self.page2Layout.addRow("Job:", QLineEdit())
- self.page2Layout.addRow("Department:", QLineEdit())
- self.page2.setLayout(self.page2Layout)
- self.stackedLayout.addWidget(self.page2)
- # Add the combo box and the stacked layout to the top-level layout
- layout.addWidget(self.pageCombo)
- layout.addLayout(self.stackedLayout)
- def switchPage(self):
- self.stackedLayout.setCurrentIndex(self.pageCombo.currentIndex())
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = Window()
- window.show()
- sys.exit(app.exec_())
在第21至23行,您將創(chuàng)建一個QComboBox對象,該對象將允許您在布局中的頁面之間進行切換。然后,在列表的組合框中添加兩個選項,并將其連接到旨在處理頁面切換的.switchPage()。
在.switchPage()內(nèi)部,您在布局對象上調(diào)用.setCurrentIndex(),將組合框的當(dāng)前索引作為參數(shù)傳遞。這樣,當(dāng)用戶更改組合框中的選項時,堆疊版式上的頁面將相應(yīng)地更改。
在第25行上,創(chuàng)建QStackedLayout對象。在第27至32行上,將第一頁添加到布局中,在第34至39行上,將第二頁添加到布局中。每個頁面都由一個QWidget對象表示,該對象以方便的布局包含多個小部件。
使一切正常運行的最后一步是將組合框和布局添加到應(yīng)用程序的主布局。
現(xiàn)在,您的應(yīng)用程序的行為如下:
在這種情況下,您的應(yīng)用程序布局中有兩個頁面。每個頁面由一個QWidget對象表示。當(dāng)您在窗口頂部的組合框中選擇一個新頁面時,布局將更改以顯示所選頁面。
除了堆疊的布局和堆疊的小部件,您還可以使用QTabWidget創(chuàng)建多頁用戶界面。您將在下一節(jié)中學(xué)習(xí)如何操作。
使用PyQt的標(biāo)簽小部件
在PyQt中創(chuàng)建多頁排列的另一種流行方式是使用稱為QTabWidget的類。此類提供標(biāo)簽欄和頁面區(qū)域。您可以使用選項卡欄在頁面之間切換,并使用頁面區(qū)域顯示與所選選項卡關(guān)聯(lián)的頁面。
默認(rèn)情況下,選項卡欄位于頁面區(qū)域的頂部。但是,可以使用.setTabPosition()和四個可能的選項卡位置之一來更改此行為:
要將選項卡添加到選項卡小部件,請使用.addTab()。此方法有兩個變量或重載的實現(xiàn):
1、.addTab(page, label)
2、.addTab(page, icon, label)
在這兩種情況下,該方法都會添加一個新標(biāo)簽,label為標(biāo)簽標(biāo)題。. page必須是一個小部件,代表與手邊的選項卡關(guān)聯(lián)的頁面。
在該方法的第二變量中,圖標(biāo)必須是QIcon對象。如果您將圖標(biāo)傳遞給.addTab(),則該圖標(biāo)將顯示在標(biāo)簽標(biāo)題的左側(cè)。
創(chuàng)建選項卡小部件時的常見做法是為每個頁面使用QWidget對象。這樣,您就可以使用包含所需窗口小部件的布局向頁面添加額外的窗口小部件。
大多數(shù)情況下,您將使用標(biāo)簽小部件為GUI應(yīng)用程序創(chuàng)建對話框。這種布局允許您在相對較小的空間中為用戶提供多個選項。您還可以利用選項卡系統(tǒng)根據(jù)一些分類標(biāo)準(zhǔn)來組織選項。
這是一個示例應(yīng)用程序,顯示了如何創(chuàng)建和使用QTabWidget對象的基礎(chǔ)知識:
- import sys
- from PyQt5.QtWidgets import (
- QApplication,
- QCheckBox,
- QTabWidget,
- QVBoxLayout,
- QWidget,
- )
- class Window(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("QTabWidget Example")
- self.resize(270, 110)
- # Create a top-level layout
- layout = QVBoxLayout()
- self.setLayout(layout)
- # Create the tab widget with two tabs
- tabs = QTabWidget()
- tabs.addTab(self.generalTabUI(), "General")
- tabs.addTab(self.networkTabUI(), "Network")
- layout.addWidget(tabs)
- def generalTabUI(self):
- """Create the General page UI."""
- generalTab = QWidget()
- layout = QVBoxLayout()
- layout.addWidget(QCheckBox("General Option 1"))
- layout.addWidget(QCheckBox("General Option 2"))
- generalTab.setLayout(layout)
- return generalTab
- def networkTabUI(self):
- """Create the Network page UI."""
- networkTab = QWidget()
- layout = QVBoxLayout()
- layout.addWidget(QCheckBox("Network Option 1"))
- layout.addWidget(QCheckBox("Network Option 2"))
- networkTab.setLayout(layout)
- return networkTab
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = Window()
- window.show()
- sys.exit(app.exec_())
在此示例中,您使用選項卡小部件向用戶顯示一個簡潔的對話框,該對話框顯示與假設(shè)首選項菜單的“常規(guī)”和“網(wǎng)絡(luò)”部分相關(guān)的選項。在第20行上,創(chuàng)建QTabWidget對象。然后,使用.addTab()將兩個選項卡添加到選項卡小部件。
在.generalTabUI()和networkTabUI()中,為每個選項卡創(chuàng)建特定的GUI。為此,您可以使用QWidget對象,QVBoxLayout對象和一些復(fù)選框來保存選項。
如果立即運行該應(yīng)用程序,則屏幕上將顯示以下對話框:
您有一個功能齊全的基于選項卡的GUI。請注意,要在頁面之間切換,只需單擊相應(yīng)的選項卡。