2016-02-19 6 views
1

Я хочу, чтобы мое приложение прекратило все перетаскивания и падения в dragLeaveEvent, не отпуская кнопку мыши.Окончание QDrag Преждевременно

Проблема заключается в том, что цикл приостанавливает все события, которые могут отменить QDrag в то время как это происходит, даже если в документации говорится:

«В Linux и Mac OS X, в операции перетаскивания может занять некоторое время , но эта функция не блокирует цикл событий. Другие события по-прежнему доставляются в приложение при выполнении операции . В Windows цикл событий Qt блокируется во время операции . Однако QDrag.exec () в Windows приводит к тому, что processEvents() до часто вызывается, чтобы поддерживать графический интерфейс. любые циклы или операции вызывают, когда активна операция перетаскивания, она будет блокировать операцию перетаскивания ». .

Из-за этого я не могу вызывать события, которые могут привести к перетаскиванию.

До сих пор я пробовал, что предлагается here, как видно из кода. Я использую PyQt5, но если решение работает в Qt, оно должно работать в PyQt.

Редактировать: Я немного напуган, чтобы удалить перетаскивание, так как сцена не владеет им. Полагаю, я мог бы его настроить, но, как было опубликовано here, он не должен работать.

Edit2: Добавлен код с моими нерабочими попытками его исправить. Я бы очень хотел решить эту проблему, не создавая собственную структуру перетаскивания. Также обрезанный пост.

import sys 
from PyQt5.QtWidgets import (QMainWindow, QApplication, 
    QGraphicsView, QGraphicsScene, QGraphicsWidget, QGraphicsRectItem) 
from PyQt5.QtCore import (QMimeData, Qt, QByteArray, QCoreApplication, 
    QEvent, QPoint) 
from PyQt5.QtGui import QBrush, QColor, QDrag, QPen, QMouseEvent 


class MainWindow(QMainWindow): 
    def __init__(self): 
     super().__init__() 
     self.scene = CustomScene() 
     self.view = QGraphicsView(self.scene, self) 
     self.setGeometry(100, 100, 600, 600) 
     self.view.setGeometry(0, 0, 500, 500) 
     self.show() 


class CustomScene(QGraphicsScene): 
    def __init__(self): 
     super().__init__() 
     self.customWidgets = [] 
     for i in range(5): 
      newItem = CustomDragWidget() 
      self.addItem(newItem) 
      self.customWidgets.append(newItem) 
      newItem.setGeometry(i * 50, i * 50, 50, 50) 

    def dragLeaveEvent(self, event): 
     # Work your magic here. I've tried the following: 
     # 1) 
     self.customWidgets[0].dropEvent(event) 
     # 2) 
     self.dropEvent(event) 
     # 3) 
     eve = QMouseEvent(QEvent.MouseButtonRelease, QPoint(0, 0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) 
     QCoreApplication.sendEvent(self.views()[0], eve) 
     QCoreApplication.processEvents() 
     # 4) 
     eve = QMouseEvent(QEvent.MouseButtonRelease, QPoint(0, 0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) 
     QCoreApplication.sendEvent(self.customWidgets[0], eve) 
     QCoreApplication.processEvents() 

    def dropEvent(self, QGraphicsSceneDragDropEvent): 
     # a dummy dropevent that tries to stop the drop, but doesnt work 
     QGraphicsSceneDragDropEvent.accept() 

class CustomDragWidget(QGraphicsWidget): 
    def __init__(self,): 
     super().__init__() 
     self.squareItem = QGraphicsRectItem() 
     self.squareItem.setBrush(QBrush(QColor(Qt.blue))) 
     self.squareItem.setPen(QPen(QColor(Qt.black), 2)) 
     self.squareItem.setRect(0, 0, 50, 50) 
     self.squareItem.setParentItem(self) 
     self.setAcceptDrops(True) 

    def mousePressEvent(self, event): 
     mime = QMimeData() 
     itemData = QByteArray() 
     mime.setData('application/x-dnditemdata', itemData) 
     drag = QDrag(self) 
     drag.setMimeData(mime) 
     drag.exec(Qt.MoveAction) 

    def dropEvent(self, event): 
     event.accept() 


if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    win = MainWindow() 
    win.show() 
    sys.exit(app.exec_()) 
+0

Может ли вы предоставить небольшой автономный пример, демонстрирующий эту проблему? – ekhumoro

+0

Конечно! Теперь я редактирую сообщение. – TheSmartWon

+0

Готово к редактированию, а код теперь доступен для копирования. – TheSmartWon

ответ

1

Это немного хака, но это похоже на работу (на Linux, так или иначе):

def dragLeaveEvent(self, event): 
     QCoreApplication.postEvent(self, 
      QKeyEvent(QEvent.KeyPress, Qt.Key_Escape, Qt.NoModifier)) 
+0

Он не работает здесь, в мире Windows 10. ForbiddenCursor по-прежнему показывает :( – TheSmartWon

+0

@ TheSmartWon. Нажатие клавиши реального спасения отменяет перетаскивание на Windows? Или есть другой способ отменить перетаскивание через клавиатуру в Windows? – ekhumoro

+0

Ключ-побег действительно содержит слово в Windows. просто кажется, что событие, где бы оно ни было получено, по-прежнему не раскалывает цепочку на QDrop. Возможно, это проблема только для Windows. – TheSmartWon

Смежные вопросы