Return to site

Signals And Slots Qt Tutorial

broken image


This example was ported from the PyQt4 version by Guðjón Guðjónsson.

Every time a signal emits, the connected slots are consecutively run with the data that is emitted. Emit ( 3 ); // Pass the '3' to all the slot functions. 2 Every emit, the slots are consecutively run - this means that your slots should by nature be short and concise! Widgets emit signals when events occur. For example, a button will emit a clicked signal when it is clicked. A developer can choose to connect to a signal by creating a function (a slot) and calling the connect function to relate the signal to the slot. Qt's signals and slots mechanism does not require classes to have knowledge of each other. I hope these articles have demystified signals and slots, and that knowing a bit how this works under the hood will help you make better use of them in your applications. Woboq is a software company that specializes in development and consulting around Qt and C.

The receivers of signals are called Slots in Qt terminology. A number of standard slots are provided on Qt classes to allow you to wire together different parts of your application. However, you can also use any Python function as a slot, and therefore receive the message yourself. Signals and slots are loosely coupled: A class which emits a signal neither knows nor cares which slots receive the signal. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type.

Introduction

In some applications it is often necessary to perform long-running tasks, such as computations or network operations, that cannot be broken up into smaller pieces and processed alongside normal application events. In such cases, we would like to be able to perform these tasks in a way that does not interfere with the normal running of the application, and ensure that the user interface continues to be updated. One way of achieving this is to perform these tasks in a separate thread to the main user interface thread, and only interact with it when we have results we need to display.

This example shows how to create a separate thread to perform a task - in this case, drawing stars for a picture - while continuing to run the main user interface thread. The worker thread draws each star onto its own individual image, and it passes each image back to the example's window which resides in the main application thread.

The User Interface

Tutorial

We begin by importing the modules we require. We need the math and random modules to help us draw stars.

The main window in this example is just a QWidget. We create a single Worker instance that we can reuse as required.

The user interface consists of a label, spin box and a push button that the user interacts with to configure the number of stars that the thread wil draw. The output from the thread is presented in a QLabel instance, viewer.

We connect the standard finished() and terminated() signals from the thread to the same slot in the widget. This will reset the user interface when the thread stops running. The custom output(QRect, QImage) signal is connected to the addImage() slot so that we can update the viewer label every time a new star is drawn.

The start button's clicked() signal is connected to the makePicture() slot, which is responsible for starting the worker thread.

We place each of the widgets into a grid layout and set the window's title:

The makePicture() slot needs to do three things: disable the user interface widgets that are used to start a thread, clear the viewer label with a new pixmap, and start the thread with the appropriate parameters.

Since the start button is the only widget that can cause this slot to be invoked, we simply disable it before starting the thread, avoiding problems with re-entrancy.

We call a custom method in the Worker thread instance with the size of the viewer label and the number of stars, obtained from the spin box.

Whenever is star is drawn by the worker thread, it will emit a signal that is connected to the addImage() slot. This slot is called with a QRect value, indicating where the star should be placed in the pixmap held by the viewer label, and an image of the star itself:

We use a QPainter to draw the image at the appropriate place on the label's pixmap.

We hope you enjoy your next visit to Crown. Dress Code For the main areas of the casino, dress is neat casual. Click here or call Crown's Guest Services on +61 3 9292 8888 for further information. Uncollected Goods including Lost Property. There are tips and tricks that you need to learn if you want to boost your chance of Crown Casino Anzac Day Opening Hours winning on slot machines. Keep learning new tricks and increase your chances of Crown Casino Anzac Day Opening Hours winning on slot machines. A: Crown Perth Casino operates 24 hours a day, seven days a week with the exception of Christmas Day, Good Friday and ANZAC Day. Please call +61 8 9362 7777 if you would like to know the opening times on these days. Crown casino opening hours anzac day 2019. Crown Perth Casino is open 24 hours a day, 7 days a week with the exception Christmas Day and Good Friday where the casino gaming area is closed from 3am until 10pm and on Anzac Day where the gaming floor is closed from 3am until midday: Dress Code: Visitors to Crown Casino Perth are required to dress smart casual at all times while in the casino. Crown is open 24 hours a day, 7 days a week except on Christmas Day, Good Friday and Anzac Day. On these days Crown is closed from 4am and re opens 12 noon. How to get to Crown Casino Map Southern Cross is the closest train station.

The updateUi() slot is called when a thread stops running. Since we usually want to let the user run the thread again, we reset the user interface to enable the start button to be pressed:

Now that we have seen how an instance of the Window class uses the worker thread, let us take a look at the thread's implementation.

The Worker Thread

The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application.

We define size and stars attributes that store information about the work the thread is required to do, and we assign default values to them. The exiting attribute is used to tell the thread to stop processing.

Each star is drawn using a QPainterPath that we define in advance:

Before a Worker object is destroyed, we need to ensure that it stops processing. For this reason, we implement the following method in a way that indicates to the part of the object that performs the processing that it must stop, and waits until it does so.

For convenience, we define a method to set up the attributes required by the thread before starting it.

The start() method is a special method that sets up the thread and calls our implementation of the run() method. We provide the render() method instead of letting our own run() method take extra arguments because the run() method is called by PyQt itself with no arguments.

