Почему мой keyPressEvent не регистрируется или не работает PyQt5? - PullRequest
1 голос
/ 19 марта 2020

Эта программа для школьного проекта. Я добавляю простой keyPressEvent в мое приложение PyQt5, чтобы закрыть программу. Я считаю, что я добавил правильный код, но keyPressEvent даже не зарегистрирует нажатие клавиши. Я попытался установить фокус с помощью self.setFocusPolicy(Qt.StrongFocus), но это не сработало. Я опустил нерелевантные виджеты в коде

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, 
                                QLabel, QPushButton, QWidget, 
                                QStackedLayout, QVBoxLayout, 
                                QStackedWidget, QLineEdit,
                                QCheckBox, QMessageBox,
                                QGridLayout)
from PyQt5.QtCore import Qt

class UI(QWidget):

    def setupUI(self, Main):

        self.width = 900
        self.height = 500

        self.pages = QStackedLayout()

        self.login = QWidget()
        self.register = QWidget()
        self.home = QWidget()

        self.loginUI()
        self.homeUI()

        self.pages.addWidget(self.login)
        self.pages.addWidget(self.home)

    def loginUI(self):

        self.login_Layout = QGridLayout(self.login)

        self.login.setFixedSize(300, 200)

        self.loginButton = QPushButton("Log In")
        self.login_Layout.addWidget(self.loginButton, 0, 0)

    def homeUI(self):

        self.home_Layout = QGridLayout(self.home)

        self.home.setFixedSize(self.width, self.height)
        self.Button1 = QPushButton("Log Out")

        self.Button2 = QPushButton("HELLO")

        self.home_Layout.addWidget(self.Button1, 0, 0, 1, 1)
        self.home_Layout.addWidget(self.Button2, 0, 1)

class Main(QMainWindow, UI):

    def __init__(self):
        super(Main, self).__init__()

        self.setupUI(self)

        self.loginButton.clicked.connect(self.GoTohomePage)
        self.Button1.clicked.connect(self.GoTologinPage)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            print("closed")

    def GoTohomePage(self):
        self.pages.setCurrentIndex(1)
    def GoTologinPage(self):
        self.pages.setCurrentIndex(0)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    M = Main()
    sys.exit(app.exec())

1 Ответ

0 голосов
/ 19 марта 2020

В вашем коде есть большая концептуальная проблема, и только из-за тонкого "не-ошибки" в Qt ваша программа "кажется" работает (как в "она работает = она показывает") ").

Основная проблема заключается в том, что вы пытаетесь наследовать от QMainWindow _ и _ QWidget, что не имеет особого смысла, поскольку QMainWindow уже наследует QWidget.

На самом деле вы видите не ваше главное окно (экземпляр Main), но все отдельные QWidget, которые вы создали (self.login, et c.).

Это «не ошибка» (вероятно, связанная с этим отчетом ): когда новый виджет добавляется в QStackedLayout, он пытается показать его. Если в макете с накоплением нет виджета в конструкторе и не установлен ни один виджет, по какой-то причине Qt показывает этот виджет, как только приложение exec 'd.

Это не должно делать это да, но вы также не должны создавать макет, не устанавливая его в виджет (так как вы не должны обычно создавать класс с множественным наследованием, совместно использующим одного и того же прямого предка, в данном случае QWidget). Также происходит то, что всякий раз, когда вы вызываете self.pages.setCurrentIndex, макет с накоплением пытается показать новый виджет и скрыть предыдущий. Это нормально для нормальных ситуаций (чаще всего, когда используется QStackedWidget, но у вас неожиданный результат: поскольку для стекового макета не установлен виджет, его виджет вообще не должен отображаться (на самом деле его поведение технически не является техническим) не так, но проблема не в этом).

Решение состоит в том, чтобы реализовать все в классе Main, создать центральный виджет и установить компоновку для этого виджета.

class Main(QMainWindow, UI):

    def __init__(self):
        super(Main, self).__init__()

        self.setupUI(self)

        self.loginButton.clicked.connect(self.GoTohomePage)
        self.Button1.clicked.connect(self.GoTologinPage)

    def setupUI(self, Main):

        self.width = 900
        self.height = 500

        <b>centralWidget = QWidget()
        self.setCentralWidget(centralWidget)

        self.pages = QStackedLayout()
        centralWidget.setLayout(self.pages)</b>
        # the two lines above are the same as the following:
        # self.pages = QStackedLayout(centralWidget)

        self.login = QWidget()
        self.register = QWidget()
        self.home = QWidget()

        self.loginUI()
        self.homeUI()

        self.pages.addWidget(self.login)
        self.pages.addWidget(self.home)

    def loginUI(self):

        self.login_Layout = QGridLayout(self.login)

        self.login.setFixedSize(300, 200)

        self.loginButton = QPushButton("Log In")
        self.login_Layout.addWidget(self.loginButton, 0, 0)

    def homeUI(self):

        self.home_Layout = QGridLayout(self.home)

        self.home.setFixedSize(self.width, self.height)
        self.Button1 = QPushButton("Log Out")

        self.Button2 = QPushButton("HELLO")

        self.home_Layout.addWidget(self.Button1, 0, 0, 1, 1)
        self.home_Layout.addWidget(self.Button2, 0, 1)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            print("closed")

    def GoTohomePage(self):
        self.pages.setCurrentIndex(1)
    def GoTologinPage(self):
        self.pages.setCurrentIndex(0)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    M = Main()
    <b>M.show()</b>
    sys.exit(app.exec())

Как видите, я включил весь код в один класс с некоторыми важными изменениями:

  • Я создал новый виджет, который установлен как центральный виджет , который почти обязателен для любого класса QMainWindow (чтобы узнать больше об этом, прочитайте документацию об этом);
  • составной макет применяется к центральному виджету ;
  • экземпляр окна явно показан (с использованием M.show())

С этими простыми изменениями keyPressEvent теперь правильно перехвачен. A Также я считаю, что я пытался оставить большую часть вашего кода нетронутым, но для того, что я вижу, вы должны вместо этого использовать QStackedWidget, который ведет себя таким же образом, но, как виджет, у него есть лучшие способы управления его содержимым:

    def setupUI(self, Main):

        self.pages = QStackedWidget()
        self.setCentralWidget(self.pages)

        self.width = 900
        self.height = 500

        self.login = QWidget()
        self.register = QWidget()
        self.home = QWidget()

        self.loginUI()
        self.homeUI()

        self.pages.addWidget(self.login)
        self.pages.addWidget(self.home)
        # ...

Наконец, если вы хотите использовать разные размеры окон для каждого «диалогового» окна, вам вообще не следует использовать сложенный объект на основе, поскольку он основывает подсказку о размере на «самом большом» виджете, который он содержит. Если вы этого не хотите, вы можете явно использовать self.setFixedSize(width, height) в окне каждый раз, когда изменяется «страница», но я бы не советовал.

PS: Я полагаю, что вы сделали ошибка множественного наследования при попытке понять, как используется вывод pyuic, или как-то неправильно понять документацию о с помощью Designer ; может быть, чрезмерная ошибка, но честная ;-). Я искренне надеюсь, что никто не говорил вам создавать подобные виджеты ... если это так, позор ему / ей: это полностью неправильно!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...