PyQT: Handling Windows and Buttons

In this article, you will continue to learn about the process of building a GUI in PyQT. Specifically, you will learn about QDialog and QPushButton, which handle windows and buttons, the building blocks of most GUIs.

Understanding the steps involved in a process in just the first step in the journey of understanding the process. In the first part of PyQT, the first step in understanding the process of building a GUI using PyQT was taken. The journey has just begun.

In this journey we will be encountering various components starting with the most common widgets (windows, buttons, etc.) and moving on to exquisite widgets (table view, 3d canvas). In this discussion I will be focusing on the most common  ones that become the foundation of a GUI based application: the window and button. In the vocabulary of PyQT they are termed as QWindow (QDialog, QMainWindow, and so on also serve this purpose) and QButton (QPushButton, QRadioButton, and so forth).

In the first section, I will be discussing QDialog. Then I will cover the main slots and signals of QDialog. In the third section I will discuss QPushButton. Finally, in the last section I will extend the application developed in the previous part to provide the functionalities of changing the display to binary mode, as well as controlling the application window using buttons. That sets the agenda for this discussion.

QDialog and QPushButton: Gateways to PyQT Applications

Dialogs and buttons are the most recognized facets of GUI. So how can a toolkit like PyQT be behind? As with all other widgets, it is necessary to know the details in order to tap into their full power. So here are the details.

First, let’s discuss the QDialog class. As you know, windows form the basis of all the GUI-based applications. However there are windows and windows. There is a category of windows that acts as containers for other windows and widgets, such as menus and so on. Then there is a category that acts as a container for simple widgets, and is used for capturing user inputs for a specific process.

The first category contains the Main Window of an application, and the second category contains the dialog boxes. Though dialog boxes are primarily used to gather user inputs, there are applications that are built completely upon dialog boxes. In this section I will be discussing the attributes, signals and slots that are required more often in building a dialog based application.

Dialog, by definition, is a window that pops up over the existing application window. The QDialog class is the parent of all the dialog classes. If you remember the “Hello World” application from the first part, the class was derived from QDialog. Now coming back to the QDialog class, it effectively represents the dialogs of real world user interfaces. Since there are two types of dialogs in real world, so the QDialog also supports two types of dialogs, modal and modeless. The important aspect of any type of dialog is that even though it is top level widget, yet it can have a parent.

Now, let’s discuss modal dialogues. If a dialog blocks input to the other widgets, then it is modal.  The most common way to make a dialog modal is by calling its exec_loop() method. The exec_loop() method returns a useful value when the dialog is closed. One other approach is to call the setModal() method with true. But this has to be done before calling the show() method, because once show() is called, setModal() wont have any effect.

For example, if mDialog is an object of the MDialog class that is derived from QDialog, then:

    mDialog.setModal(true)
  mDialog.show()

    and

    mDialog.exec_loop()

    perform the same function. That is both methods makes the dialog modal.

As for a modeless dialogue, its functioning is opposite to that of a modal dialog. The best examples of modeless dialog boxes are search/replace dialogs provided by word processors. Dialogs are made modeless by calling the show() method instead of the QDialog class. The show() method doesn’t grab the focus from other window elements. Instead it returns to the caller immediately.

{mospagebreak title=Slots} 

The show() and exec_loop() methods determine whether the dialogs are modal  or modeless. However the main purpose of dialogs is to provide information feedback to the user, as well as to gather information from the user using buttons such as OK and Cancel. For these purposes, the accept() and reject() slots have been provided by the QDialog class. 

Both of these are protected Slots. They are available only to the classes inherited from QDialog.

The accept() slot closes the dialog and sets the return value to ACCEPTED. This value is equivalent to the Boolean value of 1. The best scenario to visualize the usage of accept() is a button representing OK. If the clicked signal of this button is connected with the accept() slot, then upon the button being clicked, the dialog box would be closed and the return value would become ACCEPTED. In code this would be:

       self.OK = QPushButton(self,”OK”)
   self.connect(self.OK,SIGNAL(“clicked()”),self.accept)

The above code is a snippet from an about dialog. When the OK button is clicked, the signal connects to the accept() dialog.

The reject() slot provides functionalities that are the opposite of accept(). It comes into picture when the dialog is canceled. The return code is set to Rejected. This slot can be connected to the signal corresponding to the dialog box or any button’s clicked() signal. If the button’s clicked() signal is connected, then the code would be:       

self.Cancel = QPushButton(self,”Cancel”)
self.connect(self.Cancel,SIGNAL(“clicked()”),self.reject)

QDialog (as of version 3.x) doesn’t emit any signal of its own.  That’s about it for QDialog and its main slots and methods. Next is the most common widget of all: the command button, or in the terminology of PyQT, QPushButton. 

{mospagebreak title=QPushButton}

QPushButton provides a command button or, put more simply, a button. Typical buttons are OK, Cancel, Help, and so on. A QPushButton object can be obtained by calling the constructor with at least two parameters: the parent widget and the label to be displayed. For example, to create an object of QPushButton with the label “Test” and with the  no parent widget, the statement would be:

      test = QPushButton(None,”&Test”)