The run() method is where we perform the processing that occurs in the thread provided by the Worker instance:

Information stored as attributes in the instance determines the number of stars to be drawn and the area over which they will be distributed.

We draw the number of stars requested as long as the exiting attribute remains False. This additional check allows us to terminate the thread on demand by setting the exiting attribute to True at any time.

The drawing code is not particularly relevant to this example. We simply draw on an appropriately-sized transparent image.

For each star drawn, we send the main thread information about where it should be placed along with the star's image by emitting our custom output() signal:

Since QRect and QImage objects can be serialized for transmission via the signals and slots mechanism, they can be sent between threads in this way, making it convenient to use threads in a wide range of situations where built-in types are used.

Running the Example

We only need one more piece of code to complete the example:

Most PyQt GUI applications consist of a main window and several dialogs. Dialogs are small-sized windows that allow you to communicate with your users, either by showing messages on the screen or by taking the user's input. You can use Qt Designer to create dialogs taking advantage of the variety of options that this tool offers.

In this tutorial, we'll learn how to create and customize dialogs using Qt Designer. We'll also learn two different ways of using and launching dialogs in our GUI applications. With this knowledge, we'll be able to add dialogs to our applications quickly and easily.

For a better understanding of the topics we'll cover in this tutorial, it will help to have some previous knowledge about PyQt applications, widgets, layouts and signals and slots.

Getting Started With PyQt Dialogs

In GUI programming, dialogs are small-sized windows that offer auxiliary functionalities and allow you to communicate with your users. Some common examples of dialogs include the Open Document dialog in a word processor or a text editor, the Settings or Preferences dialogs in most GUI applications, the Search dialog in a file manager or a text editor, and so on.

Dialogs are also often used to show error messages or general information on a given operation. They can also be used to ask the users their confirmation to continue with an operation or to take input from the user for a database.

PyQt offers a rich collection of built-in dialog classes that you can use directly in your applications. Some of them are:

  • QFontDialog for selecting a font
  • QPrintDialog for specifying the printer's configuration
  • QProgressDialog for providing feedback on the progress of a slow operation
  • QColorDialog for specifying colors
  • QInputDialog for getting a single value from the user
  • QFileDialog for selecting files or directories

Additionally, PyQt provides the QDialog class for creating entirely custom dialogs when there is no built-in available for the operation that you need to perform.

While we can use the QDialog class to build dialogs in Python code, we can also use Qt Designer to create custom dialogs in the drag and drop editor. Qt Designer is a Qt tool that offers a user-friendly GUI that will allow us to quickly create and set up our dialogs and windows.

Creating Dialogs With Qt Designer

You can use Qt Designer to create and customize the user interface of your custom dialogs. With Qt Designer, you can create a dialog's GUI using a built-in template or you can create a dialog entirely from scratch. You can add widgets to your dialogs, arrange widgets in layouts, set their appearance, provide initial values for their attributes, set their tab order, create buddies to provide keyboard shortcuts, and connect the widgets' built-in signals to slots.

When we create a dialog using Qt Designer, the dialog's GUI is stored in a .ui file, which is an XML file that provides all the information we'll need to later build the dialog GUI in our applications.

In the next few sections we'll look at how to create and customize dialog's GUI using Qt Designer.

Using Qt Designer's Dialog Templates

When we launch Qt Designer, we are presented with the application's main window and with a dialog called New Form. This dialog allows us to select a template for the GUI we want to create. These templates include options to create dialogs, main windows, and custom widgets.

In this tutorial, we're just interested in how to create dialogs with Qt Designer. So, we'll just cover the 3 templates Qt Designer offers for creating dialogs:

  1. Dialog with Buttons Bottom to create a form (or dialog) with an OK and a Cancel buttons horizontally-arranged on the bottom-right corner of the form

  2. Dialog with Buttons Right to create a form with an OK and a Cancel buttons vertically-arranged on the top-right corner of the form

  3. Dialog without Buttons to create an empty form without buttons

The following screencast shows how we can use Qt Designer to create custom dialogs using the different (default) dialog templates:

To create a dialog using a Qt Designer's template, we just need to select the desired template from the New Form dialog and then click on the Create button or hit Alt+R on our keyboard.

If when you launch Qt Designer, the New Form dialog doesn't appear, then you can click on the New button on Qt Designer's toolbar. You can also click on the File>New.. main menu option or press the Ctrl+N key combination on your keyboard.

Adding Widgets and Layouts

Widgets are the building blocks of any PyQt GUI application. You can use widgets to display information, get the user's input, and provide containers for other widgets that should be grouped. With Qt Designer, you can add widgets to our dialogs and windows by dragging and doping them from Qt Designer's Widget Box panel to your form. Once you have all the required widgets in place, you can arrange them using Qt's layouts.

Signals And Slots Qt Tutorial

Say your company is creating a database application to manage the employees' relevant information. You're asked to add a new PyQt dialog to enter or update general information about employees. The dialog must include options to enter the following info: Employee name, Employment date, Department, Position, Annual salary andJob description.

The following screencast shows how we can quickly create the GUI for the dialog at hand using Qt Designer:

