用PyQt打造具有專業(yè)外觀的GUI(中篇)
快速創(chuàng)建表單:QFormLayout
如果您一直在創(chuàng)建表單以執(zhí)行將數(shù)據(jù)輸入數(shù)據(jù)庫(kù)等操作,那么QFormLayout適合您。此類將小部件布置為兩列布局。第一列通常顯示描述預(yù)期輸入的標(biāo)簽,第二列通常包含允許用戶輸入或編輯數(shù)據(jù)的輸入小部件,例如QLineEdit,QComboBox或QSpinBox。
要將小部件添加到表單布局,請(qǐng)使用.addRow()。此方法有多種變量,但是在大多數(shù)情況下,您可以從以下兩種進(jìn)行選擇:
- .addRow(label,field)將新行添加到表單布局的底部。該行應(yīng)包含一個(gè)QLabel對(duì)象(label)和一個(gè)輸入小部件(field))。
- .addRow(labelText,field)自動(dòng)創(chuàng)建并添加帶有l(wèi)abelText作為其文本的新QLabel對(duì)象。字段. field包含一個(gè)輸入小部件。
這是一個(gè)使用QFormLayout對(duì)象排列小部件的示例應(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)建一個(gè)QFormLayout對(duì)象。然后,在第19至22行上,向布局中添加一些行。請(qǐng)注意,在第19行和第20行,您使用方法的第二個(gè)變量,在第22行,您使用第一個(gè)變量,將QLabel對(duì)象作為第一個(gè)參數(shù)傳遞給.addRow()。
如果您運(yùn)行此代碼,則會(huì)在屏幕上看到以下窗口:
使用QFormLayout,可以以兩列的方式組織小部件。第一列包含標(biāo)簽,要求用戶提供一些信息。第二列顯示允許用戶輸入或編輯該信息的小部件。
嵌套布局以構(gòu)建復(fù)雜的GUI
您可以使用嵌套布局來創(chuàng)建復(fù)雜的GUI,而使用通用PyQt的布局管理器之一很難創(chuàng)建這些GUI。為此,您需要在外部布局上調(diào)用.addLayout()。這樣,內(nèi)部布局成為外部布局的子級(jí)。
假設(shè)您需要?jiǎng)?chuàng)建一個(gè)對(duì)話框,該對(duì)話框在表單布局中顯示標(biāo)簽和行編輯,并且在這些小部件下方您要在垂直布局中放置多個(gè)復(fù)選框。這是您的對(duì)話框外觀的模型:
藍(lán)色矩形代表您的外部布局。綠色矩形是將保留標(biāo)簽和行編輯的表單布局。紅色矩形是用于容納選項(xiàng)復(fù)選框的垂直布局。綠色布局和紅色布局都嵌套在藍(lán)色布局中,藍(lán)色布局是垂直布局。
這是一個(gè)如何使用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是因?yàn)槟M麑⑿〔考怪迸帕性诖绑w上。在您的模型中,這是藍(lán)色布局。
- 在第19行,您創(chuàng)建一個(gè)表單布局來保存標(biāo)簽和行編輯。
- 在第21行,將所需的小部件添加到布局中。這等效于您的綠色布局。
- 在第23行,您將創(chuàng)建一個(gè)垂直布局來容納復(fù)選框。
- 在第25至27行上,添加所需的復(fù)選框。這是您的紅色布局。
- 在第29和30行上,將topLayout和optionsLayout嵌套在outsideLayout下。
如果您運(yùn)行該應(yīng)用程序,則會(huì)看到類似以下的窗口:
在此應(yīng)用程序中,您將兩個(gè)不同的布局嵌套在外部布局下,以為窗口創(chuàng)建常規(guī)布局。在窗口頂部,使用水平布局放置標(biāo)簽和行編輯。然后,使用垂直布局在其下方放置一些復(fù)選框。
使用多頁(yè)布局和小部件
到目前為止,您已經(jīng)了解了如何使用傳統(tǒng)或通用布局管理器在應(yīng)用程序的窗口中排列小部件。這些布局管理器將小部件安排在單頁(yè)布局上。換句話說,您的GUI將始終向用戶顯示相同的窗口小部件集。
有時(shí)您需要?jiǎng)?chuàng)建一個(gè)布局,以顯示一組不同的窗口小部件,以響應(yīng)GUI上的某些用戶操作。例如,如果要為給定的應(yīng)用程序創(chuàng)建首選項(xiàng)對(duì)話框,則可能需要向用戶顯示基于選項(xiàng)卡或多頁(yè)的布局,其中每個(gè)選項(xiàng)卡或頁(yè)面都包含一組不同的緊密相關(guān)的選項(xiàng)。每次用戶單擊選項(xiàng)卡或頁(yè)面時(shí),應(yīng)用程序都會(huì)顯示一組不同的小部件。
PyQt提供了一個(gè)稱為QStackedLayout的內(nèi)置布局以及一些方便的小部件(例如QTabWidget),這些小部件將允許您創(chuàng)建這種多頁(yè)布局。接下來的幾節(jié)將帶您逐步了解其中一些工具。
創(chuàng)建小部件堆棧
QStackedLayout提供了一個(gè)布局管理器,該管理器允許您將小部件排列在一個(gè)堆棧上,一個(gè)放在另一個(gè)上。在這種布局中,給定時(shí)間僅可見一個(gè)小部件。
要使用小部件填充堆疊的布局,您需要在布局對(duì)象上調(diào)用.addWidget()。這會(huì)將每個(gè)小部件添加到布局內(nèi)部小部件列表的末尾。您還可以分別使用.insertWidget(index)或.removeWidget(widget)在小部件列表中的給定位置插入或刪除小部件。
小部件列表中的每個(gè)小部件都顯示為獨(dú)立頁(yè)面。如果要在頁(yè)面上顯示多個(gè)窗口小部件,請(qǐng)對(duì)每個(gè)頁(yè)面使用QWidget對(duì)象,并為頁(yè)面窗口小部件設(shè)置適當(dāng)?shù)拇翱谛〔考季?。如果需要獲取布局中小部件(頁(yè)面)的總數(shù),則可以調(diào)用.count()。
使用QStackedLayout對(duì)象時(shí)要記住的重要一點(diǎn)是,您需要顯式提供一種在頁(yè)面之間切換的機(jī)制。否則,您的布局將始終向用戶顯示同一頁(yè)面。要在頁(yè)面之間切換,您需要在布局對(duì)象上調(diào)用.setCurrentIndex()。
這是一個(gè)示例,展示了如何使用帶有組合框的堆疊式布局在頁(yè)面之間進(jìn)行切換:
- 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)建一個(gè)QComboBox對(duì)象,該對(duì)象將允許您在布局中的頁(yè)面之間進(jìn)行切換。然后,在列表的組合框中添加兩個(gè)選項(xiàng),并將其連接到旨在處理頁(yè)面切換的.switchPage()。
在.switchPage()內(nèi)部,您在布局對(duì)象上調(diào)用.setCurrentIndex(),將組合框的當(dāng)前索引作為參數(shù)傳遞。這樣,當(dāng)用戶更改組合框中的選項(xiàng)時(shí),堆疊版式上的頁(yè)面將相應(yīng)地更改。
在第25行上,創(chuàng)建QStackedLayout對(duì)象。在第27至32行上,將第一頁(yè)添加到布局中,在第34至39行上,將第二頁(yè)添加到布局中。每個(gè)頁(yè)面都由一個(gè)QWidget對(duì)象表示,該對(duì)象以方便的布局包含多個(gè)小部件。
使一切正常運(yùn)行的最后一步是將組合框和布局添加到應(yīng)用程序的主布局。
現(xiàn)在,您的應(yīng)用程序的行為如下:
在這種情況下,您的應(yīng)用程序布局中有兩個(gè)頁(yè)面。每個(gè)頁(yè)面由一個(gè)QWidget對(duì)象表示。當(dāng)您在窗口頂部的組合框中選擇一個(gè)新頁(yè)面時(shí),布局將更改以顯示所選頁(yè)面。
除了堆疊的布局和堆疊的小部件,您還可以使用QTabWidget創(chuàng)建多頁(yè)用戶界面。您將在下一節(jié)中學(xué)習(xí)如何操作。
使用PyQt的標(biāo)簽小部件
在PyQt中創(chuàng)建多頁(yè)排列的另一種流行方式是使用稱為QTabWidget的類。此類提供標(biāo)簽欄和頁(yè)面區(qū)域。您可以使用選項(xiàng)卡欄在頁(yè)面之間切換,并使用頁(yè)面區(qū)域顯示與所選選項(xiàng)卡關(guān)聯(lián)的頁(yè)面。
默認(rèn)情況下,選項(xiàng)卡欄位于頁(yè)面區(qū)域的頂部。但是,可以使用.setTabPosition()和四個(gè)可能的選項(xiàng)卡位置之一來更改此行為:
要將選項(xiàng)卡添加到選項(xiàng)卡小部件,請(qǐng)使用.addTab()。此方法有兩個(gè)變量或重載的實(shí)現(xiàn):
1、.addTab(page, label)
2、.addTab(page, icon, label)
在這兩種情況下,該方法都會(huì)添加一個(gè)新標(biāo)簽,label為標(biāo)簽標(biāo)題。. page必須是一個(gè)小部件,代表與手邊的選項(xiàng)卡關(guān)聯(lián)的頁(yè)面。
在該方法的第二變量中,圖標(biāo)必須是QIcon對(duì)象。如果您將圖標(biāo)傳遞給.addTab(),則該圖標(biāo)將顯示在標(biāo)簽標(biāo)題的左側(cè)。
創(chuàng)建選項(xiàng)卡小部件時(shí)的常見做法是為每個(gè)頁(yè)面使用QWidget對(duì)象。這樣,您就可以使用包含所需窗口小部件的布局向頁(yè)面添加額外的窗口小部件。
大多數(shù)情況下,您將使用標(biāo)簽小部件為GUI應(yīng)用程序創(chuàng)建對(duì)話框。這種布局允許您在相對(duì)較小的空間中為用戶提供多個(gè)選項(xiàng)。您還可以利用選項(xiàng)卡系統(tǒng)根據(jù)一些分類標(biāo)準(zhǔn)來組織選項(xiàng)。
這是一個(gè)示例應(yīng)用程序,顯示了如何創(chuàng)建和使用QTabWidget對(duì)象的基礎(chǔ)知識(shí):
- 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_())
在此示例中,您使用選項(xiàng)卡小部件向用戶顯示一個(gè)簡(jiǎn)潔的對(duì)話框,該對(duì)話框顯示與假設(shè)首選項(xiàng)菜單的“常規(guī)”和“網(wǎng)絡(luò)”部分相關(guān)的選項(xiàng)。在第20行上,創(chuàng)建QTabWidget對(duì)象。然后,使用.addTab()將兩個(gè)選項(xiàng)卡添加到選項(xiàng)卡小部件。
在.generalTabUI()和networkTabUI()中,為每個(gè)選項(xiàng)卡創(chuàng)建特定的GUI。為此,您可以使用QWidget對(duì)象,QVBoxLayout對(duì)象和一些復(fù)選框來保存選項(xiàng)。
如果立即運(yùn)行該應(yīng)用程序,則屏幕上將顯示以下對(duì)話框:
您有一個(gè)功能齊全的基于選項(xiàng)卡的GUI。請(qǐng)注意,要在頁(yè)面之間切換,只需單擊相應(yīng)的選項(xiàng)卡。