Drag and drop your user interface and tie it all together with a few simple lines of Python.
Why Do this
- Learn how to quickly prototype ideas.
- Develop rich GUI applications with a little Python.
- Delve into the Qt API.
The Qt graphical toolkit has been at the heart of the KDE desktop since its inception, and it’s used by many other cross-platform applications. It’s a great because it does so much of the hard work for you, even at a low level. There’s a Qt class for dealing with string manipulation, for example, or sorting lists. There’s exceptional networking support and transparency, file handling, native XML and image handling. Using Qt to perform all these tasks means you don’t have to re-invent the wheel or import yet another library into your project. But Qt is still best known for it’s high level user-interface design, where you can quickly construct an application from buttons, sliders, forms and images and tie them all together from your code.
One of the best things about developing Qt Python apps is that you don’t need a build system and you don’t need to compile anything. You could even use the Python interpreter if you wanted to – typing commands and seeing the results in real time. To get started, you’ll need Qt 5 installed, alongside the PyQt5 packages. We’re using version 3.4.2 of Python. You should also make sure you’ve got the package that includes the pyuic5 utility, as we’ll be using this to generate Python from the user interface GUI designer for added power. With all of that added to your distribution, it’s time to create some code.
To illustrate how easy it is to write a Python/Qt application, we’ll start off with a very simple and self-contained web browser that loads a specific page. Launch a text editor. The first thing we need to do is import the bits from Qt 5 that we’re going to need – just insert the following lines in the top of a new file:
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView
How do you know which parts you’re going to need before you’ve written the code? You don’t. Normally when programming something like this you add to the ‘from’ section as and when you need to add components. In the above three lines, we’re importing the ability to handle a Qt datatype called QUrl. As you might expect, this is a type that holds a URL, or a location on the internet. The reason this is its own type and not a text string is that Qt is able to test the value to make sure it’s valid, and add functions to the data type so the programmer can do other things with the URL. Exactly what can and can’t be done can be discovered from the Qt API documentation, which although it’s written for C++, is just as relevant to PyQt as all the methods and types are the same. QUrls has functions to return a plain string or a filename, for instance, and it’s the same with everything else you import from Qt. The other two components we import here are for the GUI. QApplication is the main application class for the GUI and its associated function and QWebView, as you might expect, is a Qt widget that uses WebKit to display websites. Finally, import sys adds a selection of system functions – we’ll be using one of these to parse command line arguments. Here’s the final section of code to add:
app = QApplication(sys.argv)
view = QWebView()
With the above short piece of code we create a fully functional web browser, albeit one where you can’t manually enter your own URL. The first line creates the new application and window instance, passing the command line arguments for politeness (they’re not used). After this, we instantiate the web view widget and assign this to view. This is made visible with the show() function, and updated with our own URL in the following line. The use of QUrl like this is known as casting because, we’re using QUrl to force format a text string http://linuxvoice.com into a QUrl type because that’s the only type accepted by the QWebView widget. After this, we run the application.
Save this file with the .py extension and switch to the command line. You can run the code by preceding the name of the file with the word python or python3. You should see a window appear and, as long as you’ve got an internet connection, a few moments later you’ll see our web page. You can now navigate the site just as you would with any other browser.
As Qt uses WebKit, your browser will be able to access almost any modern website.
The biggest problem with our program is that you can’t enter your own URL. We’re going to solve this by adding both a URL input box and a button that tells your application to load the URL. But to make this more interesting, we’re going to design this user-interface with one application, export the design and convert it into Python and then write another small script to add a little functionality. The application we’re going to use to design the GUI is Qt Designer, and you should already have this installed as part of Qt.
Launch Qt Designer and from the startup wizard select a new design using QWidget as a base class. This will open an empty window into which you want to drag the QLineEdit, QPushButton and QWebView widgets. Layout in Qt is a little weird to get your head around, but to create a dynamically scalable version of a layout, place them into rough positions and select the Layout Using Grid option from the Form menu. Layouts are usually a careful balancing act that involves the horizontal and vertical grouping of objects that are again grouped together. We didn’t change the name of any of the widgets created, nor the name of the main Form object. Usually you’d want to make these more descriptive.
Save the project and make a note of where the .ui XML file, is stored – ideally in the same place you’re going to write your next Python script. Go back to the command line and navigate to that location. Now type pyuic5 input.ui > ui_output.py, changing the input and output names to fit yours. We’d recommend keeping the ui_ prefix though, as we’ll refer to this in the code. The pyuic5 command will cleverly turn your user interface file into a Python script – take a look at the contents of the file to see what it’s done. We’re going to create a new script that inherits its properties from this and uses the form you create as the basis for the application.
The first section of our previous code needs a couple of additions. Firstly, QWidget need to be added after QApplication, because we use this in our inherited class. Secondly, we need to import the Python file generated by the user interface:
from PyQt5.QtWidgets import QApplication, QWidget
from ui_output import Ui_Form
The next step is to add a block of code to manage our new class that inherits the user interface:
class MainWindow(QWidget, Ui_Form):
def __init__(self, parent=None):
All we’re doing here is creating a class we’re calling MainWindow that inherits its layout properties from Ui_Form, which was imported from the user interface file we converted earlier. We then define the function that handles its initation. The crucial line is self.pushButton.clicked.connect because this is utilising Qt’s SIGNAL/SLOT mechanism to call a function called pressed when we click the button in the user interface. You can check what SIGNALs and SLOTs are supported by Qt’s functions from the API documentation. Following this, we write the short pressed function connected to the clicked event. This simply sets the QUrl used by the web view to the contents of the lineEdit widget. The web view automatically reloads when it gets this signal.
Finally, The only change to the main bit of code we need is to make our main view use our new class rather than QWebView:
view = MainWindow()
Saving and running this will now give you a very functional web browser and also fill you with ideas of how to use this for rapidly developing Qt applications with Python.