Here, we first create a dialog using the Dialog with Buttons Bottom template. Then, we add QLabel objects to ask for the needed information. Every field needs a specific input widget. For example, we add a QLineEdit object for the Employee name, a QDateEdit object for the Employment date, two QComboBox objects for the Department and the Position, a QDoubleSpinBox object for the Annual salary, and a QTextEdit object for the Job description field.

Once we have all the widgets in place, we select all of them and arrange them using a QFormLayout object. The final step is to add a main layout to the dialog. To do that, we use a QVBoxLayout object that allows us to arrange the widgets and the dialog's buttons in a vertical column. That's all, we've created our first dialog using Qt Designer. Let's save the dialog's GUI file with the name employee.ui for later use.

If you want to have a preview of how your dialog will look like in production, then you can press the Ctrl+R key combination or click on the Form>Preview.. option on Qt Designer's main menu.

In this section, we've used Qt Designer in Edit Widgets mode, which is the default mode. In this mode, we can add widgets to our dialogs, edit widget's properties, lay out the widgets on the dialog's GUI, and so on. To activate the Edit Widgets mode, we can choose any of the three following options:

  1. Press the F3 key
  2. Select the Edit>Edit Widgets option from the main menu
  3. Click on the Edit Widgets button on Qt Designer's toolbar.

Setting Tab Order of Input Widgets

An element that can improve the usability of your dialogs is the tab order of the input widgets. The tab order is the order in which the input widgets get the focus when you hit the Tab or Shift+Tab keys. The default tab order is based on the order in which you place the widgets on the form.

For example, in our employee dialog, we placed the QDoubleSpinBox object for the Annual salary after the QTextEdit object for the Job description. If the user hits the Tab key for moving around the dialog, then they'll note that when they hit Tab to move from the PositionQComboBox to the Annual salaryQDoubleSpinBox what happens is that the focus goes to the Job descriptionQTextEdit. This is a kind of annoying behavior. The following screencast shows the problem:

Note that when the focus is on the PositionQComboBox and the user hits Tab, the focus jumps directly to the Job descriptionQTextEdit instead of jumping to the Annual SalaryQDoubleSpinBox as we would expect.

To fix this problem, we need to change the tab order of the input widgets on our dialog. Firstly, we need to switch to the Edit Tab Order mode in Qt Designer. To do that, we can either select the Edit>Edit Tab Order option on the main menu or click on the Edit Tab Order button on the toolbar.

In Edit Tab Order mode, each input widget in the form is shown with a number that indicates its position in the tab order chain. We can change the tab order by clicking on the number of each widget in the correct order. You can see how to do this in the following screencast:

In this example, we change the tab order of the input widgets by clicking on each number in the correct order. When we select a number, it changes to red to indicate that this is the currently edited position in the tab order. When we click on another number, then that number will be second in the tab order, and so on.

In case of a mistake, we can restart numbering by choosing Restart from the form's context menu. To partially edit the tab order, we can select a number with the Ctrl key pressed. The tab order will be changed from that widget on. We can also right-click on a given number and then choose Start from Here from the context menu.

Defining Buddies

In Qt, buddies are connections between related widgets. Normally between a QLabel widget and an input widget like a QLineEdit or a QComboBox. These connections allow you to provide a quick keyboard shortcut to move the focus to a given input widget. By setting buddies, you'll improve the usability of your dialogs because you'll provide the user with a fast way to move around dialogs and windows.

In our employee dialog, to move the focus to the Annual salaryQDoubleSpinBox, we can set a buddy between it and the Annual salaryQLabel widget. The buddy will automatically provide a key combination of the form Alt+Letter, in which Letter represents a single letter in the text of the label.

In our Annual salaryQLabel, that letter could be A or s or any other letter in the text of the label. The only restriction is that the selected letter doesn't clash with the letter of any other buddy in the dialog or window at hand.

To select a letter to use in our buddy, we need to place an ampersand (&) before the letter in the text of the label. With this addition, we provide the letter to use in the keyboard shortcut. For example, if we place the ampersand before the letter s in our Annual salaryQLabel, then we'll be able to access the Annual salaryQDoubleSpinBox by hitting the Alt+S shortcut on our keyboard.

Once we have selected the letters to use and placed the corresponding ampersands, we need to set the buddies. To do that, we'll activate the Edit Buddies mode in Qt Designer by either selecting the Edit>Edit Buddies option from the main menu or by clicking the Edit Buddies button on the toolbar.

To define the buddies, we'll click on a label and drag it over the corresponding input widget. The whole process is illustrated in the following screencast:

To create buddies between labels and input widgets, we can select a label with our mouse and drag it to the input widget that we want to set as its buddy. The label and the input widget will become buddies. From this point on, our users will be able to quickly move the focus to a specific input widget by pressing Alt+Letter, where Letter will be the letter that we used to define the buddy relation. Note that the buddy letters will be underlined to point the right key combination to use.

Using Button Boxes to Lay Out Dialog's Buttons

There is a standard set of buttons that you can use when it comes to creating dialogs. Even though Qt Designer's templates provide an OK button and a Cancel button, in practice you'll see dialogs that use different buttons like Apply, Close, Yes, No, and so on.

In our employee example, we've used a Cancel and an OK button, which were placed in that same order from left to right. This is the usual order for buttons on Linux or macOS but not for Windows, where the order should be swapped.

If we want that our GUI applications look as native as possible on different platforms, then we'll need to deploy different dialogs for different platforms just to show the buttons in the right order for the platform at hand.

