Cristián

Hello Qt for Python

Published Friday May 4th, 2018
58 Comments on Hello Qt for Python
Posted in Qt for Python

The first Qt for Python technology preview release is almost here, and for this reason we want to give a brief example on how it will open the doors to the Python world.

Let’s build a simple application to show the simplicity of Qt for Python using QWidgets.
Every script will have more or less the same structure:

  1. We create a QApplication
  2. Then we include all the QWidgets and structures we want to use (e.g., a QLabel)
  3. We show the application and start our QApplication

If we put these ideas together, we will have something like this:

# hello_world.py
from PySide2.QtWidgets import QApplication, QLabel

app = QApplication([])
label = QLabel("Hello Qt for Python!")
label.show()
app.exec_()

To execute it, a simple python hello_world.py will do the work.

But that’s not the whole story, the real question is: how to access the methods of a Qt class?
To simplify the process, we kept Qt APIs. For example, if we want to specify the size of a QLabel, in C++ we will have something like:

QLabel *label = new QLabel();
label->setText("Hello World!");
label->resize(800, 600);

The equivalent using Qt for Python will be:

label = QLabel()
label.setText("Hello World!")
label.resize(800, 600)

Now that we know the equivalent from C++ we can a write a more sophisticated application.

import sys
import random
from PySide2.QtCore import Qt
from PySide2.QtWidgets import (QApplication, QWidget,
    QPushButton, QLabel, QVBoxLayout)


class MyWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.hello = ["Hallo welt!", "Ciao mondo!",
            "Hei maailma!", "Hola mundo!", "Hei verden!"]

        self.button = QPushButton("Click me!")
        self.text = QLabel("Hello World")
        self.text.setAlignment(Qt.AlignCenter)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

        self.button.clicked.connect(self.magic)

    def magic(self):
        self.text.setText(random.choice(self.hello))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())

If you are not familiar with Qt development, it is a common practice to extend a certain class and adapt it to our needs. In the previous example, we are using QWidget as a base class, and we included a QLabel and a QPushButton.

The application is really simple:

  1. First, we write a list containing Hello World in many languages.
  2. Then, we initialize a QPushButton and a QLabel with a certain alignment, font and size.
  3. After that, we create a QVBoxLayout to include our objects, and we assign it to our class.
  4. And finally, we connect the clicked() signal of our QPushButton to our method called magic.

As a result, every time we click the button, we will get a Hello World in a random language!

The structure of this simple script will be the base for most of the applications using Qt for Python, and we encourage you to test it as soon as Qt for Python is out!

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Qt for Python

58 comments

stlcours says:

How about the management of memory? Because python has its garbage collector which will work for Qt Widgets?
How about the signal/slots from python to C++?

Will says:

Signals and slots are pretty straightforward:
https://wiki.qt.io/Qt_for_Python_Signals_and_Slots

It’s connected by name, so if you have a custom C++ class derived from QObject that gets exposed to Python, you can connect signals from it at runtime without special Python binding code to make the Python runtime aware of the signal at build time.

Adam V says:

Great you open the doors to the Python world.

Are their currently efforts being made making Qt for Python more native feeling – if not – is this in long-term view?
E.g. context managers for Layouts, decorators for slots, iterators for children etc?
(or at the other hand, Qt Creator?)

Cristián Cristián says:

Yes, we want to include more Python flavor features to Qt for Python in the near future, but at the moment we are focusing on the TP. If in the future you have more feedback, please don’t hesitate to contact us again with your concerns.

Paolo M. says:

Thanks a lot for this great tutorial! 🙂

Cristián Cristián says:

You can check a couple of tutorials here: https://wiki.qt.io/Qt_for_Python_Tutorial
Also, the examples that are inside the project’s repository are quite simple to follow, so you can also check them out!

Jack Stapleton says:

Looks great. Can’t wait!

Detlev Offenbach says:

How does “Qt for Python” compare to PyQt5? Will Qt for Python be available as wheels for different platforms as well?

Cristián Cristián says:

Besides the difference in the licenses of the two projects you mentioned, and that there are two different companies behind them, you can compare them by missing bindings which are available here: https://wiki.qt.io/Qt_for_Python_Missing_Bindings
Since both projects keep the Qt API, most of the time the only difference is the import statement.

