2012-08-31 15 views
7

Naprawdę staram się wymyślić sposób na zrobienie tego. Powiedzieć, że wdrożenie przycisk bardzo prosto w okna widget:Przeciąganie/przenoszenie QPushButton w PyQt

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

mogę przesunąć swój punkt inicjalizacji wokół obszaru widgetu dominującej stosując self.button.move(x,y) i mogę dostać zdarzeń myszy z mousePressEvent(self, e) poprzez e.x() i e.y(), tak, że przycisk przenosi się tam, gdzie klikam, ale po prostu nie mogę połączyć tego wszystkiego w strukturę przeciągania i upuszczania.

Wyjaśnienie: Po przeczytaniu "prawdziwego" znaczenia Przeciągnij/upuść, to nie jest to, czego potrzebuję. Chcę tylko móc przesuwać widżet za pomocą myszy, podobnie jak porusza się magnesy na lodówce.

+1

@Eric ma bardzo dobry punkt w swojej odpowiedzi. Czy mógłbyś wyjaśnić to pytanie, czy chcesz prawdziwych zdarzeń przeciągania i upuszczania ... lub po prostu móc przesuwać przycisk myszką? – jdi

+1

Na podstawie tego, co zamierzasz zrobić - zajrzałbym do QGraphicsView struktura. To, co próbujesz zrobić (wirtualna tablica magnetyczna) byłoby bardzo łatwe do osiągnięcia. –

Odpowiedz

10

Oto przykład z ruchomym przycisku, który nadal podtrzymuje normalny sygnał kliknięcia odpowiednio:

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_() 

W mousePressEvent mogę nagrywać zarówno początkową pozycję początkową i stanowiska, które będą aktualizowane całej ulicy.

W mouseMoveEvent otrzymuję właściwe przesunięcie widżetu od miejsca, w którym zostało kliknięte, gdzie znajduje się rzeczywiste pochodzenie, dzięki czemu ruch jest dokładny.

W mouseReleaseEvent sprawdzam, czy ogólny ruch był większy niż minimalna. Jeśli tak, to był opór i ignorujemy normalne zdarzenie, aby nie dać "klikniętego" sygnału. W przeciwnym razie umożliwiamy zwykłemu programowi obsługi zdarzeń wygenerowanie kliknięcia.

+0

To powinien dać mi wystarczająco dużo, by w międzyczasie się rozgryźć. Dziękuję Ci! – RodericDay

+0

Nie ma za co! Nie zapomnij przyjąć odpowiedzi, jeśli rozwiąże ona Twój problem! – jdi

+0

Byłem niezdecydowany, ponieważ odpowiedź, którą najbardziej lubiłem, to QGraphicsScene, ale to rozwiązanie jest lepszą odpowiedzią na dokładne pytanie, które zadałem. Proszę bardzo! – RodericDay

2

To zależy od tego, co próbujesz zrobić. Jeśli próbujesz wykonać rzeczywistą operację "Przeciągnij & Upuść", robisz to źle. To, co robisz, to po prostu przesuwanie przycisku w jego współrzędnej X, Y w obrębie rodzica. Nigdy nie wywołuje żadnych zdarzeń typu przeciągnij/upuść, są one zupełnie inne.

Należy zapoznać się z dokumentacją drag drop & tutaj:

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

Zamiast przesuwając przycisk wewnątrz mousePressEvent, musisz utworzyć nowy obiekt QDrag i wykonać ją. Możesz sprawić, by wyglądał jak twój przycisk, wykonując migawkę przycisku za pomocą metody QPixmap :: grabWidget i przypisując ją do instancji QDrag za pomocą metody QDrag :: setPixmap.

Zdarzenie, jeśli wszystko, co próbujesz zrobić, to przenieść widżet wokół w przestrzeni nadrzędnej, polecam używanie tego szkieletu i po prostu zaakceptowanie zdarzenia upuszczenia dla przycisku. Wtedy nie uruchamiasz kilku niepotrzebnych przerysowań.

+0

pomysł, w którym mógłbym znaleźć dobry przykład do naśladowania? Nie miałbym nic przeciwko temu, przeciągając kolorowy prostokąt lub coś w tym stylu. Idea instancji "QDrag" wydaje mi się zbyt skomplikowana z jakiegoś powodu, tak jakby jej celem było przeciągnięcie folderu do katalogu lub coś podobnego. – RodericDay

+0

Tak, to jest główny punkt tego.Chyba pytanie brzmi: jaki jest twój cel? –

+0

Moim ostatecznym celem jest możliwość symulacji planszy przez zaimportowanie * .bmps W krótkim czasie chcę móc przenosić obiekty QLabel zawierające Pixmap dookoła, takie jak szachy na planszy. Ale bez logiki i stref automatycznego zrzutu. Tylko obrazy na ekranie. Najlepsza analogia, jaką mogę wymyślić, to magnesy na lodówkę. Chcę wirtualne magnesy na lodówkę. – RodericDay