Как вы моделируете пресс QPushButton, используя код - PullRequest
0 голосов
/ 25 февраля 2020

Я хочу, чтобы обработчик для нажатия кнопки имитировал другое нажатие кнопки. Есть ли способ сделать это, используя собственный сигнал / слот? Мой тестовый код (поведение, которое я ищу), когда нажатие на кнопку № 1 должно выполнить обработчик № 1 и отправить нажатие кнопки (сигнал) от кнопки № 2, которая выполняет обработчик № 2 и отправить нажатие кнопки (сигнал) от кнопки # 1 и повторите. Ошибки следуют за двумя вещами, которые я пробовал:

import time
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication


class Example(QMainWindow):

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

        self.initUI()

    def initUI(self):

        self.btn1 = QPushButton("Button 1", self)
        self.btn1.move(30, 50)

        self.btn2 = QPushButton("Button 2", self)
        self.btn2.move(150, 50)

        self.btn1.clicked.connect(self.button1Clicked)
        self.btn2.clicked.connect(self.button2Clicked)

        self.statusBar()

        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Event sender')
        self.show()

    def button1Clicked(self):

        self.statusBar().showMessage('Button #1 was pressed')
        time.sleep(5)
        self.btn2.emit()        # QPushButton' object has no attribute 'emit'
        self.btn2.clicked()     # native Qt signal is not callable

    def button2Clicked(self):

        self.statusBar().showMessage('Button #2 was pressed')
        time.sleep(5)
        self.btn1.emit()
        self.btn1.clicked()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 26 февраля 2020

Вы не должны использовать time.sleep, поскольку он блокирует событие GUI l oop. Если вы хотите испустить щелчковый сигнал через время T, то вы должны вызвать button.clicked.emit() с QTimer:

QTimer.singleShot(T, lambda: button.clicked.emit())

, который можно упростить до:

QTimer.singleShot(T, button.clicked.emit)

В вашем случае :

def button1Clicked(self):
    self.statusBar().showMessage("Button #1 was pressed")
    <b>QTimer.singleShot(5000, self.btn2.clicked.emit)</b>

def button2Clicked(self):
    self.statusBar().showMessage("Button #2 was pressed")
    <b>QTimer.singleShot(5000, self.btn1.clicked.emit)</b>

С другой стороны, рекомендуется излучать сигнал только в пределах класса, к которому относится сигнал, поэтому в случае кнопок вы можете использовать click() способ сделать то же самое:

def button1Clicked(self):
    self.statusBar().showMessage("Button #1 was pressed")
    <b>QTimer.singleShot(5000, self.btn2.click)</b>

def button2Clicked(self):
    self.statusBar().showMessage("Button #2 was pressed")
    <b>QTimer.singleShot(5000, self.btn1.click)</b>

Это приведет к излучению сигнала, но эффект нажатия на кнопку не будет виден, если вы хотите увидеть эффект, то вы должны использовать animateClick () метод:

def button1Clicked(self):
    self.statusBar().showMessage("Button #1 was pressed")
    <b>QTimer.singleShot(5000, self.btn2.animateClick)</b>

def button2Clicked(self):
    self.statusBar().showMessage("Button #2 was pressed")
    <b>QTimer.singleShot(5000, self.btn1.animateClick)</b>

Другой способ - отправка QMouseEvent виджету:

def send_mouse_event(widget, timeout=100):
    lp = widget.rect().center()
    press_event = QMouseEvent(
        QEvent.MouseButtonPress, lp, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier
    )
    QCoreApplication.postEvent(widget, press_event)
    release_event = QMouseEvent(
        QEvent.MouseButtonRelease, lp, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier
    )
    QTimer.singleShot(
        timeout, lambda: QCoreApplication.postEvent(widget, release_event)
    )
def button1Clicked(self):
    self.statusBar().showMessage("Button #1 was pressed")
    QTimer.singleShot(5000, lambda: send_mouse_event(self.btn2))

def button2Clicked(self):
    self.statusBar().showMessage("Button #2 was pressed")
    QTimer.singleShot(5000, lambda: send_mouse_event(self.btn1))

Другое решение - использование QtTest.QTest:

from PyQt5.QtTest import QTest
# ...
class Example(QMainWindow):
    # ...
    def button1Clicked(self):
        self.statusBar().showMessage("Button #1 was pressed")
        QTimer.singleShot(
            5000, lambda: QTest.mouseClick(self.btn2, Qt.LeftButton, delay=100)
        )

    def button2Clicked(self):
        self.statusBar().showMessage("Button #2 was pressed")
        QTimer.singleShot(
            5000, lambda: QTest.mouseClick(self.btn1, Qt.LeftButton, delay=100)
        )
...