MuhammadLab
Python programming resource

Complete PyQt guide for professional Python desktop apps.

Learn PyQt as a modern desktop GUI framework for Python. This tutorial teaches QApplication, widgets, layouts, signals and slots, dialogs, tables, menus, styling, and class-based app design with runnable examples.

PyQt6 examplesSignals and slotsProfessional layoutsDesktop app projects

More professional than Tkinter

PyQt is commonly used when students need richer widgets, cleaner layouts, and polished desktop applications.

Event-driven programming

Signals and slots teach how user actions trigger Python functions without writing a linear script.

Project-ready structure

Class-based PyQt apps help students organize larger screens, state, validation, and helper logic.

Core theory

What is PyQt?

PyQt is a Python binding for the Qt application framework. Qt is a mature framework for building desktop applications with windows, menus, dialogs, buttons, tables, text editors, charts, and many other interface components.

The main teaching idea is that PyQt separates the visual interface from the Python logic. Widgets collect input and show output. Python methods validate, calculate, load files, and update the screen.

User action - signal - connected Python method - updated interface

Which GUI path should students use?

Tkinter
Built into Python
Simple teaching apps, quick demos, beginner GUI concepts
PyQt
Installed with pip
Professional desktop apps, complex layouts, polished interfaces
Web app
Runs in browser
Online tools, responsive websites, hosted applications

Architecture

How a PyQt app is organized

PyQt becomes much easier when students understand the moving parts first: application object, widgets, layouts, signals, slots, and classes.

QApplication owns the app

A PyQt program starts by creating a QApplication object. This object manages application settings, the event loop, keyboard and mouse events, styling, and communication with the operating system.

Widgets build the interface

Everything visible is a widget: QLabel, QPushButton, QLineEdit, QTextEdit, QTableWidget, QComboBox, and many more. A window is also a widget.

Layouts make the UI responsive

PyQt layouts such as QVBoxLayout, QHBoxLayout, and QGridLayout calculate widget size and position. Students should prefer layouts over fixed pixel positions.

Signals and slots connect behavior

When the user clicks a button, changes text, or selects an item, PyQt emits a signal. A slot is a Python function connected to that signal.

Stylesheets polish the look

PyQt can use Qt Style Sheets, which feel similar to CSS. This lets students style buttons, inputs, panels, and whole applications.

Class-based design matters

Most serious PyQt apps are organized as classes. The class owns the widgets, event handlers, data, and helper methods for one screen or application.

Learning path

Teach PyQt in this order

This order prevents students from getting lost. They first learn how the app runs, then how to create widgets, then how to connect actions to Python logic.

1

QApplication

The application object that controls the GUI event loop.

2

Widgets

Visual interface objects such as labels, buttons, inputs, and tables.

3

Layouts

Responsive containers that arrange widgets without fixed coordinates.

4

Signals and slots

The event system that connects user actions to Python functions.

5

Windows and dialogs

Main windows, message boxes, file pickers, and secondary screens.

6

Projects

Combine interface design, validation, files, and application state.

Signals and slots

The central PyQt idea

A signal is emitted when something happens. A slot is the function that responds. For example, a button emits clicked, and your Python method handles the click.

button.clicked.connect(my_function)
Event happens - Python responds.

Tutorial lessons

Runnable PyQt examples with theory.

Each lesson explains the concept first, then gives a complete PyQt6 example students can run locally after installing PyQt6.

14 lessons

Lesson 1

Install PyQt and create your first window

Understand the minimum structure of a PyQt application.

Link

Theory

PyQt is not built into Python like Tkinter. Students usually install it with pip, then create a QApplication and at least one visible widget. The event loop starts with app.exec().

Key points

  • Install PyQt6 with pip.
  • QApplication represents the running GUI app.
  • QWidget creates a blank window.
  • show() makes the window visible.
  • app.exec() starts the event loop.

Classroom note

Explain that QApplication is like the engine of the app. QWidget is the visible car body. app.exec() keeps the engine running.

Python code
# Install first:
# pip install PyQt6

import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("My First PyQt App")
window.resize(420, 240)

label = QLabel("My First PyQt App")
label.setAlignment(Qt.AlignmentFlag.AlignCenter)

layout = QVBoxLayout()
layout.addWidget(label)
window.setLayout(layout)

window.show()

sys.exit(app.exec())
Screenshot after execution
Install PyQt and create your first window PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 2

Add a label

Display text inside a PyQt window.

Link

Theory

QLabel is the basic output widget. It can show instructions, headings, status messages, or results. Unlike print(), QLabel appears inside the graphical interface.

Key points

  • QLabel displays text.
  • setText() can update it later.
  • A layout places the label inside the window.
  • Alignment controls where text appears.

Classroom note

