Fading Coder

An Old Coder’s Final Dance

Home > Tech > Content

Building PyQt5 GUIs in PyCharm with Qt Designer and pyuic

Tech 2

This guide shows how to design user interfaces with Qt Deisgner, configure PyCharm to use Designer and pyuic, and run the resulting PyQt5 application. It also includes a pure-code alternative without Designer.

1. Install the required tools

  • Install PyCharm (Community or Professional).
  • Install PyQt5 and Qt Designer tools in the interpreter used by the project:
# PyQt5 runtime and widgets
pip install PyQt5

# Qt Designer and related toolchain
pip install pyqt5-tools

Notes:

  • On Windows, pyqt5-tools typically places Designer at:
    • \Lib\site-packages\qt5_applications\Qt\bin\designer.exe
  • On Linux/macOS, pyuic5 is usually on PATH after installing PyQt5. Designer may be available through system packages or pyqt5-tools.

To programmatically locate Designer when using pyqt5-tools on Windows:

python -c "import os, qt5_applications as q; print(os.path.join(os.path.dirname(q.__file__), 'Qt', 'bin', 'designer.exe'))"

2. Configure PyCharm External Tools

Setting up External Tools lets you launch Designer and convert .ui files without leaving the IDE.

2.1 Add Qt Designer

  • File → Settings → Tools → External Tools → + (Add)
    • Name: Qt Designer
    • Program (Windows):
      • $PyInterpreterDirectory$/Lib/site-packages/qt5_applications/Qt/bin/designer.exe
    • Program (Linux/macOS):
      • designer (if available on PATH) or the full path to Designer
    • Working directory: $ProjectFileDir$

2.2 Add pyuic5 (UI compiler)

  • File → Settings → Tools → External Tools → + (Add)
    • Name: pyuic5
    • Program (Windows): $PyInterpreterDirectory$/Scripts/pyuic5.exe
    • Program (Linux/macOS): pyuic5
    • Arguments:
      • -o "$FileNameWithoutExtension$.py" "$FileName$"
    • Working directory: $FileDir$

You can now access both from Tools → Exetrnal Tools in PyCharm.

3. Design a form with Qt Designer

  1. Tools → External Tools → Qt Designer.
  2. Create a "Main Window".
  3. Drop widgets (labels, line edits, push buttons) onto the form.
  4. Set objectName properties you’ll use in code, for example:
    • edtUser, edtPassword, btnLogin, btnQuit
  5. File → Save As… (e.g., login.ui) inside your project.

4. Convert the .ui file to Python

In PyCharm, right‑click login.ui → Tools → External Tools → pyuic5. This generates login.py (or login_ui.py—depending on your file name) containing the Ui_MainWindow class.

5. Run the generated UI in a PyQt5 application

Create a new Python file (e.g., app.py) that imports the generated class and wires up logic.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox

# Assuming pyuic5 created login.py with Ui_MainWindow class
from login import Ui_MainWindow

class LoginWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Wire up signals
        if hasattr(self.ui, 'btnLogin'):
            self.ui.btnLogin.clicked.connect(self.handle_login)
        if hasattr(self.ui, 'btnQuit'):
            self.ui.btnQuit.clicked.connect(self.close)

    def handle_login(self):
        user = getattr(self.ui, 'edtUser', None)
        pwd = getattr(self.ui, 'edtPassword', None)

        username = user.text() if user else ''
        password = pwd.text() if pwd else ''

        if not username:
            QMessageBox.warning(self, 'Login', 'Enter a username.')
            return
        if not password:
            QMessageBox.warning(self, 'Login', 'Enter a password.')
            return

        QMessageBox.information(self, 'Login', f'Welcome, {username}!')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = LoginWindow()
    win.show()
    sys.exit(app.exec_())
  • The generated module name and class depend on the .ui file name. Adjust the import if needed.
  • It’s common to keep the generated file untouched and put all behavior in your own subclass as shown.

6. Building the same UI purely in code (no Designer)

Below is an equivalent login window implemented programmatically with layouts. This approach avoids absolute positioning and is more maintainable.

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
    QApplication, QWidget, QLabel, QLineEdit,
    QPushButton, QMessageBox, QGridLayout, QHBoxLayout, QVBoxLayout
)

class LoginForm(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Login')
        self.resize(360, 180)
        self._build_ui()

    def _build_ui(self):
        lbl_user = QLabel('Username:')
        lbl_pass = QLabel('Password:')

        self.inp_user = QLineEdit()
        self.inp_user.setPlaceholderText('Your username')

        self.inp_pass = QLineEdit()
        self.inp_pass.setPlaceholderText('Your password')
        self.inp_pass.setEchoMode(QLineEdit.Password)

        btn_login = QPushButton('Login')
        btn_exit = QPushButton('Exit')

        btn_login.clicked.connect(self.on_login)
        btn_exit.clicked.connect(self.close)

        grid = QGridLayout()
        grid.addWidget(lbl_user, 0, 0)
        grid.addWidget(self.inp_user, 0, 1)
        grid.addWidget(lbl_pass, 1, 0)
        grid.addWidget(self.inp_pass, 1, 1)

        buttons = QHBoxLayout()
        buttons.addStretch(1)
        buttons.addWidget(btn_login)
        buttons.addWidget(btn_exit)

        root = QVBoxLayout()
        root.addLayout(grid)
        root.addLayout(buttons)

        self.setLayout(root)

    def on_login(self):
        u = self.inp_user.text().strip()
        p = self.inp_pass.text()

        if not u:
            QMessageBox.warning(self, 'Login', 'Username is required.')
            return
        if not p:
            QMessageBox.warning(self, 'Login', 'Password is required.')
            return

        QMessageBox.information(self, 'Login', f'Hello, {u}!')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = LoginForm()
    w.show()
    sys.exit(app.exec_())

7. When to use Designer vs code

  • Designer + pyuic
    • Visual layout and rapid prototyping
    • Keeps UI structure separate from behavior
    • Easy to iterate on widget placement and properties
  • Pure code
    • No generated files; full control via Python
    • Great for dynamic UIs or complex programmatic layouts
    • Slightly more verbose but version-control-friendly for small forms
Tags: pyqt5PyCharm

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.