Cristián Cristián says:

forgot to mention the wheels situation: we are planning a set of wheels for Linux, macOS and Windows for 64bit and a 32bit version only for windows. Besides this we are supporting python 2.7 and python 3.3+.
We are aiming to have a stable ABI to generate wheels for python 3.x

Alexander says:

Great work, finally some basic examples for PySide!

I really fell in love with PyQt and I can’t wait to try out the new PySide for Qt5.

However, something that bothers me as a Python programmer is that the Qt API is very unpythonic. Things like CamelCasing are just not PEP8 compatible. Moreover, why not expose Qt properties as Python properties? Things like label.setText could be as simple as label.text = ‘foo’.

Moreover, something that is quite annoying when using Python with QML is that one has to write a lot of boilerplate code for properties and signals. It would pretty cool if there would be something like attrs for Qt, qtattrs or so, that get’s rid of all the boilerplate code.

Anyway, I’m pretty happy with Python and Qt at the moment, but with a few tweaks it could easily become the number 1 GUI framework for Python.

sacha says:

I agree !
To be pythonic, the “Q” prefix should have been removed. Something like :

from Qt.Widgets import Application, Label
app = Application([])
label = Label(“Hello Qt for Python!”)
label.show()
app.exec_()

dave cortesi says:

One reason for keeping all the ClassNames and memberNames() the same is that you can then refer to doc.qt.io, as you do with PyQt5. They mess with the API, they have to write and maintain a new doc set.

Cristián Cristián says:

I understand your concern, but we had two options: Keep the Qt API, which allows everyone to easily jump from C++ to Python without much struggle, or rewrite the API in a more pythonic way.
Python is quite permissive on this, you can take a look for example to the logging module: https://docs.python.org/3.6/library/logging.html which also uses camelCase, and it’s accepted even though it breaks PEP8.

A solution (third option) could be to allow both approaches, but this will require a lot of maintenance and verification steps to avoid any wrong behavior, but we are not closing this door.

yes, the QML situation could be improved, and hopefully we can work on that in the near future, but at the moment we are focusing on the TP, and preparing everything to be online.

Alexander says:

Excellent. Please don’t forget the native Qt properties as Python properties feature (this can be done with Python descriptors) – it would make Python for Qt significantly more Pythonic regardless of CamelCasing.

Something I also thought about is an automatic conversion of snake_cased property and signal names to camelCase in QML. So one could write PEP8 style code and it still feels native inside QML.

Anyway, since I’m working with Qt/C++ for more than 7 years now I don’t have a problem with the casing and switching back and forth. I’m just thinking about new users and companies.

Cristián Cristián says:

I agree, those are things that could really improve the experience from a Python point of view, but it’s not straightforward. The whole binding generation process would need to be updated to create a kind of alias that replace camelCase to camel_case, and also exposing the Qt properties as Python properties, would generate a totally new API (e.g., set text to a QLabel using label.setText(“Hello”) and label.text = “Hello”).
At the moment, this will not be included in the near releases, but we are aware of the improvement this could mean to the project.
We will, for sure, consider this for major future changes.

Babilon says:

I think that having two APIs that do exactly the same would be too confusing. If ever, you should provide mory pythonic API as a separate import.

AdamV says:

I actually do not think giving the binding part of PySide python_style naming is a good idea, nor dropping the Q prefix.
This will make the distinction between engine and python-app calls more difficult,
which is very important from a performance and usability standpoint (getter function vs python property).