An ampersand in front of the label marks it as an accelerator key. Or in other words, the letter succeeding the ampersand becomes a hotkey. In the above example, “T” has become a hotkey.

QPushButton can also display an icon or a pixmap. The icon has to be passed to the QPushButton as a parameter of the constructor, or as a parameter to the setPixmap() or setIconSet() methods of QPushButton class. To make it more clear, take a look at the following example:

      test.setIconSet(QPixmap(“Test.xpm”))

The setIconSet() method requires an object of QPixmap, which in turn takes the name of the graphics file as a parameter. Using the setIconSet() method the icon can be manipulated.

The next aspect of QPushButton that you need to understand is the events that it can generate, in other words, the signals emitted by QPushButton. QPushButton emits three signals, which are clicked(), pressed(), and released(). Of these, clicked() signal is the most commonly used. The reason for this is that pressed and released together form the click. And most of the time the user expects processing to be done.

The clicked() signal is emitted when the button is activated. Activation means the button is pressed and released. It is also emitted when the accelerator key is pressed. The pressed() signal is emitted when the button is just pressed, while the released() signal is emitted when a pressed button is released.

Though all of these are basic events of button widgets, sometimes, capturing the wrong event/signal can be really problematic. For example, if the accept() slot of QDialog is connected with the pressed signal of QPushButton and also with the clicked(), then the clicked()-accept() connection would over-ride the pressed()-accept() connection. So this must to be kept in mind when connecting signals with slots. 

That brings us to the end of our introduction. In the next section I will put the signals of QPushButton to use in order to demonstrate them in the real world.

{mospagebreak title=PyQT in the Real World}

I mentioned at the beginning that I will be enhancing the application developed in the previous article. The enhancements include a button to change the mode of the display to hexadecimal format, and another button to close the application. 

So here it is. Only the differences from the previous application are is bolded:

class Form1(QDialog):
def __init__(self,parent = None,name = None,modal = 0,fl = 0):
                      QDialog.__init__(self,parent,name,modal,fl)
                      self.lCDNumber1 = QLCDNumber(self,”lCDNumber1″)
   self.lCDNumber1.setGeometry(QRect(110,140,301,30))                     

                     self.slider1 = QSlider(self,”slider1″)
                     self.slider1.setGeometry(QRect(130,220,261,31))
                     self.slider1.setOrientation(QSlider.Horizontal)         

                      self.Close = QPushButton(self,”&Close”)
                       self.Close.setGeometry(QRect(250,120,90,30))                     

                        self.hex = QPushButton(self,”&hex”)
                        self.hex.setGeometry(QRect(20,120,100,30))

 self.connect(self.slider1,SIGNAL(“valueChanged(int)”),
                    self.lCDNumber1.display)

if __name__ == “__main__”:
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL(“lastWindowClosed()”),a,SLOT(“quit()”))
    w = Form1()
    a.setMainWidget(w)
    a.exec_loop()

The close button is defined by the Close QPushButton object. The ampersand before the “C” is to make C the hotkey. The setGeometry can be ignored for the time being. I will be discussing it in the future. Next is the button for changing the mode of the QLCDNumber. The hex QPushButton object is the button for changing the mode.

Next comes the connections to make the buttons into what is required.

class Form1(QDialog):
def __init__(self,parent = None,name = None,modal = 0,fl = 0):
                      QDialog.__init__(self,parent,name,modal,fl)
                      self.lCDNumber1 = QLCDNumber(self,”lCDNumber1″)
   self.lCDNumber1.setGeometry(QRect(110,140,301,30))                     

                     self.slider1 = QSlider(self,”slider1″)
                     self.slider1.setGeometry(QRect(130,220,261,31))
                     self.slider1.setOrientation(QSlider.Horizontal)         

                      self.Close = QPushButton(self,”&Close”)
                      self.Close.setGeometry(QRect(250,120,90,30))                     

                      self.hex = QPushButton(self,”&hex”)
                      self.hex.setGeometry(QRect(20,120,100,30))
 self.connect(self.slider1,SIGNAL(“valueChanged(int)”),  
                     self.lCDNumber1.display)
  self.connect(self.hex,SIGNAL(“clicked()”),
                  self.lCDNumber1.setHexMode)
                       self.connect(self.Close,SIGNAL(“pressed()”),self.close)

if __name__ == “__main__”:
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL(“lastWindowClosed()”),a,SLOT(“quit()”))
    w = Form1()
    a.setMainWidget(w)
    a.exec_loop()

The QLCDNumber has a slot to change the mode to hexadecimal mode. It is setHexMode. Connecting the clicked signal of the hex button to the setHexMode Slot of QLCDNumber does the trick. Next is the closing of the dialog. I had already mentioned that QDialog doesn’t have any slots of its own. But it inherits one from QObject. The slot is close. It is to this slot that the clicked signal of the Close button is connected.

That completes the enhanced application. And this brings us to the end of this discussion. If the application just enhanced is compared with an application having the same functionalities written in any other language, it can be observed that PyQT does much with a small amount of code. That is the beauty of this toolkit. In an upcoming article I will discuss the text boxes along with radio buttons and checkboxes. 

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort