如果由同一应用程序触发,则丢弃QClipboard :: DataChanged()信号
Discard QClipboard::dataChanged() signal if triggered by the same application
我正在应用程序中使用qclipboard,其中可以复制和粘贴大型3D对象。糊状操作可能会阻止GUI一段时间,因为必须去序列化许多数据。
我想在对象被复制并粘贴在同一应用程序窗口上的频繁情况下进行优化。在这种情况下,我不需要系统范围的剪贴板,简单的内部功能可以存储并复制C 对象而无需进行挑选化。
所以这个想法是:
1)当调用"复制"时,内部存储对象的副本,并且对象被序列化并将其放置在系统剪贴板上。设置了标志,以记住下一个糊状操作应直接采用存储的对象,而不是系统剪贴板。
2)当系统剪贴板已通过另一个应用程序修改(可能是同一程序,但另一个过程)时,设置了标志,以知道应从系统剪贴板上进行下一个粘贴操作,并具有供应。p> 3)"粘贴"操作检查标志,然后将内部存储的对象取下,或者从系统剪贴板中估算对象。
问题是1)。每当我更改系统剪贴板时,datachanged()信号就会触发。这是不同步的,在qclipboard :: SetData被调用后很长时间。因此,将blocksignals()设置为setData()的呼叫无济于事。
有什么想法吗?
谢谢!
在文档中我假设QClipboard::ownsClipboard()
如果dataChanged()
是由当前过程本身引起的,则返回true
。
因此,您可以在连接到dataChanged()
和E.G.的插槽中检查一下。忽略该特定的调用。
第一个问题是您不应该在GUI线程中进行审理。您可以同时运行避难所。
固定后,您就可以针对剪贴板内部的情况进行优化。这可以使用标志完成 - 而不会阻止信号。
这是您如何解决这两个问题的草图。首先,我们有一个Data
类,该类容纳数据并且复制价格昂贵 - 因此我们不让它复制:
class Data {
Q_DISABLE_COPY(Data) // presumably expensive to copy
public:
//...
QMimeData* serialize() { return new QMimeData; }
static QSharedPointer<Data> deserialize(QMimeData*);
};
Q_DECLARE_METATYPE(QSharedPointer<Data>)
然后,我们需要一种克隆MIME数据的方法:
QMimeData* clone(const QMimeData *src) {
auto dst = new QMimeData();
for (auto format : src->formats())
dst->setData(format, src->data(format));
return dst;
}
最后,具有由操作触发的on_copy
和on_paste
方法的控制器对象。
跟踪分为两个阶段:首先,副本将内部状态切换为Copied
。然后,当剪贴板指示数据已更改时,状态从Copied
到Ready
。
最后,如果状态为Ready
,则on_paste
将使用内部数据执行糊状。否则,它将同时进行挑选,并在避免完成后执行粘贴。
paste
方法应实现数据的实际粘贴。
class Class : public QObject {
Q_OBJECT
QSharedPointer<Data> m_data;
enum { None, Copied, Ready } m_internalCopy = None;
Q_SIGNAL void reqPaste(const QSharedPointer<Data> &);
void paste(const QSharedPointer<Data> &);
void onDataChanged() {
m_internalCopy = m_internalCopy == Copied ? Ready : None;
}
public:
Q_SLOT void on_copy() {
m_internalCopy = Copied;
QScopedPointer<QMimeData> mimeData(m_data->serialize());
QApplication::clipboard()->setMimeData(mimeData.data());
}
Q_SLOT void on_paste() {
if (m_internalCopy == Ready)
return paste(m_data);
m_internalCopy = None;
auto mimeData = clone(QApplication::clipboard()->mimeData());
QtConcurrent::run([=]{
emit reqPaste(Data::deserialize(mimeData));
delete mimeData;
});
}
Class() {
qRegisterMetaType<QSharedPointer<Data>>();
connect(QApplication::clipboard(), &QClipboard::dataChanged, this,
&Class::onDataChanged);
connect(this, &Class::reqPaste, this, &Class::paste);
}
};
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ 初始化 .data 部分中的变量
- 模式"allocate memory or use existing data"
- boost::asio data owning `ConstBufferSequence`
- Python to C++ Data structure API
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- protobuf C++ SQLite handle blob data
- 错误:字段'dateOfBirth'的类型不完整'Poco::Data::Date'
- 为什么构造函数 Message(const T&data) 与 Message(T&& data) 冲突,当 T = int&时?
- "thread-safe data"与"thread-safe code/functions"的区别
- 如何找到目标文件 *.o 的 ram rom 使用情况(.bss .text .rodata .data)?
- 这在C++ "It does not own the underlying data, and so is cheap to copy or assign"中意味着什么
- 使用 .data() 将字符数组转换为 std::string 不会转换整个数组
- *(int*)&data[18]在这段代码中实际上做了什么?
- 出现这种错误的原因是什么"invalid use of non-static data member "
- 构造中错误:未在此范围中声明"data"
- 我可以在初始化之前使用 std::array 成员变量中的 data() 指针吗?发出警告
- 如何将data[i].int转换为vaible