Robert Johns | 25 Feb, 2025
Fact checked by Jim Markus

How to Build Your A Desktop App with Python & PyQt

If you’ve wanted to create desktop applications with Python, PyQt is one of the most powerful frameworks available. It provides an easy way to build professional-looking applications with user interfaces that are both flexible and feature-rich.

In this tutorial, I’ll walk you through the basics of PyQt by creating a simple app with labels, text fields, and buttons while explaining the key concepts you need to know.

By the end of this guide, you’ll have your first functional PyQt app and a solid understanding of how to expand these skills for more complex projects.

What is PyQt?

PyQt is a set of Python bindings for the Qt framework, one of the most widely used libraries for building cross-platform GUI applications. With PyQt, you can design powerful desktop applications that work on Windows, macOS, and Linux.

Here are the three key concepts of PyQt:

  1. The QApplication Object – This is the core of every PyQt application. It manages the event loop and global application settings.
  2. Widgets – Elements such as labels, buttons, and text fields that allow user interaction.
  3. Event Handling (Signals and Slots) – PyQt’s mechanism for responding to user interactions such as button clicks or text input.

Since PyQt doesn’t come pre-installed with Python, you need to install it first. You can do this by running:

pip install PyQt5

Now, let’s dive in and build our first PyQt application!

Creating a Simple PyQt App

The best way to get started with PyQt is by building a basic application. Let’s go step by step to create a Python project with an output like I've shown below.

Turn Python code into a GUI with PyQt

So, when you're ready, open your Python editor or IDE and then simply follow the steps below to create your first Python desktop app.

Step 1: Importing the Required Modules

Before we write any GUI code, we need to import the necessary PyQt modules:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QMessageBox
  • QApplication manages the overall application.
  • QWidget is the base class for our main application window.
  • QLabel, QLineEdit, and QPushButton are widgets for displaying text, accepting user input, and handling button interactions.
  • QVBoxLayout is a layout manager that arranges widgets vertically.
  • QMessageBox is used for pop-up message dialogs.

Step 2: Creating the Main Application Window

Now, let’s initialize our main window:

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("Basic PyQt App - Procedural")
window.setGeometry(100, 100, 400, 200)
  • QApplication(sys.argv): Creates an instance of our application.
  • QWidget(): Creates the main window.
  • setWindowTitle(): Sets the title of the window.
  • setGeometry(): Defines the window’s size and position on the screen.

Step 3: Applying Styling

Styling in PyQt is done using the setStyleSheet() method, which follows a syntax similar to CSS (Cascading Style Sheets). This allows us to customize the appearance of widgets by specifying properties such as colors, borders, font sizes, and padding.

window.setStyleSheet("""
    QWidget {
        background-color: #f7f9fc;
    }
    QLabel {
        color: #003366;
        font-size: 14px;
        font-weight: bold;
    }
    QLineEdit {
        border: 2px solid #007BFF;
        border-radius: 5px;
        padding: 8px;
        font-size: 14px;
    }
    QPushButton {
        background-color: #007BFF;
        color: white;
        border-radius: 5px;
        padding: 10px;
        font-size: 14px;
        font-weight: bold;
    }
    QPushButton:hover {
        background-color: #0056b3;
    }
""")

Let's break down what we're doing here:

  • Selectors (QWidget, QLabel, etc.) – These define styles for specific PyQt widget types.

  • Properties (background-color, font-size, etc.) – These define how each widget should look.

  • Hover Effects (QPushButton:hover) – This allows styling changes when a user hovers over a button.

This approach provides a flexible way to create professional-looking user interfaces without modifying each widget individually.

Step 4: Adding Widgets to the Application

Let’s add a label, a text input field, and two buttons.

layout = QVBoxLayout()

label = QLabel("Enter your name:", window)
layout.addWidget(label)

text_field = QLineEdit(window)
text_field.setPlaceholderText("Type your name here...")
layout.addWidget(text_field)
  • QLabel(): Displays a message to the user.
  • QLineEdit(): Provides a text input field where users can type.
  • setPlaceholderText(): Gives users a hint on what to enter.

Step 5: Adding Buttons and Event Handling

Let’s add a submit button that displays a greeting and a quit button to close the application.

def submit_action():
    user_input = text_field.text().strip()
    if user_input:
        QMessageBox.information(window, "Input Received", f"Hello, {user_input}!")
    else:
        QMessageBox.warning(window, "No Input", "Please enter your name.")

