Пример создания небольшого GUI хеллоу ворлда используя PySide2 (Qt) на Windows (кроссплатформенно).

Для установки зависимостей и создания virtualenv используется poetry https://poetry.eustace.io/docs/

В зависимостях есть всё нужное для работы скриптов.
Графический редактор ui файлов (Qt Designer) устанавливается отдельно: либо инсталятором С++ Qt отсюда https://www.qt.io/download (кнопка справа про опенсорс), либо тут он доступен без всего лишнего https://build-system.fman.io/qt-designer-download (не пробовал).

Видео всего процесса. 5:49, без звука (в таком формате особо нечего говорить, цели полностью объяснить все основы не было):

Код: https://github.com/AlexP11223/pyside2_example

Вместо генерации Питоновского кода из .ui файлов, их можно сразу загружать https://doc.qt.io/qtforpython/tutorials … -directly, но мне так не особо понравилось. Может не разобрался, а может не допилили еще, Pyside2 недавно начали развивать, до этого PyQt5 был основным. Основные проблемы вроде были в том, что неудобно добавлять обработчики событий (нельзя просто создать метод с @Slot) и непонятно как переопределять методы (например paintEvent). Я находил какие-то решения, но они выглядели как-то сложно и/или добавляли другие проблемы. Ну и так не будет подсказок IDE про элементы виджета (self.ui.myMegaButton).

Вызовы pyside2-uic естественно можно автоматизировать кучей способов типа скриптов, Makefile, средств IDE.

В одном проекте я просто создал скрипт перегенирирующий все файлы и запускал его вручную когда надо:

Код:
import inspect
import os
import re


def read_all_file_text(file_path, encoding='utf-8'):
    with open(file_path, 'r', encoding=encoding) as f:
        return f.read()


def write_all_file_text(file_path, text, encoding='utf-8'):
    with open(file_path, 'w', encoding=encoding) as f:
        return f.write(text)


dir_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
filenames = [f for f in os.listdir(dir_path) if f.endswith('.ui')]

for filename in filenames:
    input_path = os.path.join(dir_path, filename)
    output_path = os.path.join(dir_path, 'ui_' + os.path.splitext(filename)[0] + '.py')
    cmd = f'pyside2-uic "{input_path}" > "{output_path}"'
    print(cmd)
    ret = os.system(cmd)
    if ret != 0:
        print(f'Exit code {ret}')
        continue

    # remove header
    src = read_all_file_text(output_path)
    clean_src = re.sub(r'# Form implementation generated.+(# WARNING! All changes made in this file will be lost!)',
                       r'\g<1>', src, flags=re.S)
    write_all_file_text(output_path, clean_src)

   
Скрипт еще убирает коммент с датой потому что я коммитил их в Гит (конечно наверно лучше добавить их в .gitignore и просто генерировать после git clone и т.д., но в том случае так было удобнее по каким-то причинам).