This is a good moment to compare terminal output with GUI output: print() writes to the console, QLabel writes to the window.

Python code
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Label Example")
window.resize(420, 220)

label = QLabel("Welcome to PyQt GUI development!")
label.setAlignment(Qt.AlignmentFlag.AlignCenter)

layout = QVBoxLayout()
layout.addWidget(label)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Add a label PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 3

Create a button and connect a click

Run Python code when the user clicks a button.

Link

Theory

PyQt uses signals and slots. clicked is a signal emitted by QPushButton. A Python function connected with clicked.connect() becomes the slot that runs when the signal happens.

Key points

  • QPushButton creates a clickable button.
  • clicked is the button signal.
  • connect() attaches a Python function.
  • Do not call the function with parentheses inside connect.

Classroom note

Use the phrase signal to slot repeatedly. It is the central PyQt idea.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget

def say_hello():
    label.setText("Hello! The button signal reached Python.")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Button Signal Example")

label = QLabel("Waiting for click...")
button = QPushButton("Click Me")
button.clicked.connect(say_hello)

layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(button)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Create a button and connect a click PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 4

Read text input with QLineEdit

Collect single-line user input.

Link

Theory

QLineEdit is PyQt input for one line of text. It is used for names, email addresses, numbers, passwords, search boxes, and short form fields.

Key points

  • text() reads the current value.
  • setPlaceholderText() gives a hint.
  • setEchoMode() can hide passwords.
  • Input arrives as text, even when it looks numeric.

Classroom note

Ask students what happens if the input is empty. That leads naturally into validation.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget

def greet_user():
    name = name_input.text()
    result_label.setText(f"Hello, {name}!")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("QLineEdit Input")

name_input = QLineEdit()
name_input.setPlaceholderText("Enter your name")

button = QPushButton("Greet")
button.clicked.connect(greet_user)

result_label = QLabel("")

layout = QVBoxLayout()
layout.addWidget(name_input)
layout.addWidget(button)
layout.addWidget(result_label)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Read text input with QLineEdit PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 5

Build a login form with QGridLayout

Use rows and columns to create a clean form.

Link

Theory

QGridLayout is ideal for forms because it aligns labels and input fields. Students should learn that professional interfaces are usually layout-driven, not manually positioned pixel by pixel.

Key points

  • QGridLayout arranges widgets in rows and columns.
  • Password fields use EchoMode.Password.
  • The result label gives visual feedback.
  • Validation belongs inside the slot function.

Classroom note

Make clear that this login form is a GUI logic demo, not production authentication.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QGridLayout, QWidget

def login():
    username = username_input.text()
    password = password_input.text()

    if username == "admin" and password == "1234":
        result_label.setText("Login successful!")
    else:
        result_label.setText("Invalid username or password")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("PyQt Login Form")

username_input = QLineEdit()
password_input = QLineEdit()
password_input.setEchoMode(QLineEdit.EchoMode.Password)

login_button = QPushButton("Login")
login_button.clicked.connect(login)
result_label = QLabel("")

layout = QGridLayout()
layout.addWidget(QLabel("Username"), 0, 0)
layout.addWidget(username_input, 0, 1)
layout.addWidget(QLabel("Password"), 1, 0)
layout.addWidget(password_input, 1, 1)
layout.addWidget(login_button, 2, 1)
layout.addWidget(result_label, 3, 0, 1, 2)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Build a login form with QGridLayout PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 6

Understand vertical and horizontal layouts

Arrange widgets without fixed coordinates.

Link

Theory

QVBoxLayout stacks widgets vertically. QHBoxLayout places widgets horizontally. Combining them creates most beginner interfaces: headers, form rows, button bars, and output sections.

Key points

  • QVBoxLayout stacks top to bottom.
  • QHBoxLayout stacks left to right.
  • Nested layouts create complex screens.
  • Layouts respond better to resizing than fixed coordinates.

Classroom note

Have students sketch the screen first. Each row or section usually becomes a layout.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QWidget

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Nested Layouts")

title = QLabel("Student Dashboard")

button_row = QHBoxLayout()
button_row.addWidget(QPushButton("Profile"))
button_row.addWidget(QPushButton("Grades"))
button_row.addWidget(QPushButton("Settings"))

main_layout = QVBoxLayout()
main_layout.addWidget(title)
main_layout.addLayout(button_row)
main_layout.addWidget(QLabel("Select a section above."))

window.setLayout(main_layout)
window.show()
sys.exit(app.exec())
Screenshot after execution
Understand vertical and horizontal layouts PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 7

Use QMessageBox for pop-up messages

Show information, warning, and error dialogs.

Link

Theory

Dialogs are temporary windows used for important feedback. QMessageBox is useful when the user must notice something, such as invalid input or a completed action.