While I do think (#comment-1203167) more pythonic features would be great, renaming everything from the bindings (which is not that high on the pythonic priorities, see logging module) would be bad.

Adding Python properties (e.g. central_widget = property(setCentralWidget, centralWidget)) to the bindings would be interesting, but would add to the already huge namespace.

mark says:

Needs one screenshot, please.

Alex says:

This are really great news! Thanks for efforts and keep going!

Domas says:

Great news. Pyside2 took a while but it seems to be ready for release. I will be happy to try it out in my GUI experiments.b

asd says:

Can I install it using conda? Inside a virtual environment?
This is the biggest reason no one uses Qt from Python and until it’s addressed posts like these won’t help.

Cristián Cristián says:

You can setup your virtual environment with Anaconda, then install the wheel via pip.
The community has been always in charge of providing the official wheels into different environments, like adapting them to use different package managers, so I hope it will not take long to be available with conda, since even the outdated PySide for Qt4 is there.

Damien says:

Looks like the first link (“https://pyside.org/”) does not work.

Also, no instructions on how to get started. Looks like it’s here: https://wiki.qt.io/Qt_for_Python_GettingStarted

But, it says “3.5 recommended” while only the 3.6 and 2.7 versions are available.

So, I guess the recommended setup is python 3.6 and this pip command:

pip install –index-url=http://download.qt.io/snapshots/ci/pyside/5.9/latest/ pyside2 –trusted-host download.qt.io

Cristián Cristián says:

Thanks for noticing the broken link.
The getting started wiki says “>= 3.5 recommended”, and since it’s not officially out yet, we don’t have all the wheels for all the versions we want to support, including old Python versions, but once it’s out, you can installed via pip for your Python 3.5

Jason says:

I’m so confused. I thought QML was there future?
Why don’t you just focus on that?
Why don’t replace the JS engine with Python if you want python to bad?

Your whole premise is flawed though – python’s resurgence is from machine learning, not apps.

Cristián Cristián says:

Usually companies can focus on more than a couple of products, so there is no problem of having people working in QML and Qt for Python.

jason says:

Riverbank already has quality bindings, and has provided steady support. To do a QML App in Python you now need to know C++, QML, Python (none of which are bad, but you’re starting to make a clusterfuck (technical term) of tech like HTML/CSS/JS. If you had QML that was Python instead of JS, that would be cool, but Python QML apps look awkward at best having 3 separate languages in them.

I’d rather the Qt Trolls focus on providing a QML TreeView (finally) or providing QML as a web runtime like React, which would be far more cool, and broadening Qt ecosystem than extending Qt to Python, which has already been done. PySide is an also-ran, and that’s all it ever will be. PySide was announced, faded, and is announced again. PyQt was steady the entire time. Clearly despite the implication of having enough people, PySide development fell out of favor.

I really think having a web runtime would do far more for Qt than python bindings, which as I’ve already stated, are available elsewhere.

Cristián Cristián says:

Thanks for your advise, I think the more suitable place to discuss all your concerns is our mailing list. Maybe you can share your point of view and have a more active discussion http://lists.qt-project.org/mailman/listinfo/development

Fabrice S says:

As a Python developer, I would prefer to have Python instead of JS in QML. But we can justify that QML uses a simple JS because it is simple, JITable etc.

Python is cool but complex on many aspects. JS is a pragmatic choice that just work. Thus I would prefer to invest time to support ES 2015 than a R&D proof of concept on Python.

Young says:

PyQt does not provide LGPL for opensource license. As far as I know, this was the reason why Nokia released PySide(PySide1) at the very first time. Maybe you don’t care about LGPL/GPL, but somebody cares.

Massimiliano says:

Will you support automatic deployment of Python applications to Android? Perhaps through QtCreator?

Cristián Cristián says:

Not at the moment, but personally I would love to have the option to do it, so we can say it’s a nice-to-have feature that can be consider in the future.

Massimiliano says:

Yes, that would totally be a killer feature for Qt for Python. Looking forward to seeing it implemented!

Dag says:

Exciting news! Will your deployment tools like windeployqt and macdeployqt work for Qt for Python apps, or do you recommend using something like PyInstaller? Would love to see a full example, using QML and QtQuick Controls for the UI, Qt for Python for the backend, and best practice for building the distribution binaries in this scenario.

Cristián Cristián says:

At the moment we are not considering any deployment tool for the TP, so we recommend using pyinstaller. Hopefully we will be able to improve the deployment process in the near future. Stay tuned, maybe soon there will be a QML/QtQuick + Qt for Python example 😉

Michael Herrmann Michael Herrmann says:

I’ve been working on a cross-platform file manager based on PyQt for two years. I open sourced my deployment tool for it: https://build-system.fman.io/ It already has 1,500 stars on GitHub. Once Qt for Python is stable, I’ll be happy to fully add support for it as well!

Oleg Korsak says:

Please show in another tutorial how to get things done with AsyncIO

Will says:

Is Qt Creator going to now support python GUI development directly through Qt Designer instead of externally processing a UI file?

Cristián Cristián says:

There is effort to provide support on QtCreator to develop with Python, but not related to Qt Designer.

Diego says:

I’m new at programming. I’ve always wanted to make a program with a graphical interface, but I’ve always found it complicated.

Reading this tutorial I found very simple and I encouraged to try, but I can not install this library at all. I tried to follow all the explanations of this site and others more, but none helped me.

Could you recommend me some?
I use Python3 + and Linux.

Cristián Cristián says:

At the moment there are a few snapshot wheels that you can try to install, but the official release is planned to be mid June.
Here you can find the command https://wiki.qt.io/Qt_for_Python_GettingStarted#Wheels
but be aware that it’s just for Python 3.6 and Linux 64bits at the moment.

Frispete says:

Usually, you have the choice of using PySide and/or PyQt5, that comes with your linux distro.
Changing your scripts between these two projects is mostly a matter of changing the import statements accordingly.

Vincent says:

Is it possible to make Qt for Python work with Jupyter Notebook?

Cristián Cristián says:

AFAIK no, but that will be on the hands of the Jupyter developers, since the notebooks will need to support QObjects.

Will says:

Will Qt Creator be able to interactively develop GUIs with Qt Designer in python? I feel this is the killer feature present in C++ but missing in Python in the Qt product landscape.

Cristián Cristián says:

There is effort to support Python on Qt Creator besides just syntax highlight, so hopefully we can provide this solution soon, but we don’t have a date yet.

Devan Williams says:

This is great news! Love that you guys are working with Python.
I’m surprised you didn’t call it QtPy though (or qtpy), pronounced “cutie pie”).

Derek says:

.net plans?

Cristián Cristián says:

No, but if you are a C# user, maybe you can check QtSharp: https://gitlab.com/ddobrev/QtSharp

Check https://en.wikipedia.org/wiki/List_of_language_bindings_for_Qt_5 if you are curious, there are many more bindings for other languages, sadly most of them are stalled.

Vlad says:

I think this is so important step forward to wider spreading of Qt framework. So many programmers are afraid of the complexity of C++ but if Qt can be used with Python, this is completely different story. Of course PyQt has been here for years, but with its prohibitive licensing, it is not actually usable. Given the increasing popularity of Python and lack of anything GUI related… Congrats to the Qt team, the future looks bright for them. And for us who love Qt. 🙂

stonebig says:

I’m very happy that at last, there is a chance we get a sustainable Python to Qt interface.

The other advantage of PyQt5 will be immediate availability.

To allow Scientific user-base willing to test the PySide2 watters, it would be nice to help a minimum set of projects to get compatible and stable:
. Pyzo (crash at the close),
. PyQtgraph (some bugs),
. Spyder (the “proof” that PySide2 will have reach PyQt5 parity)

stonebig says:

oups! read me “the other advantage ‘OVER’ PyQt5”

Cristián Cristián says:

A couple of weeks ago we solved a bug that was similar to the situation you mention related to Pyzo, are they using the latest PySide2 module version? (if they are using it)
Regarding the other project you mention, since Qt for Python is an open source project, we are always encouraging people to submit patches, features, etc, etc, and many modules already are working on providing compatibility between PyQt and PySide projects.
I think it is on the community’s hands to provide support to third party applications. I would love to contribute to those projects too, but we need to prioritize the core development of Qt for Python first.

Derek says:

I have a simple question; I understand the need to keep the syntax similar to the C++ usage (hence the CamelCase); but why keep the trailing underscore on the exec() function … that just seems bizarre?

Cristián Cristián says:

Because `exec` is a reserved word in Python https://docs.python.org/3/library/functions.html#exec

alias says:

Hi , by run example get this err. Why ?

from PySide2.QtWidgets import QApplication, QLabel
importError: could not import module ‘PySide2.QtGui’

alias says:

Hi , by run example get this err. Why ?

# hello_world.py
from PySide2.QtWidgets import QApplication, QLabel
app = QApplication([])
label = QLabel(“Hello Qt for Python!”)
label.show()
app.exec_()

err:
from PySide2.QtWidgets import QApplication, QLabel
importError: could not import module ‘PySide2.QtGui’

How can i fix this err.

Commenting closed.

Get started today with Qt Download now