python - 从 QClipboard 复制/粘贴文本会卡住程序

标签 python pyqt qtablewidget pyside2 qclipboard

我有一个 QTableWidget,当单击一行时,它会选择该行中的所有单元格。我正在尝试添加“复制”功能,以便在选择行并将其粘贴到文本编辑器中时可以 ^ctrl-c 。但是,使用我当前的代码,一旦我 ^ctrl-c 一行,我复制的行就会不断被复制。

我在方法“read_clipboard”中实现了一个打印语句,以查看复制的行是否被读取,这就是我发现该行不断被复制的方式,就像在无限循环中一样。

之前关于 PyQt/Qt 和 QClipboard 的堆栈溢出问题对我来说都没有效果。

def __init__(self):
   super(MainWindow, self).__init__()
   self.setupUi(self)
   self.my_selector = self.my_tableWidget.selectionModel()

   # Where I detect the signal to call my "read_clipboard" method
   QtGui.QGuiApplication.clipboard().dataChanged.connect(self.read_clipboard)

   self.show()

def read_clipboard(self):
    selection = self.my_selector.selectedIndexes()
    if selection:
        print(selection)
        QtGui.QGuiApplication.clipboard().clear()
        QtGui.QGuiApplication.clipboard().setText(selection)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()  # Creates MainWindow object
    ret = app.exec_()
    sys.exit(ret)

当我 ^ctrl-c 一行时,程序连续打印“选择”,就好像它处于无限循环中一样,我不知道如何在它只运行一次后停止它,以便我可以复制它一行。

最佳答案

您不应该以这种方式使用 dataChanged 信号,原因有两个:

  • 每次整个系统中剪贴板发生变化时都会调用它;
  • 清除剪贴板显然会更改其内容,从而导致递归调用 read_clipboard 方法;显然,您可以按照@furas的建议暂时断开信号,但第一个问题仍然存在。

此外,您不能将 QItemSelectionModel 用于 setText,因为它需要一个字符串。

更好的解决方案是重写自定义 QTableWidget 类的 keyPressEvent,以在默认实现对其进行操作之前捕获它的“复制”操作:

class MyTableWidget(QtWidgets.QTableWidget):
    def keyPressEvent(self, event):
        if event == QtGui.QKeySequence.Copy:
            # set clipboard only if it's not a key repetition
            if not event.isAutoRepeat():
                QtWidgets.QApplication.clipboard().setText(', '.join(i.data() for i in self.selectedIndexes() if i.data()))
        else:
            super(MyTableWidget, self).keyPressEvent(event)

另一种类似的可能性是在您的表中安装事件过滤器并检查其关键事件:

class MyWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.my_tableWidget.installEventFilter(self)

    def eventFilter(self, source, event):
        if source == self.table and event.type() == QtCore.QEvent.KeyPress and event == QtGui.QKeySequence.Copy:
            if not event.isAutoRepeat():
                QtWidgets.QApplication.clipboard().setText(', '.join(i.data() for i in self.table.selectedIndexes() if i.data()))
            # return True to ensure that the event is not actually propagated
            # to the table widget, nor its parent(s)
            return True
        return super(MainWindow, self).eventFilter(source, event)

关于python - 从 QClipboard 复制/粘贴文本会卡住程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57260037/

相关文章:

python - 仅在 Spyder IDE 中出现内存错误

python - 尝试生成一段时间戳

python - Python 中出现奇怪的语法解析错误?

python - 如何将数据从 QTableWidget 检索到 Dataframe?

python - 使用 Python 进行 Excel 和列表

python - 如何从搜索列表中突出显示 QTableWidget 中的单词

python - 如何获取音频设备和名称

python - pyQt 相当于 asyncore/asynchat

c++ - Qt 5.2 调用 QTableWidget::update 不会导致 QTableWidget::paintEvent

python - 如何从 QTableWidget 项目中获取选定的标题标签?