Fortunately, PyQt provides an effective solution for this particular problem. Instead of adding a Cancel and an OK button directly, we can use the QDialogButtonBox class and select the buttons according to our needs. This PyQt class will automatically handle the order of the buttons for us according to the standard practice on the underlying platform.

Here's how our employee dialog looks like on Windows 10, Linux, and macOS:

Button Box on Windows

Button Box on Linux

Button Box on macOS

n Windows, the buttons at the bottom-right corner of the dialog are shown swapped if you compare them with the same dialog running on Linux or macOS. That's because Qt Designer's dialog templates use a QDialogButtonBox object by default to lay out the buttons on the dialog. This is quite convenient if you're creating multi-platform GUI applications with PyQt.

We can select the buttons that we want to show on our dialogs by changing the .standardButtons property of the QDialogButtonBox object on Qt Designer's Property Editor. Take a look at the following screencast:

The Property Editor allows us to set the .standardButtons property of a QDialogButtonBox object and to select different sets of standard buttons. Note that when we change the buttons in the QDialogButtonBox, they get placed according to the standard practice on the current platform.

Signals And Slots Qt Tutorial For Beginners

Connecting Built-in Signals and Slots

In PyQt, the user's actions over the widget of a GUI applications are called events. When an event occurs, the widget at hand emits a signal to let you know that the event has occurred. To give life to your applications, you need to connect those signals to specific slots. Slots are methods that are executed as a response to events.

Most widgets implement built-in signals that are emitted when a given event (like a mouse click) occurs on the widget. Widgets also provide built-in slots that allow you to perform certain actions on the widget. For example, a QTextEdit object provides a .clear() slot that you can connect to a button or to a menu option to clear the content of the widget.

You can use Qt Designer to connect these built-in signals and slots. To establish a signal and slot connection between two widgets in a dialog, you first need to switch to Qt Designer's Edit Signals/Slots mode. To do that, you can press the F4 key, select the Edit>Edit Signals/Slots option in the main menu, or click on the Edit Signals/Slots button on the toolbar.

Once in the Edit Signals/Slots mode, you select the signal-provider widget with your mouse and then drag and drop this widget over the slot-provider widget. This will launch Qt Designer's Configure Connection dialog.

The Configure Connection dialog has two panels. In the left panel, you can select a signal and in the right panel, you can select a slot. Then, you need to press the OK button to create the connection. This will draw an arrow from the signal-provider widget to the slot-provider widget indicating that the connection is established. Additionally, you'll see the name of the signal and the slot that you just connect.

For example, suppose we have a dialog with a QTextEdit and a QPushButton. We need to connect the .clicked() signal of the button with the .clear() slot of the text edit, so we can clear the content of the text edit by clicking on the button. Check out the following example:

In this example, we first switch to the Edit Signals/Slots mode. Then, we select the Clear button, drag it, and drop it over the QTextEdit object. This presents us with the Configure Connection dialog. In this dialog, we select the .clicked() signal in the left panel and the .clear() slot in the right panel. When we press OK, the connection gets established. We can also click on the Cancel button to cancel the connection operation.

Signals And Slots Qt Tutorial

We begin by importing the modules we require. We need the math and random modules to help us draw stars.

The main window in this example is just a QWidget. We create a single Worker instance that we can reuse as required.

The user interface consists of a label, spin box and a push button that the user interacts with to configure the number of stars that the thread wil draw. The output from the thread is presented in a QLabel instance, viewer.

We connect the standard finished() and terminated() signals from the thread to the same slot in the widget. This will reset the user interface when the thread stops running. The custom output(QRect, QImage) signal is connected to the addImage() slot so that we can update the viewer label every time a new star is drawn.

The start button's clicked() signal is connected to the makePicture() slot, which is responsible for starting the worker thread.

We place each of the widgets into a grid layout and set the window's title:

The makePicture() slot needs to do three things: disable the user interface widgets that are used to start a thread, clear the viewer label with a new pixmap, and start the thread with the appropriate parameters.

Since the start button is the only widget that can cause this slot to be invoked, we simply disable it before starting the thread, avoiding problems with re-entrancy.

We call a custom method in the Worker thread instance with the size of the viewer label and the number of stars, obtained from the spin box.

Whenever is star is drawn by the worker thread, it will emit a signal that is connected to the addImage() slot. This slot is called with a QRect value, indicating where the star should be placed in the pixmap held by the viewer label, and an image of the star itself:

We use a QPainter to draw the image at the appropriate place on the label's pixmap.

We hope you enjoy your next visit to Crown. Dress Code For the main areas of the casino, dress is neat casual. Click here or call Crown's Guest Services on +61 3 9292 8888 for further information. Uncollected Goods including Lost Property. There are tips and tricks that you need to learn if you want to boost your chance of Crown Casino Anzac Day Opening Hours winning on slot machines. Keep learning new tricks and increase your chances of Crown Casino Anzac Day Opening Hours winning on slot machines. A: Crown Perth Casino operates 24 hours a day, seven days a week with the exception of Christmas Day, Good Friday and ANZAC Day. Please call +61 8 9362 7777 if you would like to know the opening times on these days. Crown casino opening hours anzac day 2019. Crown Perth Casino is open 24 hours a day, 7 days a week with the exception Christmas Day and Good Friday where the casino gaming area is closed from 3am until 10pm and on Anzac Day where the gaming floor is closed from 3am until midday: Dress Code: Visitors to Crown Casino Perth are required to dress smart casual at all times while in the casino. Crown is open 24 hours a day, 7 days a week except on Christmas Day, Good Friday and Anzac Day. On these days Crown is closed from 4am and re opens 12 noon. How to get to Crown Casino Map Southern Cross is the closest train station.

