У меня есть приложение PyQt5, которое показывает небольшой список. Это позволяет пользователю копировать элементы списка. Когда пользователь копирует элемент списка, он использует отложенную визуализацию, чтобы поместить ссылку на элемент в буфер обмена. Когда элемент вставляется из буфера обмена, он пытается переключить выделение и автоматически помещает следующий элемент в буфер обмена.
Отложенный рендеринг работает в первый раз. Однако, когда я пытаюсь очистить или повторно использовать буфер обмена, я получаю внутреннюю ошибку Qt, которая печатает сообщение, но не распространяется на Python. Это происходит в Windows 10. Пока я ищу кроссплатформенное решение (следовательно, Qt), в настоящее время меня интересует только решение этого в Windows.
. Вот краткий обзор того, что Приложение выглядит так:
Когда я нажимаю Ctrl + C, выбранный элемент копируется правильно. Затем я нажимаю Ctrl + V в окне блокнота. Выделенный текст вставляется просто отлично. Затем строки QApplication.clipboard().clear()
и QApplication.clipboard().setMimeData(data)
в self.copy
обе «молча» терпят неудачу со следующими распечатками:
OleSetClipboard: Failed to set mime data (NULL) on clipboard: COM error 0xffffffff800401f0 CO_E_NOTINITIALIZED (Unknown error 0x0800401f0) (The parameter is incorrect.)
OleSetClipboard: Failed to set mime data (text/plain) on clipboard: COM error 0xffffffff800401f0 CO_E_NOTINITIALIZED (Unknown error 0x0800401f0) (The parameter is incorrect.)
Я считаю, что это как-то связано с временами жизни объектов, которые Qt создается под капотом для поддержки интерфейса PyQt, но я не знаю, как это исправить.
Код ниже. Я реализовал пользовательский класс QMimeData
, который может обрабатывать только текст, и вызывает обратный вызов в ответ на retreiveData
. Я поставил обратный вызов на Timer
, чтобы объект мог быть возвращен и вставлен, прежде чем мы переназначим буфер обмена. Похоже, что это не имеет значения: даже если я обновлю выделение, вставка произойдет правильно, и станет немного яснее, почему я не могу получить доступ к буферу обмена для другой копии.
from PyQt5.QtCore import Qt, QMimeData, QStringListModel, QVariant
from PyQt5.QtGui import QClipboard
from PyQt5.QtWidgets import QAbstractItemView, QApplication, QListView
from threading import Timer
class MyMimeData(QMimeData):
FORMATS = {'text/plain'}
def __init__(self, item, hook=None):
super().__init__()
self.item = item
self.hook = hook
def hasFormat(self, fmt):
return fmt in self.FORMATS
def formats(self):
return list(self.FORMATS)
def retrieveData(self, mime, type):
if self.hasFormat(mime):
if self.hook:
self.hook()
return QVariant(self.item)
return QVariant()
class MyListView(QListView):
def keyPressEvent(self, event):
if event.key() == Qt.Key_C and event.modifiers() & Qt.ControlModifier:
self.copy()
else:
super().keyPressEvent(event)
def toggleRow(self):
current = self.selectedIndexes()[0]
self.setCurrentIndex(self.model().index((1 - current.row()) % 2, current.column()))
Timer(0.5, self.copy).start()
def copy(self):
item = self.selectedIndexes()[0].data()
data = MyMimeData(item, self.toggleRow)
# These are the lines that fail on the second round
QApplication.clipboard().clear()
QApplication.clipboard().setMimeData(data)
# Boilerplate to run the app
app = QApplication([])
model = QStringListModel(["First", "Second"])
view = MyListView()
view.setSelectionMode(QAbstractItemView.SingleSelection)
view.setModel(model)
view.show()
app.exec_()
I Я пытался увеличить продолжительность таймера, но это ничего не меняет (кроме задержки сообщения об ошибке, конечно). Это неудивительно, так как я ожидаю, что есть некоторые проблемы с областями видимости, которые я не знаю.
Я также пытался использовать один экземпляр MyMimeData
и просто обновлять содержимое, которое он получает на основе в текущем ряду. В этом случае снова и снова вставляется только первая строка, поскольку очевидно, что буфер обмена кэширует значение для определенного формата после его извлечения.
Характеристики платформы:
- ОС: Windows 10
- Версия Conda: conda 4.8.3
- Python Версия: Python 3.7.6
PyQt5.QtCore.QT_VERSION_STR
: 5.12.5 PyQt5.Qt.PYQT_VERSION_STR
: 5.12.3
Вдохновением для этого является моя попытка ответить Обнаружение пасты в python