<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Herrmann</title>
    <description>The latest articles on DEV Community by Michael Herrmann (@m_herrmann).</description>
    <link>https://dev.to/m_herrmann</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F114643%2F35a980eb-e97a-4eba-9441-0a19c6dfcd46.jpeg</url>
      <title>DEV Community: Michael Herrmann</title>
      <link>https://dev.to/m_herrmann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m_herrmann"/>
    <language>en</language>
    <item>
      <title>Python Qt tutorial: Create a simple chat client</title>
      <dc:creator>Michael Herrmann</dc:creator>
      <pubDate>Wed, 14 Nov 2018 11:10:48 +0000</pubDate>
      <link>https://dev.to/m_herrmann/python-qt-tutorial-create-a-simple-chat-client-cgl</link>
      <guid>https://dev.to/m_herrmann/python-qt-tutorial-create-a-simple-chat-client-cgl</guid>
      <description>&lt;p&gt;This Python Qt tutorial shows you how to create a (working!) chat client for Windows, Mac or Linux. We will install Qt for Python, write the client and build an installer for it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Qt from Python
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.qt.io/" rel="noopener noreferrer"&gt;Qt&lt;/a&gt; is a GUI framework. It is developed in C++. But in 2018, the Qt company released &lt;a href="https://www.qt.io/qt-for-python" rel="noopener noreferrer"&gt;Qt for Python&lt;/a&gt;. This gives you the increased productivity of this dynamic language, while retaining most of the speed of C++.&lt;/p&gt;

&lt;p&gt;Before Qt for Python came out, most people used a library called &lt;a href="https://riverbankcomputing.com/software/pyqt/intro" rel="noopener noreferrer"&gt;PyQt&lt;/a&gt;. It is more mature, and very stable. Its drawback is that it requires you to purchase a license for commercial projects. This is unlike Qt for Python, which is licensed under the LGPL and can thus normally be used for free.&lt;/p&gt;

&lt;p&gt;From a code perspective, it does not make much of a difference which of the two bindings you use. Their APIs are almost exactly the same. We use Qt for Python here because it is newer. If you want to use PyQt instead, check out &lt;a href="https://build-system.fman.io/pyqt5-tutorial" rel="noopener noreferrer"&gt;this PyQt5 tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing Qt for Python
&lt;/h1&gt;

&lt;p&gt;Installing Qt in Python 3 is very easy, thanks to the venv and pip modules. Open a terminal and navigate to an empty directory. Assuming Python's installation directory is on your PATH, you can then enter the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m venv virtualenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This creates a virtual environment in the &lt;code&gt;virtualenv&lt;/code&gt; directory. It will store your project's dependencies.&lt;/p&gt;

&lt;p&gt;To activate the virtual environment, use one of the following two commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call virtualenv\scripts\activate.bat  # on Windows
source virtualenv/bin/activate        # On Mac / Linux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can tell that the activation was successful by the &lt;code&gt;(virtualenv)&lt;/code&gt; prefix in your shell:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoi14nzwr27toch3ffui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoi14nzwr27toch3ffui.png" alt="Screenshot of an activate Python 3 virtual environment on Windows" width="477" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the remainder of this tutorial, we will assume that the virtual environment is active.&lt;/p&gt;

&lt;p&gt;To install Qt for Python, enter the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install PySide2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It's called &lt;code&gt;PySide2&lt;/code&gt; for historical reasons: PySide were the first official Python bindings, released in 2009 by then-owner of Qt Nokia. After Nokia sold Qt in 2011, development of PySide stalled. PySide2 was a community effort to maintain it. Finally, in 2016, the Qt company &lt;a href="https://groups.google.com/d/msg/pyside-dev/pqwzngAGLWE/kXUpXBhILAAJ" rel="noopener noreferrer"&gt;committed&lt;/a&gt; to officially supporting this project.&lt;/p&gt;

&lt;h1&gt;
  
  
  A chat client
&lt;/h1&gt;

&lt;p&gt;We will now use Qt for Python to create a (working!) chat client. Here is what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3b39lzpdjaa3vuvu9kgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3b39lzpdjaa3vuvu9kgk.png" alt="Qt sample application" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll build this top to bottom. First, the text area that displays everybody's messages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv6f6ee945am07egufua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv6f6ee945am07egufua.png" alt="QTextEdit screenshot" width="272" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To display it, start &lt;code&gt;python&lt;/code&gt; in your terminal and enter the following commands:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap58qa1axmqazpf6q609.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap58qa1axmqazpf6q609.png" alt="QTextEdit sample code on Windows" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first line tells Python to load PySide:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PySide2.QtWidgets import *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we create a &lt;code&gt;QApplication&lt;/code&gt;. This is required in any Qt application. We pass the empty brackets &lt;code&gt;[]&lt;/code&gt; to indicate that there are no command line parameters:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app = QApplication([])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, we create the text area via the line:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text_area = QTextEdit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We tell Qt to display the text area:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text_area.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This opens a window. To make it respond to user input, we finally need the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.exec_()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now Qt processes key strokes, mouse events etc. until you close the little window that contains the text field.&lt;/p&gt;