The updateUi() slot is called when a thread stops running. Since we usually want to let the user run the thread again, we reset the user interface to enable the start button to be pressed:

Now that we have seen how an instance of the Window class uses the worker thread, let us take a look at the thread's implementation.

The Worker Thread

The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application.

We define size and stars attributes that store information about the work the thread is required to do, and we assign default values to them. The exiting attribute is used to tell the thread to stop processing.

Each star is drawn using a QPainterPath that we define in advance:

Before a Worker object is destroyed, we need to ensure that it stops processing. For this reason, we implement the following method in a way that indicates to the part of the object that performs the processing that it must stop, and waits until it does so.

For convenience, we define a method to set up the attributes required by the thread before starting it.

The start() method is a special method that sets up the thread and calls our implementation of the run() method. We provide the render() method instead of letting our own run() method take extra arguments because the run() method is called by PyQt itself with no arguments.

The run() method is where we perform the processing that occurs in the thread provided by the Worker instance:

Information stored as attributes in the instance determines the number of stars to be drawn and the area over which they will be distributed.

We draw the number of stars requested as long as the exiting attribute remains False. This additional check allows us to terminate the thread on demand by setting the exiting attribute to True at any time.

The drawing code is not particularly relevant to this example. We simply draw on an appropriately-sized transparent image.

For each star drawn, we send the main thread information about where it should be placed along with the star's image by emitting our custom output() signal:

Since QRect and QImage objects can be serialized for transmission via the signals and slots mechanism, they can be sent between threads in this way, making it convenient to use threads in a wide range of situations where built-in types are used.

Running the Example

We only need one more piece of code to complete the example:

Most PyQt GUI applications consist of a main window and several dialogs. Dialogs are small-sized windows that allow you to communicate with your users, either by showing messages on the screen or by taking the user's input. You can use Qt Designer to create dialogs taking advantage of the variety of options that this tool offers.

In this tutorial, we'll learn how to create and customize dialogs using Qt Designer. We'll also learn two different ways of using and launching dialogs in our GUI applications. With this knowledge, we'll be able to add dialogs to our applications quickly and easily.

For a better understanding of the topics we'll cover in this tutorial, it will help to have some previous knowledge about PyQt applications, widgets, layouts and signals and slots.

Getting Started With PyQt Dialogs

In GUI programming, dialogs are small-sized windows that offer auxiliary functionalities and allow you to communicate with your users. Some common examples of dialogs include the Open Document dialog in a word processor or a text editor, the Settings or Preferences dialogs in most GUI applications, the Search dialog in a file manager or a text editor, and so on.

Dialogs are also often used to show error messages or general information on a given operation. They can also be used to ask the users their confirmation to continue with an operation or to take input from the user for a database.

PyQt offers a rich collection of built-in dialog classes that you can use directly in your applications. Some of them are:

  • QFontDialog for selecting a font
  • QPrintDialog for specifying the printer's configuration
  • QProgressDialog for providing feedback on the progress of a slow operation
  • QColorDialog for specifying colors
  • QInputDialog for getting a single value from the user
  • QFileDialog for selecting files or directories

Additionally, PyQt provides the QDialog class for creating entirely custom dialogs when there is no built-in available for the operation that you need to perform.

While we can use the QDialog class to build dialogs in Python code, we can also use Qt Designer to create custom dialogs in the drag and drop editor. Qt Designer is a Qt tool that offers a user-friendly GUI that will allow us to quickly create and set up our dialogs and windows.

Creating Dialogs With Qt Designer

You can use Qt Designer to create and customize the user interface of your custom dialogs. With Qt Designer, you can create a dialog's GUI using a built-in template or you can create a dialog entirely from scratch. You can add widgets to your dialogs, arrange widgets in layouts, set their appearance, provide initial values for their attributes, set their tab order, create buddies to provide keyboard shortcuts, and connect the widgets' built-in signals to slots.

When we create a dialog using Qt Designer, the dialog's GUI is stored in a .ui file, which is an XML file that provides all the information we'll need to later build the dialog GUI in our applications.

In the next few sections we'll look at how to create and customize dialog's GUI using Qt Designer.

Using Qt Designer's Dialog Templates

When we launch Qt Designer, we are presented with the application's main window and with a dialog called New Form. This dialog allows us to select a template for the GUI we want to create. These templates include options to create dialogs, main windows, and custom widgets.

In this tutorial, we're just interested in how to create dialogs with Qt Designer. So, we'll just cover the 3 templates Qt Designer offers for creating dialogs:

  1. Dialog with Buttons Bottom to create a form (or dialog) with an OK and a Cancel buttons horizontally-arranged on the bottom-right corner of the form

  2. Dialog with Buttons Right to create a form with an OK and a Cancel buttons vertically-arranged on the top-right corner of the form

  3. Dialog without Buttons to create an empty form without buttons

