9

これを行う方法を見つけるのに本当に苦労しています。ウィジェット ウィンドウに非常に単純にボタンを実装するとします。

self.button = QPushButton("Drag Me", self)

を使用して親ウィジェットの領域の周りにその初期化ポイントを移動でき、 と を介してマウスself.button.move(x,y)イベントを取得できるため、クリックした場所にボタンが移動しますが、これらすべてをドラッグアンドドロップフレームワークにまとめることができないようです。mousePressEvent(self, e)e.x()e.y()

明確化: ドラッグ/ドロップの「真の」意味を読んだ後、それは私が必要としているものではありません。冷蔵庫の磁石を動かすのと同じように、ウィジェットをマウスで動かしたいだけです。

4

2 に答える 2

18

通常のクリック信号を適切にサポートする可動ボタンの例を次に示します。

from PyQt4 import QtCore, QtGui


class DragButton(QtGui.QPushButton):

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == QtCore.Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        super(DragButton, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)
            self.move(newPos)

            self.__mouseMovePos = globalPos

        super(DragButton, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos 
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(DragButton, self).mouseReleaseEvent(event)

def clicked():
    print "click as normal!"

if __name__ == "__main__":
    app = QtGui.QApplication([])
    w = QtGui.QWidget()
    w.resize(800,600)

    button = DragButton("Drag", w)
    button.clicked.connect(clicked)

    w.show()
    app.exec_()

IではmousePressEvent、最初の開始位置と、ドラッグ中に更新される位置の両方を記録します。

ではmouseMoveEvent、移動が正確になるように、クリックされた場所から実際の原点までのウィジェットの適切なオフセットを取得します。

mouseReleaseEvent、全体的な移動が少なくともわずかな量よりも大きかったかどうかを確認します。もしそうなら、それはドラッグであり、「クリックされた」信号を生成しないように通常のイベントを無視します。それ以外の場合は、通常のイベント ハンドラーがクリックを生成できるようにします。

于 2012-08-31T19:19:18.157 に答える
2

それはあなたがしようとしていることに依存します。実際の「ドラッグ アンド ドロップ」を行おうとしている場合、それは間違っています。あなたがしていることは、親内の X、Y 座標空間でボタンを移動するだけです。ドラッグ/ドロップ イベントを実際に呼び出すことはありません。これらはまったく異なります。

ここにあるドラッグ アンド ドロップのドキュメントをよく読んでください。

http://doc.qt.nokia.com/4.7-snapshot/dnd.html
http://qt-project.org/doc/qt-5.0/qdrag.html

mousePressEvent 内でボタンを移動する代わりに、新しい QDrag オブジェクトを作成して実行する必要があります。QPixmap::grabWidget メソッドを使用してボタンのスナップショットを取得し、QDrag::setPixmap メソッドを使用して QDrag インスタンスに割り当てることで、ボタンのように見せることができます。

親スペースでウィジェットを移動するだけの場合は、このフレームワークを使用して、ボタンのドロップ イベントを受け入れることをお勧めします。そうすれば、不要な再描画を大量にトリガーすることはありません。

于 2012-08-31T17:37:08.110 に答える