Key points

  • information() shows normal messages.
  • warning() shows caution messages.
  • critical() shows error messages.
  • Dialogs interrupt the flow until the user responds.

Classroom note

Teach students not to overuse pop-ups. Use labels for normal feedback and dialogs for important feedback.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QMessageBox, QPushButton, QVBoxLayout, QWidget

def show_message():
    QMessageBox.information(window, "Saved", "Your work has been saved.")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Message Box")

button = QPushButton("Show Message")
button.clicked.connect(show_message)

layout = QVBoxLayout()
layout.addWidget(button)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Use QMessageBox for pop-up messages PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 8

Open files with QFileDialog

Let users select a file from the computer.

Link

Theory

QFileDialog connects the app to the file system. This is essential for tools that load text files, CSV files, images, PDFs, or project files.

Key points

  • getOpenFileName() opens a file picker.
  • It returns the selected path and filter.
  • An empty path means the user cancelled.
  • File filters guide the user to valid files.

Classroom note

This is the bridge between GUI lessons and practical file-processing projects.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QFileDialog, QLabel, QPushButton, QVBoxLayout, QWidget

def open_file():
    path, _ = QFileDialog.getOpenFileName(
        window,
        "Open Text File",
        "",
        "Text Files (*.txt);;All Files (*)"
    )

    if path:
        result_label.setText(path)

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("File Dialog")

button = QPushButton("Choose File")
button.clicked.connect(open_file)
result_label = QLabel("No file selected.")

layout = QVBoxLayout()
layout.addWidget(button)
layout.addWidget(result_label)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Open files with QFileDialog PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 9

Create a multi-line note editor

Use QTextEdit for paragraphs and longer text.

Link

Theory

QTextEdit is a rich multi-line editor. It can hold notes, logs, reports, feedback, pasted text, and simple documents. It is one of the most useful widgets for student projects.

Key points

  • toPlainText() reads the content.
  • setPlainText() writes content.
  • QTextEdit is better than QLineEdit for long text.
  • It can support rich text if needed.

Classroom note

This example connects GUI programming to text processing, which students already understand from Python basics.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QPushButton, QTextEdit, QVBoxLayout, QWidget

def count_words():
    text = editor.toPlainText()
    words = text.split()
    result_label.setText(f"Words: {len(words)}")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Note Editor")

editor = QTextEdit()
editor.setPlaceholderText("Type or paste notes here...")

button = QPushButton("Count Words")
button.clicked.connect(count_words)
result_label = QLabel("Words: 0")

layout = QVBoxLayout()
layout.addWidget(editor)
layout.addWidget(button)
layout.addWidget(result_label)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Create a multi-line note editor PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 10

Use combo boxes and checkboxes

Collect choices instead of free text.

Link

Theory

Good interfaces reduce typing when the valid choices are known. QComboBox gives a drop-down list. QCheckBox stores an optional yes/no choice.

Key points

  • QComboBox.currentText() reads the selected item.
  • QCheckBox.isChecked() reads true or false.
  • Choice widgets reduce invalid input.
  • They are useful for settings and forms.

Classroom note

Explain that choosing the right input widget is part of interface design.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QCheckBox, QComboBox, QLabel, QPushButton, QVBoxLayout, QWidget

def show_selection():
    language = language_box.currentText()
    notifications = "enabled" if notify_check.isChecked() else "disabled"
    result_label.setText(f"{language} selected, notifications {notifications}.")

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Choices")

language_box = QComboBox()
language_box.addItems(["Python", "JavaScript", "R", "SQL"])

notify_check = QCheckBox("Enable notifications")

button = QPushButton("Submit")
button.clicked.connect(show_selection)
result_label = QLabel("")

layout = QVBoxLayout()
layout.addWidget(language_box)
layout.addWidget(notify_check)
layout.addWidget(button)
layout.addWidget(result_label)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Use combo boxes and checkboxes PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 11

Display data with QTableWidget

Show rows and columns in a desktop app.

Link

Theory

Many real applications need tables: student marks, CSV previews, inventory, contacts, or logs. QTableWidget is an approachable way to display tabular data without building a full model/view system first.

Key points

  • setRowCount() controls rows.
  • setColumnCount() controls columns.
  • setHorizontalHeaderLabels() names columns.
  • QTableWidgetItem stores cell content.

Classroom note

After this, students can build a CSV viewer by combining QFileDialog and QTableWidget.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Student Table")
window.resize(520, 260)

table = QTableWidget()
table.setRowCount(3)
table.setColumnCount(3)
table.setHorizontalHeaderLabels(["Name", "Course", "Score"])

data = [
    ["Aisha", "Python", "91"],
    ["Omar", "Databases", "84"],
    ["Lina", "Cybersecurity", "88"],
]