submit_button = QPushButton("Submit", window)
submit_button.clicked.connect(submit_action)
layout.addWidget(submit_button)

quit_button = QPushButton("Quit", window)
quit_button.clicked.connect(window.close)
layout.addWidget(quit_button)
  • QPushButton(): Creates buttons.
  • clicked.connect(submit_action): Connects the button click to the function that displays the user’s input.
  • QMessageBox.information(): Displays a pop-up with the entered name.
  • QMessageBox.warning(): Shows a warning if no input is provided.

Finally, we set the layout and run the app:

window.setLayout(layout)
window.show()
sys.exit(app.exec())

Then, simply run your Python script to reveal an app window like I've shown below.

Successful creation of a Python GUI with PyQt

Now, let’s refactor this code into an Object-Oriented Programming (OOP) structure for better maintainability.

Refactoring the PyQt App Using OOP

For larger applications, organizing your code using classes is a best practice. If you're new to Python and unfamiliar with OOP, you may want to come back to this later. Otherwise, here's how to refactor our app using a class:

class PyQtApp(QWidget):
    def __init__(self):
        super().__init__()

        # Set up the main window
        self.setWindowTitle("Basic PyQt App")
        self.setGeometry(100, 100, 400, 200)

        # Apply styles
        self.setStyleSheet("""
            QWidget {
                background-color: #f7f9fc;
            }
            QLabel {
                color: #003366;
                font-size: 14px;
                font-weight: bold;
            }
            QLineEdit {
                border: 2px solid #007BFF;
                border-radius: 5px;
                padding: 8px;
                font-size: 14px;
            }
            QPushButton {
                background-color: #007BFF;
                color: white;
                border-radius: 5px;
                padding: 10px;
                font-size: 14px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #0056b3;
            }
        """)

        # Initialize the UI
        self.init_ui()

    def init_ui(self):
        # Create layout
        layout = QVBoxLayout()

        # Label
        self.label = QLabel("Enter your name:", self)
        layout.addWidget(self.label)

        # Text Input Field
        self.text_field = QLineEdit(self)
        self.text_field.setPlaceholderText("Type your name here...")
        layout.addWidget(self.text_field)

        # Submit Button
        self.submit_button = QPushButton("Submit", self)
        self.submit_button.clicked.connect(self.submit_action)
        layout.addWidget(self.submit_button)

        # Quit Button
        self.quit_button = QPushButton("Quit", self)
        self.quit_button.clicked.connect(self.close)
        layout.addWidget(self.quit_button)

        # Set layout
        self.setLayout(layout)

    def submit_action(self):
        user_input = self.text_field.text().strip()
        if user_input:
            QMessageBox.information(self, "Input Received", f"Hello, {user_input}!")
        else:
            QMessageBox.warning(self, "No Input", "Please enter your name.")


# Run the application
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = PyQtApp()
    window.show()
    sys.exit(app.exec())

How the OOP Version Works

  • Class Structure: The application is encapsulated in the PyQtApp class. This makes the code more modular and easier to manage.

  • Initialization (__init__): The __init__ method sets up the application by configuring the main window and calling the init_ui method.

  • Method Organization: Widget creation and event handling are organized into separate methods within the class. For example, init_ui defines the layout, while submit_action handles button clicks.

  • Encapsulation: By grouping UI logic into a class, we improve readability and reusability.

I hope you can see how effective this approach is, but just in case you need more convincing, here are the key advantages of OOP:

  1. Organization: Group related functions and data together.

  2. Reusability: Easily extend the class for more features.

  3. Readability: Cleaner and more modular code.

Wrapping Up

Congratulations! You’ve built your first PyQt app and learned the foundational concepts of GUI programming in Python. With this knowledge, you can create more complex applications like calculators, to-do lists, or even image editors.

Feel free to experiment with the code, add more widgets, or improve the styling. Happy coding!

By Robert Johns

Technical Editor for Hackr.io | 15+ Years in Python, Java, SQL, C++, C#, JavaScript, Ruby, PHP, .NET, MATLAB, HTML & CSS, and more... 10+ Years in Networking, Cloud, APIs, Linux | 5+ Years in Data Science | 2x PhDs in Structural & Blast Engineering

View all post by the author

Subscribe to our Newsletter for Articles, News, & Jobs.

I accept the Terms and Conditions.

Disclosure: Hackr.io is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.

In this article

Learn More

Please login to leave comments