"keyPressEvent" is (sometimes) not called after DragDrop
-
Hello,
i want to drag items from a table, but only when i press ALT.
Without i want only easy selection.My solution:
void Cxy::keyPressEvent(QKeyEvent *event)
{ if(event->key() == Qt::Key_Alt) { gotable->setDragEnabled(true); }
}
void Cxy::keyReleaseEvent(QKeyEvent *event)
{ if(event->key() == Qt::Key_Alt) { gotable->setDragEnabled(false); }
}works, but i often loose "keyReleaseEvent" when i drop the content in another program.
My solution: a retriggered timer till the windows function "GetKeyState" says "no more ALT". Works perfect.But i still have a problem with "keyPressEvent".
This works fine: (A) 1. press ALT, 2. drag 3. drop 4. release ALT
This also: (B) 1. press ALT 2. drag 3. release ALT 4. drop in another program (my program looses focus)
This also: (C) 1. press ALT 2. drag 3. release ALT 4. drop in my own programBUT, in case (C) qt don't call "keyPressEvent" when i press ALT next time.
In this single case i have to press ALT 2 times, only the second time i get a "keyPressEvent"
I even can press other keys, they are detected(!), but when i press ALT after (C) (and even after pressing other keys), the first pressed ALT has no effect.
Seems that only the ALT key is locked once after (C).Any idea?
I could use "GetKeyState" again, but then i have to poll it permanently and waste many cpu-time... -
I guess, when Drag is in progress, Qt does not provide key-events at all.
Seems that key-handling is not the the main strenght from Qt, so i wrote my own key-handler by using
original windows funktion SetWindowsHookEx(WH_KEYBOARD_LL, myLowLevelKeyboardProc, NULL, 0);
Not portable, of course, but it works perfect in all cases without the need to program timers etc.
But i am still open for better soulutions... -
@tomweb
a way cleaner approach instead of toggling the drag-enabled property like you do, would be to override QAbstractItemView::startDrag() and check if the ALT key is pressed - using QApplication::keyboardModifiers().Assuming Cxy is subclassing QAbstractItemView
void Cxy::startDrag(Qt::DropActions supportedActions) { if( !(QApplication::keyboardModifiers() & Qt::AltModifier) ) return; QModelIndexList selectedIndexes = this->getSelectedDraggableIndexes(); // need to be implemented by yourself if (selectedIndexes .count() > 0) { QMimeData *data = this->model()->mimeData(selectedIndexes); if ( !data ) return; QDrag *drag = new QDrag(this); drag->setPixmap(...); drag->setMimeData(data); drag->setHotSpot(...); Qt::DropAction defaultDropAction = Qt::IgnoreAction; if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction())) defaultDropAction = this->defaultDropAction(); else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) defaultDropAction = Qt::CopyAction; drag->exec(supportedActions, defaultDropAction); .... } }
-
Hello @raven-worx ,
thank you very much for this hint.
First you confused me a little bit with "subclassing QAbstractItemView".
I didn't find how to subclass "QAbstractItemView".
In effect, i only had to extended "myQTableWidget"
in Header:
bool useAltKey; // DragDrop with ALT on/off
void startDrag(Qt::DropActions supportedActions);
and in implementation:
void myQTableWidget::startDrag(Qt::DropActions supportedActions)
{ if( useAltKey && (!(QApplication::keyboardModifiers() & Qt::AltModifier)) ) { return; }
QTableWidget::startDrag( supportedActions);
}
Works perfect, and it's even easier to turn on/off this feature. Again thank you. -
@tomweb
indeed...this is easier. :)