The following screencast shows how we can use Qt Designer to create custom dialogs using the different (default) dialog templates:

To create a dialog using a Qt Designer's template, we just need to select the desired template from the New Form dialog and then click on the Create button or hit Alt+R on our keyboard.

If when you launch Qt Designer, the New Form dialog doesn't appear, then you can click on the New button on Qt Designer's toolbar. You can also click on the File>New.. main menu option or press the Ctrl+N key combination on your keyboard.

Adding Widgets and Layouts

Widgets are the building blocks of any PyQt GUI application. You can use widgets to display information, get the user's input, and provide containers for other widgets that should be grouped. With Qt Designer, you can add widgets to our dialogs and windows by dragging and doping them from Qt Designer's Widget Box panel to your form. Once you have all the required widgets in place, you can arrange them using Qt's layouts.

Say your company is creating a database application to manage the employees' relevant information. You're asked to add a new PyQt dialog to enter or update general information about employees. The dialog must include options to enter the following info: Employee name, Employment date, Department, Position, Annual salary andJob description.

The following screencast shows how we can quickly create the GUI for the dialog at hand using Qt Designer:

Here, we first create a dialog using the Dialog with Buttons Bottom template. Then, we add QLabel objects to ask for the needed information. Every field needs a specific input widget. For example, we add a QLineEdit object for the Employee name, a QDateEdit object for the Employment date, two QComboBox objects for the Department and the Position, a QDoubleSpinBox object for the Annual salary, and a QTextEdit object for the Job description field.

Once we have all the widgets in place, we select all of them and arrange them using a QFormLayout object. The final step is to add a main layout to the dialog. To do that, we use a QVBoxLayout object that allows us to arrange the widgets and the dialog's buttons in a vertical column. That's all, we've created our first dialog using Qt Designer. Let's save the dialog's GUI file with the name employee.ui for later use.

If you want to have a preview of how your dialog will look like in production, then you can press the Ctrl+R key combination or click on the Form>Preview.. option on Qt Designer's main menu.

In this section, we've used Qt Designer in Edit Widgets mode, which is the default mode. In this mode, we can add widgets to our dialogs, edit widget's properties, lay out the widgets on the dialog's GUI, and so on. To activate the Edit Widgets mode, we can choose any of the three following options:

  1. Press the F3 key
  2. Select the Edit>Edit Widgets option from the main menu
  3. Click on the Edit Widgets button on Qt Designer's toolbar.

Setting Tab Order of Input Widgets

An element that can improve the usability of your dialogs is the tab order of the input widgets. The tab order is the order in which the input widgets get the focus when you hit the Tab or Shift+Tab keys. The default tab order is based on the order in which you place the widgets on the form.

For example, in our employee dialog, we placed the QDoubleSpinBox object for the Annual salary after the QTextEdit object for the Job description. If the user hits the Tab key for moving around the dialog, then they'll note that when they hit Tab to move from the PositionQComboBox to the Annual salaryQDoubleSpinBox what happens is that the focus goes to the Job descriptionQTextEdit. This is a kind of annoying behavior. The following screencast shows the problem:

Note that when the focus is on the PositionQComboBox and the user hits Tab, the focus jumps directly to the Job descriptionQTextEdit instead of jumping to the Annual SalaryQDoubleSpinBox as we would expect.

To fix this problem, we need to change the tab order of the input widgets on our dialog. Firstly, we need to switch to the Edit Tab Order mode in Qt Designer. To do that, we can either select the Edit>Edit Tab Order option on the main menu or click on the Edit Tab Order button on the toolbar.

In Edit Tab Order mode, each input widget in the form is shown with a number that indicates its position in the tab order chain. We can change the tab order by clicking on the number of each widget in the correct order. You can see how to do this in the following screencast:

In this example, we change the tab order of the input widgets by clicking on each number in the correct order. When we select a number, it changes to red to indicate that this is the currently edited position in the tab order. When we click on another number, then that number will be second in the tab order, and so on.

In case of a mistake, we can restart numbering by choosing Restart from the form's context menu. To partially edit the tab order, we can select a number with the Ctrl key pressed. The tab order will be changed from that widget on. We can also right-click on a given number and then choose Start from Here from the context menu.

Defining Buddies

In Qt, buddies are connections between related widgets. Normally between a QLabel widget and an input widget like a QLineEdit or a QComboBox. These connections allow you to provide a quick keyboard shortcut to move the focus to a given input widget. By setting buddies, you'll improve the usability of your dialogs because you'll provide the user with a fast way to move around dialogs and windows.

In our employee dialog, to move the focus to the Annual salaryQDoubleSpinBox, we can set a buddy between it and the Annual salaryQLabel widget. The buddy will automatically provide a key combination of the form Alt+Letter, in which Letter represents a single letter in the text of the label.

In our Annual salaryQLabel, that letter could be A or s or any other letter in the text of the label. The only restriction is that the selected letter doesn't clash with the letter of any other buddy in the dialog or window at hand.

To select a letter to use in our buddy, we need to place an ampersand (&) before the letter in the text of the label. With this addition, we provide the letter to use in the keyboard shortcut. For example, if we place the ampersand before the letter s in our Annual salaryQLabel, then we'll be able to access the Annual salaryQDoubleSpinBox by hitting the Alt+S shortcut on our keyboard.

