11. Работа с графическим пакетом PyQt

Проект PyQt (http://www.riverbankcomputing.com/software/pyqt/intro/) с открытым исходным кодом предоставляется под GPL лицензией и является Python-привязкой для кросс-платформенной библиотеки Qt (http://qt-project.org/). PyQt позволяет разрабатывать пользовательский интерфейс.

Специальная сборка пакета входит в дистрибутив Cerebro.

11.1. Особенности работы с PyQt

Приложение Cerebro также написано с использованием библиотеки Qt, поэтому есть несколько особенностей использования пакета PyQt.

QApplication - в приложении может существовать только один экземпляр класса QApplication, и он уже создается приложением, поэтому вам не нужно его создавать повторно при написании кода с использованием PyQt:

def show_window():
    #app = QtGui.QApplication(sys.argv) do not create!!!

    box = QtGui.QMessageBox()
    box.setText('Hello, World!')
    box.exec_()

Для блокирования основного интерфейса используйте диалоги или их наследников:

def show_dialog():
        
        from PyQt5 import QtWidgets,  QtCore

        class MyDialog(QtWidgets.QDialog): # класс диалога
                ...


        dialog = MyDialog()
        dialog.exec_() # пока не диалог не закроется интерфейс приложения будет заблокирован

Для создания окон без блокирования можно воспользоваться глобальными объектами:

window = None

def show_window():

        global window   

        if window == None: # если обьект окна еще не создан, создаем его
                window = QtWidgets.QLabel()

                window.setText('Показываем окно первый раз')
        else:
                window.setText('Показываем окно повторно')
        
        window.show()

Сигналы и слоты - встроенный интерпритатор Python не может обрабатывать ошибки в слотах PyQt, используйте конструкцию try except для перехвата ошибок с слотах, иначе есть вероятность некорректного завершения работы приложения:

class MyWindow(QtWidgets.QWidget):
    def __init__(self):

        # ...

        self.my_button = QtWidgets.QPushButton()
        self.my_button.connect(self.my_button_click) # signal

        # ...

    def my_button_click(self): # slot
        try:
            # place your code in try catch block
        except Exception as err:
            cerebro.core.print_error('PyQt Error: ' + str(err))

Предупреждение

Hеприятной особенностью использования PyQt является невозможность перезагрузки Python-модулей без перезагрузки приложения. То есть, вам придется отключить кнопку автоматической перезагрузки Python-модулей и не пользоваться кнопкой полной перезагрузки Python интерпритатора, иначе есть вероятность некорректного завершения работы приложения. Связанно это с проблемами переинициализации Python интерпритатора, которые мы не можем обойти. Поэтому для подхвата измений в коде вам будет нужно каждый перезапускать приложение.