Lecture 36 GUI - PyQt III

Layout management is the way how we place the widgets on the application window. We can place our widgets using absolute positioning or with layout classes. Managing the layout with layout managers is the preferred way of organizing our widgets.

1. Absolute positioning



We use the move() method to position our widgets. In our case these are labels. We position them by providing the x and y coordinates. The beginning of the coordinate system is at the left top corner. The x values grow from left to right. The y values grow from top to bottom.

The label widget is positioned at x=15 and y=10.

2. Box layout

QHBoxLayout and QVBoxLayout are basic layout classes that line up widgets horizontally and vertically. Imagine that we wanted to place two buttons in the right bottom corner. To create such a layout, we use one horizontal and one vertical box. To create the necessary space, we add a stretch factor.



The example places two buttons in the bottom-right corner of the window. They stay there when we resize the application window. We use both a HBoxLayout and a QVBoxLayout.

Here we create two push buttons.

We create a horizontal box layout and add a stretch factor for both buttons. The stretch adds a stretchable space before the two buttons. This will push them to the right of the window.

The addStretch method adds a QSpacerItem to the end of a box layout. A QSpacerItem is an adjustable blank space. Using vbox.addStretch(1) will add a zero-width spacer-item that expands vertically from the top of the layout downwards. Using hbox.addStretch(1) will add a zero-height spacer-item that expands horizontally from the left of the layout rightwards. The value '1' means the first
QSpacerItem. If you put '2' there it is considered as the second QSpacerItem.

Finally, we set the main layout of the window.

3. Grid layout

QGridLayout is the most universal layout class. It divides the space into rows and columns.



In our example, we create a grid of buttons. The instance of a QGridLayout is created and set to be the layout for the application window. These are the labels used later for buttons. We create a list of positions in the grid. Buttons are created and added to the layout with the addWidget() method.

4. Review example

Widgets can span multiple columns or rows in a grid. In the next example we illustrate this.



We create a window in which we have three labels, two line edits and one text edit widget. The layout is done with the QGridLayout. We create a grid layout and set spacing between widgets. If we add a widget to a grid, we can provide row span and column span of the widget. In our case, we make the reviewEdit widget span 5 rows.

5. Events and signals

GUI applications are event-driven. Events are generated mainly by the user of an application. But they can be generated by other means as well; e.g. an Internet connection, a window manager, or a timer. When we call the application's exec_() method, the application enters the main loop. The main loop fetches events and sends them to the objects. In the event model, there are three participants:

*event source
*event object
*event target

The event source is the object whose state changes. It generates events. The event object (event) encapsulates the state changes in the event source. The event target is the object that wants to be notified. Event source object delegates the task of handling an event to the event target. PyQt5 has a unique signal and slot mechanism to deal with events. Signals and slots are used for communication between objects. A signal is emitted when a particular event occurs. A slot can be any Python callable. A slot is called when its connected signal is emitted.

This is a simple example demonstrating signals and slots in PyQt5.



In our example, we display a QtGui.QLCDNumber and a QtGui.QSlider. We change the lcd number by dragging the slider knob. Here we connect a valueChanged signal of the slider to the display slot of the lcd number. The sender is an object that sends a signal. The receiver is the object that receives the signal. The slot is the method that reacts to the signal.

6. Reimplementing event handler

Events in PyQt5 are processed often by reimplementing event handlers.



In our example, we reimplement the keyPressEvent() event handler. If we click the Escape button, the application terminates.

7. Event object

Event object is a Python object that contains a number of attributes describing the event. Event object is specific to the generated event type.



In this example, we display the x and y coordinates of a mouse pointer in a label widget. The x and y coordinates are displayd in a QLabel widget. Mouse tracking is disabled by default, so the widget only receives mouse move events when at least one mouse button is pressed while the mouse is being moved. If mouse tracking is enabled, the widget receives mouse move events even if no buttons are pressed. The e is the event object; it contains data about the event that was triggered; in our case, a mouse move event. With the x() and y() methods we determine the x and y coordinates of the mouse pointer. We build the string and set it to the label widget.

8. Event sender

Sometimes it is convenient to know which widget is the sender of a signal. For this, PyQt5 has the sender() method.



We have two buttons in our example. In the buttonClicked() method we determine which button we have clicked by calling the sender() method. Both buttons are connected to the same slot. We determine the signal source by calling the sender() method. In the statusbar of the application, we show the label of the button being pressed.

9. Emitting signals

Objects created from a QObject can emit signals. The following example shows how we to emit custom signals.



We create a new signal called closeApp. This signal is emitted during a mouse press event. The signal is connected to the close() slot of the QMainWindow. A signal is created with the pyqtSignal() as a class attribute of the external Communicate class. The custom closeApp signal is connected to the close() slot of the QMainWindow. When we click on the window with a mouse pointer, the closeApp signal is emitted. The application terminates.

10. Dialogs

Dialog windows or dialogs are an indispensable part of most modern GUI applications. A dialog is defined as a conversation between two or more persons. In a computer application a dialog is a window which is used to "talk" to the application. A dialog is used to input data, modify data, change the application settings etc.

QInputDialog

QInputDialog provides a simple convenience dialog to get a single value from the user. The input value can be a string, a number, or an item from a list.



The example has a button and a line edit widget. The button shows the input dialog for getting text values. The entered text will be displayed in the line edit widget. This line displays the input dialog. The first string is a dialog title, the second one is a message within the dialog. The dialog returns the entered text and a boolean value. If we click the Ok button, the boolean value is true.The text that we have received from the dialog is set to the line edit widget with setText().

QColorDialog

QColorDialog provides a dialog widget for selecting colour values.



The application example shows a push button and a QFrame. The widget background is set to black colour. Using the QColorDialog, we can change its background. This is an initial colour of the QFrame background. We check if the colour is valid. If we click on the Cancel button, no valid colour is returned. If the colour is valid, we change the background colour using style sheets.

QFontDialog

QFontDialog is a dialog widget for selecting a font.



In our example, we have a button and a label. With the QFontDialog, we change the font of the label. Here we pop up the font dialog. The getFont() method returns the font name and the ok parameter. It is equal to True if the user clicked Ok; otherwise it is False. If we clicked Ok, the font of the label is changed with setFont().

QFileDialog

QFileDialog is a dialog that allows users to select files or directories. The files can be selected for both opening and saving.



The example shows a menubar, centrally set text edit widget, and a statusbar. The menu item shows the QFileDialog which is used to select a file. The contents of the file are loaded into the text edit widget. The example is based on the QMainWindow widget because we centrally set a text edit widget. We pop up the QFileDialog. The first string in the getOpenFileName() method is the caption. The second string specifies the dialog working directory. By default, the file filter is set to All files (*). The selected file name is read and the contents of the file are set to the text edit widget.









Tasks:

1. Code up all these examples in this tutorial in one .py file and 'push' it to your GUI repository. Send the link of the repository to the homework email.