Once we have selected the letters to use and placed the corresponding ampersands, we need to set the buddies. To do that, we'll activate the Edit Buddies mode in Qt Designer by either selecting the Edit>Edit Buddies option from the main menu or by clicking the Edit Buddies button on the toolbar.

To define the buddies, we'll click on a label and drag it over the corresponding input widget. The whole process is illustrated in the following screencast:

To create buddies between labels and input widgets, we can select a label with our mouse and drag it to the input widget that we want to set as its buddy. The label and the input widget will become buddies. From this point on, our users will be able to quickly move the focus to a specific input widget by pressing Alt+Letter, where Letter will be the letter that we used to define the buddy relation. Note that the buddy letters will be underlined to point the right key combination to use.

Using Button Boxes to Lay Out Dialog's Buttons

There is a standard set of buttons that you can use when it comes to creating dialogs. Even though Qt Designer's templates provide an OK button and a Cancel button, in practice you'll see dialogs that use different buttons like Apply, Close, Yes, No, and so on.

In our employee example, we've used a Cancel and an OK button, which were placed in that same order from left to right. This is the usual order for buttons on Linux or macOS but not for Windows, where the order should be swapped.

If we want that our GUI applications look as native as possible on different platforms, then we'll need to deploy different dialogs for different platforms just to show the buttons in the right order for the platform at hand.

Fortunately, PyQt provides an effective solution for this particular problem. Instead of adding a Cancel and an OK button directly, we can use the QDialogButtonBox class and select the buttons according to our needs. This PyQt class will automatically handle the order of the buttons for us according to the standard practice on the underlying platform.

Here's how our employee dialog looks like on Windows 10, Linux, and macOS:

Button Box on Windows

Button Box on Linux

Button Box on macOS

n Windows, the buttons at the bottom-right corner of the dialog are shown swapped if you compare them with the same dialog running on Linux or macOS. That's because Qt Designer's dialog templates use a QDialogButtonBox object by default to lay out the buttons on the dialog. This is quite convenient if you're creating multi-platform GUI applications with PyQt.

We can select the buttons that we want to show on our dialogs by changing the .standardButtons property of the QDialogButtonBox object on Qt Designer's Property Editor. Take a look at the following screencast:

The Property Editor allows us to set the .standardButtons property of a QDialogButtonBox object and to select different sets of standard buttons. Note that when we change the buttons in the QDialogButtonBox, they get placed according to the standard practice on the current platform.

Signals And Slots Qt Tutorial For Beginners

Connecting Built-in Signals and Slots

In PyQt, the user's actions over the widget of a GUI applications are called events. When an event occurs, the widget at hand emits a signal to let you know that the event has occurred. To give life to your applications, you need to connect those signals to specific slots. Slots are methods that are executed as a response to events.

Most widgets implement built-in signals that are emitted when a given event (like a mouse click) occurs on the widget. Widgets also provide built-in slots that allow you to perform certain actions on the widget. For example, a QTextEdit object provides a .clear() slot that you can connect to a button or to a menu option to clear the content of the widget.

You can use Qt Designer to connect these built-in signals and slots. To establish a signal and slot connection between two widgets in a dialog, you first need to switch to Qt Designer's Edit Signals/Slots mode. To do that, you can press the F4 key, select the Edit>Edit Signals/Slots option in the main menu, or click on the Edit Signals/Slots button on the toolbar.

Once in the Edit Signals/Slots mode, you select the signal-provider widget with your mouse and then drag and drop this widget over the slot-provider widget. This will launch Qt Designer's Configure Connection dialog.

The Configure Connection dialog has two panels. In the left panel, you can select a signal and in the right panel, you can select a slot. Then, you need to press the OK button to create the connection. This will draw an arrow from the signal-provider widget to the slot-provider widget indicating that the connection is established. Additionally, you'll see the name of the signal and the slot that you just connect.

For example, suppose we have a dialog with a QTextEdit and a QPushButton. We need to connect the .clicked() signal of the button with the .clear() slot of the text edit, so we can clear the content of the text edit by clicking on the button. Check out the following example:

In this example, we first switch to the Edit Signals/Slots mode. Then, we select the Clear button, drag it, and drop it over the QTextEdit object. This presents us with the Configure Connection dialog. In this dialog, we select the .clicked() signal in the left panel and the .clear() slot in the right panel. When we press OK, the connection gets established. We can also click on the Cancel button to cancel the connection operation.

The connection appears as an arrow connecting the two widgets with two labels indicating the name of the signal and the slot that each widget provides.

To modify a connection, you can double-click on the arrow or one of the labels. This will display the Configure Connection dialog, where you can change the signal or the slot involved in the connection.

To delete a connection, you can select the arrow that represents the connection or one of the labels that identify the signal and the slot, and then press the Del key.

Since dialogs are also widgets, you can connect a signal of a widget (say a button) with a slot of the dialog or form. The process is the same, you just need to drag and drop the widget over the form and then configure the desired signal and slot from the Configure Connection dialog.

