【问题标题】:PyQt avoid falling in infinite loop when handling an eventPyQt 在处理事件时避免陷入无限循环
【发布时间】:2019-10-01 10:07:47
【问题描述】:

在 PyQt 中,我试图在每次更改时获取剪贴板的内容,执行一些操作以将输出计算为文本并将其再次放入剪贴板。

问题似乎是,当我在“剪贴板内容已更改”事件处理函数中更改剪贴板的内容时,这会触发并一遍又一遍地无限调用该函数。

这是我正在使用的代码:

import sys
from PyQt5.Qt import QApplication, QClipboard
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QPlainTextEdit
from PyQt5.QtCore import QSize

class ExampleWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(440, 240))
        self.setWindowTitle("PyQt5 Clipboard example")

        # Add text field
        self.b = QPlainTextEdit(self)
        self.b.insertPlainText("Use your mouse to copy text to the clipboard.\nText can be copied from any application.\n")
        self.b.move(10,10)
        self.b.resize(400,200)

        # clipboard
        self.cb = QApplication.clipboard()
        self.cb_changed_handler = self.cb.dataChanged.connect(self.clipboardChanged)

    def clipboardChanged(self):
        text = self.cb.text()
        print(text)
        self.b.insertPlainText(text + '\n')
        self.cb.clear(mode=self.cb.Clipboard)
        self.cb.setText("this is a text", mode=self.cb.Clipboard) # this creates an infinite loop!!    

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = ExampleWindow()
    mainWin.show()
    sys.exit( app.exec_() )

我也试过下面的clipboardChanged函数没有成功,python崩溃了:

def clipboardChanged(self):
    text = self.cb.text()
    print(text)
    self.b.insertPlainText(text + '\n')
    # This does not work, python crashes!!
    # let's disable the event listener, do what we should and restore the event
    self.cb.dataChanged().disconnect()
    self.cb.clear(mode=self.cb.Clipboard)
    self.cb.setText("this is a text", mode=self.cb.Clipboard)
    self.cb_changed_handler = self.cb.dataChanged.connect(self.clipboardChanged)

我正在使用 Windows。

执行后

from PyQt5.Qt import PYQT_VERSION_STR
print("PyQt version:", PYQT_VERSION_STR)

我明白了

PyQt version: 5.9.2

【问题讨论】:

    标签: python python-3.x windows pyqt pyqt5


    【解决方案1】:

    解决办法是使用blockSignals()防止在clipboardChanged方法中发出QClipBoarddataChanged信号:

    def clipboardChanged(self):
        text = self.cb.text()
        print(text)
        self.b.insertPlainText(text + '\n')
        self.cb.blockSignals(True)
        self.cb.clear(mode=self.cb.Clipboard)
        self.cb.setText("this is a text", mode=QClipboard.Clipboard)   
        self.cb.blockSignals(False)

    【讨论】:

    • 您的答案似乎是正确的,但它也会导致我的计算机出现无限循环。我应该清除任何信号队列吗?
    • 您只使用您提供的代码吗?相反,如果您的真实代码与您提供的不同,那么您的代码不是 MRE,并且很难为您提供帮助。
    • @aturegano 这很奇怪,也许这是一个错误。你用的是什么版本的 PyQt5
    • @aturegano 尝试更新一下,最新版本是PyQt5 5.13.1
    • @aturegano 我的答案总是使用最新版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多