for row, values in enumerate(data):
    for column, value in enumerate(values):
        table.setItem(row, column, QTableWidgetItem(value))

layout = QVBoxLayout()
layout.addWidget(table)
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Display data with QTableWidget PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 12

Use QMainWindow for real applications

Create a main window with menus, status bars, and a central widget.

Link

Theory

QWidget is enough for simple apps. QMainWindow is better for professional applications because it supports menu bars, toolbars, status bars, dock widgets, and one central content area.

Key points

  • QMainWindow is for full applications.
  • setCentralWidget() sets the main content.
  • menuBar() creates menus.
  • statusBar() displays status messages.

Classroom note

Use QMainWindow when teaching bigger projects, not the first lesson.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QMainWindow

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Main Window App")
        self.resize(520, 320)

        self.setCentralWidget(QLabel("Main content area"))

        file_menu = self.menuBar().addMenu("File")
        file_menu.addAction("Open")
        file_menu.addAction("Exit")

        self.statusBar().showMessage("Ready")

app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Screenshot after execution
Use QMainWindow for real applications PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 13

Style PyQt with Qt Style Sheets

Make the interface look polished.

Link

Theory

Qt Style Sheets are similar to CSS. They help students understand that interface behavior and interface appearance can be controlled separately.

Key points

  • setStyleSheet() applies styling.
  • Selectors can target widget types.
  • Colors, borders, padding, and fonts can be styled.
  • Do not let styling hide poor layout structure.

Classroom note

Students enjoy styling, but remind them that readable spacing and clear labels matter more than decoration.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle("Styled PyQt App")
window.setStyleSheet("""
    QWidget {
        background: #f8fafc;
        font-size: 16px;
    }
    QLabel {
        color: #0f172a;
        font-weight: bold;
    }
    QPushButton {
        background: #0f766e;
        color: white;
        border-radius: 10px;
        padding: 10px 14px;
    }
    QPushButton:hover {
        background: #115e59;
    }
""")

layout = QVBoxLayout()
layout.addWidget(QLabel("Styled PyQt Interface"))
layout.addWidget(QPushButton("Continue"))
window.setLayout(layout)

window.show()
sys.exit(app.exec())
Screenshot after execution
Style PyQt with Qt Style Sheets PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Lesson 14

Build a class-based calculator

Organize widgets and logic inside a Python class.

Link

Theory

Class-based PyQt apps are easier to extend. The window class owns its widgets and methods. self.input_a, self.input_b, and self.result_label can be used by any method inside the class.

Key points

  • Classes organize larger apps.
  • self stores widgets as instance attributes.
  • Methods become event handlers.
  • Validation prevents crashes.

Classroom note

This is the best final beginner example because it combines widgets, layouts, signals, validation, and class design.

Python code
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QGridLayout, QWidget

class Calculator(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt Calculator")

        self.first_input = QLineEdit()
        self.second_input = QLineEdit()
        self.result_label = QLabel("Result:")

        add_button = QPushButton("Add")
        add_button.clicked.connect(self.add_numbers)

        layout = QGridLayout()
        layout.addWidget(QLabel("First number"), 0, 0)
        layout.addWidget(self.first_input, 0, 1)
        layout.addWidget(QLabel("Second number"), 1, 0)
        layout.addWidget(self.second_input, 1, 1)
        layout.addWidget(add_button, 2, 1)
        layout.addWidget(self.result_label, 3, 0, 1, 2)
        self.setLayout(layout)

    def add_numbers(self):
        try:
            first = float(self.first_input.text())
            second = float(self.second_input.text())
            self.result_label.setText(f"Result: {first + second}")
        except ValueError:
            self.result_label.setText("Please enter valid numbers.")

app = QApplication(sys.argv)
window = Calculator()
window.show()
sys.exit(app.exec())
Screenshot after execution
Build a class-based calculator PyQt screenshot

This image was generated by executing the PyQt example and capturing the application window.

Project ideas

Beginner PyQt projects

CSV viewer
QFileDialog, QTableWidget, CSV reading
Student marks calculator
Forms, validation, functions, result labels
Notes app
QTextEdit, save/open file dialogs, status messages
Login screen mockup
QLineEdit, password mode, grid layouts
Unit converter
QComboBox, QLineEdit, calculation functions
Settings panel
QCheckBox, QComboBox, style sheets
Mini dashboard
QMainWindow, menus, status bar, central widgets
To-do list
QListWidget, add/delete buttons, simple state

Final teaching message

PyQt teaches professional GUI architecture.

Tkinter is excellent for first GUI concepts. PyQt is the next step when students need richer widgets, cleaner application structure, stronger layout control, and a more professional desktop-app workflow.