PySide——Python圖形化界面入門教程(二)


PySide——Python圖形化界面入門教程(二)

                ——交互Widget和布局容器

               ——Interactive Widgets and Layout Containers

翻譯自:http://pythoncentral.io/pyside-pyqt-tutorial-interactive-widgets-and-layout-containers/

上一個教程中,我們了解了一些QWidget提供的功能,還有一個特殊的子類QLabel。更進一步的,我們完成了一個用來說明簡單Python/Qt應用的例子。但是,我們掌握的遠遠不能滿足用戶的需求,因為我們只能給他們顯示文本,我們的應用只會唱獨角戲!我們需要一些方法讓用戶可以和我們的程序交互,讓獨角戲變成二人轉。Qt提供了豐富的交互式widgets,這里我們將要學習其中的一小部分;我們將使用他們體驗如何在圖形化(form)上布置widgets。下一個教程,我們將學習如何使用信號和槽來響應用戶的交互。

 

交互式Widgets

Python/Qt有一系列的widgets,可以非常簡單的實現與用戶交互,並且容易和你的應用邏輯聯系。

 

按鈕(Buttons)

一個最簡單的交互方式就是讓用戶點擊按鈕,Qt中就是QPushButton。QPushButton構造器有三個結構:

1 QPushButton(parent=None)
2 QPushButton(text, [parent=None])
3 QPushButton(icon, text, [parent=None])

parent參數是一個QWidget,text是一個Python string或unicode,icon是一個QIcon。創建一個被some-form擁有的帶有文字“Go”的按鈕,可以這樣:

go_button = QPushButton('Go', some_form)

如果我們想為按鈕設置一個鍵盤快捷鍵,如Alt-G,我們可以在‘Go’前添加一個‘&G’:

go_button = QPushButton('&Go', some_form)

這還有一些按鈕的其他功能,還拿go_button做例子,你可以將其設置為form的默認按鍵:

go_button.setDefault(True)

還可以設置成平的:

go_button.setFlat(True)

將False傳遞到方法中會有相反的作用。一個按鈕還可以在被點擊時彈出一個菜單(menu):傳遞一個QMenu對象給按鈕的setMenu方法。(我們以后再研究菜單)

 

文本框(Textboxes)

 Qt的文本框控件是QLineEdit;它允許用戶輸入編輯單行的簡單文本,其構造器有如下兩種:

1 QLineEdit(parent=None)
2 QLineEdit(text, [parent=None])

他們的不同就是第二個允許用text參數設置包含的文本。QLineEdit對象有許多的方法,但是我們只關心幾個最基本的。你可以使用text()方法取回文本,用setText(text)設置文本,使用setMaxLength(chars)設置最大可輸入長度。它可以通過setReadOnly(True)設置為只讀的,使用setPlaceholderText(text)設置占位文字(placeholder text,就是那種你輸入前提示說明的字)。QLineEdit還有更多的高級屬性:可以設置輸入過濾器,處理選擇和輸入歷史等等。

 

組合框(Comboboxes)

QComboBox widget是用來給用戶提供多個文本或文本/圖標的選擇,用戶必須選擇其一。(多項選擇參見QListView和QListWidget)它的構造器如下:

1 QComboBox(parent)

它的構造如此簡單,但是目前還沒有任何選項。你可以用多種方式添加選項。如果你的所有選項都是文字的,你可以使用addItems(texts),texts是字符串列表。一個一個的添加選項可以使用addItem,它有兩個有效的方式

1 addItem(icon, text, [userData=None])
2 addItem(text, [userData=None])

參數icon是QIcon,text是一個unicode對象,userData是任何對象。你可以使用insertItem插入選項:

1 insertItem(index, icon, text, [userData=None])
2 insertItem(index, text, [userData=None])

QComboBox是一個靈活的widget,用它還可以做更多的事情。

 

例子程序:總覽

接下來,我們將學習如何把小部件組合成一個表單布局,但在我們可以做到這一點之前,讓我們先看一下這個示例應用程序。

 

正如你所看到的,這是一個非常簡單的應用程序。用戶可以選擇一個稱呼和進入的人的姓名(或其他單位)他們要打招呼,當他們點擊“建立問候,問候將在窗體上顯示一個標簽。

 

布局管理(Layout Management)

PySide和PyQt有兩個可用的方法來管理布局:使用絕對位置,開發者必須明確設置每個widget和位置和大小;使用的布局容器(layout containers),自動安排位置和調整大小。我們將用兩種方法構建上面提到的例子程序。

 

絕對位置

去設置widget的無力位置,你需要使用widget的move(x, y)方法;x和y是水平和垂直距離,這個距離是從外框(form)的左上角到widget的左上角。這是我們使用絕對距離創建的外形:

 1 # Every Qt application must have one and only one QApplication object;
 2 # it receives the command line arguments passed to the script, as they
 3 # can be used to customize the application's appearance and behavior
 4 qt_app = QApplication(sys.argv)
 5  
 6 class AbsolutePositioningExample(QWidget):
 7     ''' An example of PySide absolute positioning; the main window
 8         inherits from QWidget, a convenient widget for an empty window. '''
 9     def __init__(self):