&lt;p&gt;If the above worked as in the screenshot then congratulations! You just created a very simple GUI application with Qt for Python.&lt;/p&gt;

&lt;h1&gt;
  
  
  Positioning GUI elements
&lt;/h1&gt;

&lt;p&gt;We now want to add the text field for entering messages below the text area:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8nbwm4c4bs5khm26tz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8nbwm4c4bs5khm26tz.png" alt="Qt sample application: A QLineEdit below a QTextEdit" width="294" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how do we tell Qt to place it below (and not, say, to the right of) the text area? The answer is through a &lt;em&gt;layout&lt;/em&gt;. Layouts tell Qt how to position GUI elements.&lt;/p&gt;

&lt;p&gt;To put the text field below the text area, we use a &lt;code&gt;QVBoxLayout&lt;/code&gt; as follows:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PySide2.QtWidgets import *
app = QApplication([])
layout = QVBoxLayout()
layout.addWidget(QTextEdit())
layout.addWidget(QLineEdit())
window = QWidget()
window.setLayout(layout)
window.show()
app.exec_()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We again import &lt;code&gt;PySide2&lt;/code&gt; and create a &lt;code&gt;QApplication&lt;/code&gt;. We proceed to build the layout: First a text area like the one we had before. Then a text field of type &lt;code&gt;QLineEdit&lt;/code&gt;. Next, we create a window to contain our layout. We end by calling &lt;code&gt;.show()&lt;/code&gt; on it and using &lt;code&gt;app.exec_()&lt;/code&gt; to hand control over to Qt.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interlude: Widgets
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;QWidget&lt;/code&gt;, which we saw above, is the most basic GUI element in Qt. All other controls are specialisations of it: buttons, labels, windows, text fields, etc. Widgets are like HTML elements in that they encapsulate looks and behaviour, and can be nested.&lt;/p&gt;

&lt;p&gt;Here is a screenshot of the most important Qt widgets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7c6jwn6u3j95p2wey0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7c6jwn6u3j95p2wey0m.png" alt="Screenshot of the most common Qt widgets" width="528" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It for instance shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qlabel.html" rel="noopener noreferrer"&gt;QLabel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qcombobox.html" rel="noopener noreferrer"&gt;QComboBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qcheckbox.html" rel="noopener noreferrer"&gt;QCheckBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qpushbutton.html" rel="noopener noreferrer"&gt;QPushButton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qradiobutton.html" rel="noopener noreferrer"&gt;QRadioButton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qtextedit.html" rel="noopener noreferrer"&gt;QTextEdit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qlineedit.html" rel="noopener noreferrer"&gt;QLineEdit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qslider.html" rel="noopener noreferrer"&gt;QSlider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.qt.io/qt-5/qprogressbar.html" rel="noopener noreferrer"&gt;QProgressBar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(The code for the screenshot is available &lt;a href="https://build-system.fman.io/static/public/files/widgets_example_pyside.py" rel="noopener noreferrer"&gt;here&lt;/a&gt; for your reference.)&lt;/p&gt;

&lt;h1&gt;
  
  
  Talking to the server
&lt;/h1&gt;

&lt;p&gt;With the GUI ready, we need to connect it to a server. The easiest way to do this is via the &lt;code&gt;requests&lt;/code&gt; library. You can install it via the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once you have done this, start python again and enter the following commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests
chat_url = 'https://build-system.fman.io/chat'
requests.get(chat_url).text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This should give you the HTML of the last chat messages.&lt;/p&gt;

&lt;p&gt;We can also send a message. Here is an example, but be sure to use your own name and text :-)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requests.post(chat_url, {'name': 'Matt', 'message': 'Nice tutorial'})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you then call &lt;code&gt;requests.get(chat_url).text&lt;/code&gt; again, your message should be at the end of the output.&lt;/p&gt;

&lt;h1&gt;
  
  
  Signals
&lt;/h1&gt;

&lt;p&gt;Our chat client needs to handle certain events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the user presses &lt;code&gt;Enter&lt;/code&gt;, the current message should be sent to the server.&lt;/li&gt;
&lt;li&gt;Once per second, we want to fetch and display new messages from the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qt uses a mechanism called &lt;em&gt;signals&lt;/em&gt; for reacting to events such as user input or timers. Here is an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PySide2.QtWidgets import *
from PySide2.QtCore import QTimer
app = QApplication([])
timer = QTimer()
timer.timeout.connect(lambda: print('hi!'))
timer.start(1000)
app.exec_()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you run this code, the message &lt;code&gt;hi!&lt;/code&gt; appears in your terminal once per second:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49x5jv6guvm7p6g4tg68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49x5jv6guvm7p6g4tg68.png" alt="QTimer example" width="461" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The signal in the above code is &lt;code&gt;timer.timeout&lt;/code&gt;. We used its &lt;code&gt;.connect(...)&lt;/code&gt; method to specify a function that gets called when the signal occurs. In the example, we used the inline function &lt;code&gt;lambda: print('hi!')&lt;/code&gt;. Our other call &lt;code&gt;timer.start(1000)&lt;/code&gt; then ensured that Qt runs this function every 1,000 milliseconds.&lt;/p&gt;