Finally, if you use a Qt Designer's template for creating a dialog with a button box, then you'll note that the .accepted() signal of the QDialogButtonBox object is connected by default with the .accept() slot of the form. Likewise, the .rejected() signal is connected with the reject() slot. So, your dialog is fully functional from the very beginning.

Using Dialogs in a GUI Application

So far, you've learned how to create custom dialogs with Qt Designer but how can you use those dialogs in your GUI applications? PyQt provides at least two ways for doing that. We can:

  1. Generate the Python code for the dialog's GUI using a command-line tool called pyuic5 on the .ui file
  2. Dynamically load the code for the dialog's GUI using the uic.loadUi() function

The first option is the most common and widely used because it's more efficient when it comes to working with complex dialogs. However, it has the drawback that every time you modify the dialog with Qt Designer, you have to generate the code again.

The second option may be suitable when you're working with quite small and simple dialogs that don't involve substantial loading time.

Generating the Dialog's GUI With pyuic5

You can use the command-line tool pyuic5 to convert your .ui files into .py files that contain the Python code to build your dialogs' GUI. To do that, you need to open a command-line or terminal and run a command like this:

This command will generate a Python module called dialog.py from the dialog.ui file that we just created using Qt Designer.

Let's run the command targeting our employee dialog:

sh

This command generates a Python module called employee_dlg.py. This module contains the Python code for the dialog's GUI. Here's a small piece of the code:

The Ui_Dialog class has all the code we need to generate the dialog's GUI. The .setupUi() method contains the code that adds the widgets and lay them out on the dialog's GUI. The retranslateUi() method contains code for internationalization and localization but this topic is beyond the scope of this tutorial. So, we'll just consider .setupUi() here.

Let's create a PyQt main window-style application that allows us to use this Python module for launching our employee dialog. Here's the code:

python

We first import the required classes from the PyQt5 package. Then, we import the Ui_Dialog class from our employee_dlg module.

The Window class will be the main window of our application. In this case, we use a QPushButton as a central widget. This means that our application will show a window with a single button on it. Then, we'll connect the .clicked() signal of the button with the onEmployeeBtnClicked() slot.

Inside onEmployeeBtnClicked(), we create an instance of EmployeeDlg using our main window (self) as its parent and then launch it using its .exec() method.

In the EmployeeDlg class, we implement our dialog inheriting from the QDialog class. Inside the __init__() method, we create an instance of Ui_Dialog, which is the class that holds the code for creating our dialog's GUI. The final step is to call the .setupUi() method.

You can also use multiple inheritance when creating the EmployeeDlg class. In other words, you can declare the class as class EmployeeDlg(QDialog, Ui_Dialog): and then call the .setupUi() method as self.setupUi() inside the __init__() method.

Finally, we complete the application by running the following steps:

  1. Create an instance of the QApplication class
  2. Create an instance of our Window class
  3. Call the .show() method on our Window object
  4. Run the application's main loop calling app.exec()

Let's run the application and click on the Employee.. button. Here's how it works:

The application's main window has a single widget, the Employee.. button. When we click on this button, our employee dialog appears on the screen.

The final ellipsis in the text of the Employee.. button is a common convention that you can use to point that this button (or menu option) doesn't perform an immediate action but launches a dialog for further processing.

Even though we used a QPushButton to launch our dialog, in real-world applications we normally connect a slot like onEmployeeBtnClicked() to a toolbar button, a main menu option, or a context menu option.

Loading the Dialog's GUI With uic.loadUi()

You also have the option of dynamically loading the dialog's GUI directly from your .ui file using the uic.loadUi() function. uic.loadUi() takes a .ui file as an argument and returns a QWidget subclass that implements the GUI.

To dynamically load our employee dialog, for example, we need to make some changes to our employeeapp.py file. Firstly, we'll remove the line from employee_dlg import Ui_Dialog because we don't need ti anymore. Then, we'll add the following import:

Once we have access to uic.loadUi(), we need to modify the EmployeeDlg class as follows:

python

The __init__() method of EmployeeDlg now calls loadUi() taking 'employee.ui' as its first argument. Note that this should be the path to the .ui file. The second argument to loadUi() is called baseinstance. It's an optional argument. If specified, then the GUI is created in it. If we pass self to this argument, then we're ensuring that the GUI will be created in the instance of EmployeeDlg.

With this last change, we're done. Our application will work as expected. Note that the rest of the code remains the same. You can now run the application by yourself and see the result.

This way of loading dialogs is rarely used in practice, although it may be useful when you're working with simple and small dialogs. It has the advantage that you don't need to generate the Python code for the dialog's GUI every time you modify the .ui file using Qt Designer, which can be a productivity and maintainability win in some cases.

Signals And Slots Qt Tutorial For Beginners

Conclusion

When it comes to creating PyQt GUI applications you commonly use a main window and several dialogs. Dialogs allow you to communicate with your users (hence the name dialog). You can use dialogs to show messages on the screen or to take the user's input. Qt provides Qt Designer for creating dialogs in a fast and productive way.

In this tutorial, we covered how to create and customize dialogs using Qt Designer. We also learned about two different ways of using and launching dialogs in our GUI applications, either by generating the dialog's GUI code or by loading it dynamically.

Signals And Slots Qt Tutorial Gratis

With this knowledge, you'll be able to use Qt Designer to create fully-functional dialogs for your GUI applications in a quick and productive way.





broken image