10         # Initialize the object as a QWidget
11         QWidget.__init__(self)
12  
13         # We have to set the size of the main window
14         # ourselves, since we control the entire layout
15         self.setMinimumSize(400, 185)
16         self.setWindowTitle('Dynamic Greeter')
17  
18         # Create the controls with this object as their parent and set
19         # their position individually; each row is a label followed by
20         # another control
21  
22         # Label for the salutation chooser
23         self.salutation_lbl = QLabel('Salutation:', self)
24         self.salutation_lbl.move(5, 5) # offset the first control 5px
25                                        # from top and left
26         self.salutations = ['Ahoy',
27                             'Good day',
28                             'Hello',
29                             'Heyo',
30                             'Hi',
31                             'Salutations',
32                             'Wassup',
33                             'Yo']
34         # Create and fill the combo box to choose the salutation
35         self.salutation = QComboBox(self)
36         self.salutation.addItems(self.salutations)
37  
38         # Allow 100px for the label and 5px each for borders at the
39         # far left, between the label and the combobox, and at the far
40         # right
41         self.salutation.setMinimumWidth(285)
42         # Place it five pixels to the right of the end of the label
43         self.salutation.move(110, 5)
44  
45         # The label for the recipient control
46         self.recipient_lbl = QLabel('Recipient:', self)
47         # 5 pixel indent, 25 pixels lower than last pair of widgets
48         self.recipient_lbl.move(5, 30)
49  
50         # The recipient control is an entry textbox
51         self.recipient = QLineEdit(self)
52         # Add some ghost text to indicate what sort of thing to enter
53         self.recipient.setPlaceholderText('world' or 'Matey')
54         # Same width as the salutation
55         self.recipient.setMinimumWidth(285)
56         # Same indent as salutation but 25 pixels lower
57         self.recipient.move(110, 30)
58  
59         # The label for the greeting widget
60         self.greeting_lbl = QLabel('Greeting:', self)
61         # Same indent as the others, but 45 pixels lower so it has
62         # physical separation, indicating difference of function
63         self.greeting_lbl.move(5, 75)
64  
65         # The greeting widget is also a label
66         self.greeting = QLabel('', self)
67         # Same indent as the other controls
68         self.greeting.move(110, 75)
69  
70         # The build button is a push button
71         self.build_button = QPushButton('&Build Greeting', self)
72  
73         # Place it at the bottom right, narrower than
74         # the other interactive widgets
75         self.build_button.setMinimumWidth(145)
76         self.build_button.move(250, 150)
77  
78     def run(self):
79         # Show the form
80         self.show()
81         # Run the Qt application
82         qt_app.exec_()
83  
84 # Create an instance of the application window and run it
85 app = AbsolutePositioningExample()
86 app.run()

不用說,一個大型的應用程序可能會變得非常麻煩。另外,它也沒有大小改變的反應;標簽只是坐在指定的位置。不僅如此,想象一下,如果有視覺障礙的用戶想把他們的字體設置的大一些;使用固定的位置,您設置的控件將不再適當。

 

布局容器(Layout Containers)

由於上述種種原因,布局容器比絕對位置更為常用,他們更加靈活,替程序員分擔了計算確切位置的任務,並且他們可以調整布局去適應不同平台的GUI設置,如GTK+, KDE, Mac OS X等等。這有5個主要的布局容器,他們都是繼承自QLayout:

  • QHBoxLayout
  • QVBoxLayout
  • QGridLayout
  • QStackedLayout
  • QFormLayout

他們用來滿足不同的需求。簡而言之,QHBoxLayout和QVBoxLayout將widgets一個挨一個的水平(horizontally)、垂直(vertically)排列;QGridLayout可按照任意大小表格布局;QStackedLayout將他們一個放在一個的上面(就像stack棧一樣);QFormLayout是一個特殊的兩欄布局,它提供特殊的方法用標簽安排內容在第一列,在第二列安排相關的空間。這些布局非常有用,但是你的布局選項不局限於他們,你可以將布局嵌套組合來創建更復雜易用的用戶接口。現在,我們來看看水平、垂直布局和QFormLayout。

 

QVBoxLayout和QHBoxLayout

盒子布局(box layouts)非常的直截了當。使用它作為最上層的布局,創建布局非常簡單——它的構造器需要任何參數——並且使用望名知義的方法addWidget來添加widget。接下來你就可以設置它所屬的窗口。例如:

 1 win = QWidget()
 2  
 3 # The three labels
 4 lbl_1 = QLabel("We're")
 5 lbl_2 = QLabel('stacked')
 6 lbl_3 = QLabel('up.')
 7  
 8 # A vertical box layout
 9 layout = QVBoxLayout()
10  
11 # Add the widgets to the layout
12 layout.addWidget(lbl_1)
13 layout.addWidget(lbl_2)
14 layout.addWidget(lbl_3)
15  
16 # Set layout as the layout for the window
17 win.setLayout(layout)

