少なくともQt 5.7までのQt 4では、ドラッグは疑似同期です。 QListWidget::startDrag
が入力され、QDrag::exec()
が呼び出され、QListWidget::startDrag
が返された時点で終了します。したがって、あなたは持っているかもしれません:
void startDrag(Qt::DropActions supportedActions) override {
emit dragStarted();
QListWidget::startDrag(supportedActions); // reenters the event loop
emit dragStopped();
}
ドラッグが実際に行われたかどうかを無視すると(除外することができます)、簡単です。
しかし、この実装は変更される可能性があり、実際には変更する必要があります。イベントループの再入力は混乱です。また、が実際にQDrag
インスタンスで呼び出されたかどうかを知りたいと思います。したがって、制御がイベントループに戻る(戻りまたは再入力による)後、QDrag
インスタンスの存在を確認する必要があります。
QAbstractItemView
の子であるQDrag
を利用することができます。ドラッグが開始されたら、インスタンスを見つけてその存続時間を追跡できます。ライフモニタリングでは、現時点で疑似同期ドラッグの実装に対処するために、イベントループにファンクタをポストする必要があります。ドラッグが完全に非同期になると、以下のコードは動作します。
// https://github.com/KubaO/stackoverflown/tree/master/questions/drag-lifetime-37846521
#include <QtWidgets>
template <typename F>
static void postToThread(F && fun, QObject * obj = qApp) {
QObject src;
QObject::connect(&src, &QObject::destroyed, obj, std::forward<F>(fun),
Qt::QueuedConnection);
}
struct MyListWidget : QListWidget {
Q_SIGNAL void dragStarted();
Q_SIGNAL void dragStopped();
MyListWidget() {
setDragEnabled(true);
addItem("item1");
addItem("item2");
}
void startDrag(Qt::DropActions supportedActions) override {
postToThread([this]{
auto drag = findChild<QDrag*>();
if (drag) {
emit dragStarted();
connect(drag, &QObject::destroyed, this, &MyListWidget::dragStopped);
}
}, this);
QListWidget::startDrag(supportedActions); // reenters the event loop
}
Q_OBJECT
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
QWidget gui;
QVBoxLayout layout(&gui);
MyListWidget list;
QLabel label;
layout.addWidget(&list);
layout.addWidget(&label);
QObject::connect(&list, &MyListWidget::dragStarted, [&]{ label.setText("Drag Active"); });
QObject::connect(&list, &MyListWidget::dragStopped, [&]{ label.clear(); });
gui.show();
return app.exec();
}
#include "main.moc"
この質問は全く別の意図を持っている:私はドラッグを知らさ&ドロップ操作得ることができる方法を知りたい終了した - 有効なターゲットにドロップすることにより、または中止されることによってどちらか(無効領域にまたはを押してドロップ'ESC')もう1つの質問は、ソースウィジェット' mimeData() 'メソッドが呼び出されるたびに、' QMimeData'の新しいインスタンスを作成することによるメモリリークを回避する方法です。 – frans
これは誤解されています。 – AlexanderVX
この質問を重複しないでください、またはタイトルを編集する必要がありますか? – frans