&lt;h1&gt;
  
  
  Putting it all together
&lt;/h1&gt;

&lt;p&gt;We are now in a position to fully implement the chat client. Copy the below code into a file next to your &lt;code&gt;virtualenv&lt;/code&gt; directory, say as &lt;code&gt;main.py&lt;/code&gt;. Be sure to fill in your name at the top, or you won't be able to post messages. Then you can run the chat with the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You'll be able to see what others have written and send messages of your own. Happy chatting! :-)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PySide2.QtCore import *
from PySide2.QtWidgets import *

import requests

name = '' # Enter your name here!
chat_url = 'https://build-system.fman.io/chat'

# GUI:
app = QApplication([])
text_area = QTextEdit()
text_area.setFocusPolicy(Qt.NoFocus)
message = QLineEdit()
layout = QVBoxLayout()
layout.addWidget(text_area)
layout.addWidget(message)
window = QWidget()
window.setLayout(layout)
window.show()

# Event handlers:
def refresh_messages():
    text_area.setHtml(requests.get(chat_url).text)

def send_message():
    requests.post(chat_url, {'name': name, 'message': message.text()})
    message.clear()

# Signals:
message.returnPressed.connect(send_message)
timer = QTimer()
timer.timeout.connect(refresh_messages)
timer.start(1000)

app.exec_()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Running your app on other computers
&lt;/h1&gt;

&lt;p&gt;We can now start our app with the command &lt;code&gt;python main.py&lt;/code&gt;. But how do we run it on somebody else's computer? Especially if they don't have Python installed?&lt;/p&gt;

&lt;p&gt;What we want is a standalone executable that does not require Python (or anything else) to run. The process of creating such a binary is called &lt;em&gt;freezing&lt;/em&gt; in Python.&lt;/p&gt;

&lt;p&gt;Special Python libraries such as PyInstaller let you freeze applications. Unfortunately, they only get you 80% of the way. Very often, you still have to manually add or remove DLLs or shared libraries. And they don't address basic tasks such as accessing data files, creating installers or automatic updates.&lt;/p&gt;

&lt;p&gt;We will therefore use a more modern library called &lt;a href="https://build-system.fman.io" rel="noopener noreferrer"&gt;fbs&lt;/a&gt;. It is based on PyInstaller but adds the missing 20%. You can install it via the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fbs PyInstaller==3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To start a new fbs project, enter:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m fbs startproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This asks you a few questions. You can use &lt;em&gt;Chat&lt;/em&gt; as the application name and your name as the author.&lt;/p&gt;

&lt;p&gt;Once you have done this, please &lt;a href="https://build-system.fman.io/static/public/files/python-qt-tutorial/main.py" rel="noopener noreferrer"&gt;download this file&lt;/a&gt; and copy it over &lt;code&gt;src/main/python/main.py&lt;/code&gt;. Open the file with a text editor and replace name by your name. The following command then starts the Chat as before:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m fbs run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But what's more, you can now create a standalone executable via the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m fbs freeze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This freezes your Python code to the folder target/Chat. You can copy this directory to any other computer with the same OS as yours to run the Chat there. Isn't that awesome?&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating an installer
&lt;/h1&gt;

&lt;p&gt;You can also use fbs to generate an installer. This is done with the command &lt;code&gt;python -m fbs installer&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;(On Windows, this step requires &lt;a href="http://nsis.sourceforge.net/Main_Page" rel="noopener noreferrer"&gt;NSIS&lt;/a&gt; to be on the PATH. On Linux, you need &lt;a href="https://fpm.readthedocs.io/en/latest/installing.html" rel="noopener noreferrer"&gt;fpm&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;If you have an existing application that you wish to convert to fbs, &lt;a href="https://build-system.fman.io/pyqt-exe-creation/" rel="noopener noreferrer"&gt;this article&lt;/a&gt; may help you. It is written for PyQt, but is equally applicable to Qt for Python / PySide. Another good source of information is &lt;a href="https://github.com/mherrmann/fbs-tutorial" rel="noopener noreferrer"&gt;fbs's tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We saw above how Qt for Python can be used to create a simple desktop application. We used basic widgets such as &lt;code&gt;QTextEdit&lt;/code&gt; and &lt;code&gt;QLineEdit&lt;/code&gt;, as well as &lt;code&gt;QVBoxLayout&lt;/code&gt; to arrange them. Qt's signals let us make this GUI dynamic: First by using a timer to fetch the latest messages from the server every 1,000ms. And second by letting us respond to the user pressing the Enter button to submit a message. Finally, we used fbs to easily create a standalone executable and an installer.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on Twitter &lt;a class="mentioned-user" href="https://dev.to/m_herrmann"&gt;@m_herrmann&lt;/a&gt; if you have any questions or comments!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published &lt;a href="https://build-system.fman.io/python-qt-tutorial" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>qt</category>
    </item>
  </channel>
</rss>