QHBoxLayout也可以被同樣使用,盡管它不常作為最上層的布局。它常常被作為子布局。為一個布局中添加另一個布局,使用該布局容器的addLayout方法,例如:

1 layout = QVBoxLayout()
2 sub_layout = QHBoxLayout()
3  
4 # ... Fill the layouts with widgets ...
5  
6 layout.addLayout(sub_layout)

盒子布局有另一個更重要並且常用的方法:addStretch。一個常見的布局有很多的控件,他們之間具有靈活的空間。為了完成這個目的,在盒子的開始添加widgets,然后添加一個設置大於0的空閑空間,layout.addStretch(1),然后再添加剩下的widgets。

 

QFormLayout

QFormLayout非常像QVBoxLayout,但是它可以不用創建子布局就輕松的將每一行分成兩列。這通過使用外觀布局的addRow方法,它有很多重載(overloaded?)。單參數的版本:

1 addRow(QWidget)
2 addRow(QLayout)

添加widget或布局在整個QFormLayout的最后。雙參數版本:

1 unicode, QLayout
2 unicode, QWidget
3 QWidget, QWidget
4 QWidget, QLayout

作為一個“標簽”在第一列中初始化元素,第二個是第二列。unicode參數作為QLabel的文本,QWidget可以是任意的widget。

 

盒子布局的例子(Box Layout Example)

現在我們已經了解了如何創建交互式widget和用靈活的布局管理他們,現在我們重新創建例子應用。我們窗口的主布局是QVBoxLayout,它有兩個子布局,一個QformLayout包含所有的標簽控件,和一個QHBoxLayout來管理右下角的按鈕位置。我們將使用addStretch來分離QFormLayout,並且把按鈕擠到QHBoxLayout的右邊。你會注意到,許多代碼同絕對位置版本是一樣的;比如,創建單獨控件的時候。

 1 qt_app = QApplication(sys.argv)
 2  
 3 class LayoutExample(QWidget):
 4     ''' An example of PySide/PyQt absolute positioning; the main window
 5         inherits from QWidget, a convenient widget for an empty window. '''
 6  
 7     def __init__(self):
 8         # Initialize the object as a QWidget and
 9         # set its title and minimum width
10         QWidget.__init__(self)
11         self.setWindowTitle('Dynamic Greeter')
12         self.setMinimumWidth(400)
13  
14         # Create the QVBoxLayout that lays out the whole form
15         self.layout = QVBoxLayout()
16  
17         # Create the form layout that manages the labeled controls
18         self.form_layout = QFormLayout()
19  
20         # The salutations that we want to make available
21         self.salutations = ['Ahoy',
22                             'Good day',
23                             'Hello',
24                             'Heyo',
25                             'Hi',
26                             'Salutations',
27                             'Wassup',
28                             'Yo']
29  
30         # Create and fill the combo box to choose the salutation
31         self.salutation = QComboBox(self)
32         self.salutation.addItems(self.salutations)
33  
34         # Add it to the form layout with a label
35         self.form_layout.addRow('&Salutation:', self.salutation)
36  
37         # Create the entry control to specify a recipient
38         # and set its placeholder text
39         self.recipient = QLineEdit(self)
40         self.recipient.setPlaceholderText("e.g. 'world' or 'Matey'")
41  
42         # Add it to the form layout with a label
43         self.form_layout.addRow('&Recipient:', self.recipient)
44  
45         # Create and add the label to show the greeting text
46         self.greeting = QLabel('', self)
47         self.form_layout.addRow('Greeting:', self.greeting)
48  
49         # Add the form layout to the main VBox layout
50         self.layout.addLayout(self.form_layout)
51  
52         # Add stretch to separate the form layout from the button
53         self.layout.addStretch(1)
54  
55         # Create a horizontal box layout to hold the button
56         self.button_box = QHBoxLayout()
57  
58         # Add stretch to push the button to the far right
59         self.button_box.addStretch(1)
60  
61         # Create the build button with its caption
62         self.build_button = QPushButton('&Build Greeting', self)
63  
64         # Add it to the button box
65         self.button_box.addWidget(self.build_button)
66  
67         # Add the button box to the bottom of the main VBox layout
68         self.layout.addLayout(self.button_box)
69  
70         # Set the VBox layout as the window's main layout
71         self.setLayout(self.layout)
72  
73     def run(self):
74         # Show the form
75         self.show()
76         # Run the qt application
77         qt_app.exec_()
78  
79 # Create an instance of the application window and run it
80 app = LayoutExample()
81 app.run()

注意到這些對程序員來說是多么的容易。當代碼不太短的時候——不是每個便捷都會使代碼量減少,創建和嵌套布局有一定的代碼開銷的時候——精神上的負擔就小多了。開發人員只需完成一個組合的布局,產生所需的效果,並創建他們;控件的創建和修改是隔離的,很少再要去考慮其影響到布局和其他控件。下一部分,我們將以這個例子創建的界面,讓它實際上做些事。

 

By Ascii0x03

轉載請注明出處:http://www.cnblogs.com/ascii0x03/p/5496699.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM