2016-10-21 2 views
1

Ich habe einen QListWidget in einem QDialog, und ich möchte alle Räder Ereignisse in die Liste umgeleitet werden, so dass ich tat dies:PyQt wheelEvent Umleitung und maximale Rekursionstiefe überschritten

class Form(QDialog): 
    def __init__(self): 
    ... 
     self.myList = QListWidget() 
    ... 
    def wheelEvent(self, scrollEvent): 
     if not scrollEvent.isAccepted(): 
      scrollEvent.accept() 
      self.myList.wheelEvent(scrollEvent) 

Es funktioniert gut, bis die Scroll action versucht, die Liste über ihre Grenzen hinaus zu verschieben. Es scheint, dass in diesen Fällen das QListWidget das scroll-Ereignis nicht akzeptiert (ignoriert) und es (ignoriert) an sein Elternelement, das Formular, sendet, das es wieder an das QListWidget sendet, bis die "maximale Rekursionstiefe überschritten" ist. Fehlermeldung wird ausgelöst.

Wenn das Ereignis akzeptiert wird, bevor es an das QListWidget umgeleitet wird, warum, wenn es zurück zum Qdialog kommt, wird es erneut zum QListWidget umgeleitet? Es scheint, dass das "accept" -Flag des Ereignisses nicht beibehalten wird (oder QListWidget setzt es zurück auf "nicht akzeptiert") und wenn es zurückkommt, wird der QDialog als ein neues Ereignis behandelt. Wie kann ich diese Flags beibehalten oder QListWidget veranlassen, das Ereignis zu akzeptieren, selbst wenn die Liste oben/unten ist?

Ich habe versucht, eine Unterklasse von QListWidget zu definieren und das Ereignis in dieser Unterklasse vor der Umleitung in die Oberklasse zu akzeptieren, aber das gleiche Ergebnis, das Ereignis kommt zurück zum Dialog als nicht akzeptiert.

BEARBEITEN: Hi nochmal!

class Form(QDialog): 
    def __init__(self): 
    ... 
     self.processingWheel = False 
     self.myList = QListWidget() 
    ... 
    def wheelEvent(self, scrollEvent): 
     if not self.processingWheel: 
      self.processingWheel = True 
      self.myList.wheelEvent(scrollEvent) 
      self.processingWheel = False 

Wenn nun der QListWidget nicht das Ereignis nicht verarbeitet (weil die Liste ist oben/unten) das Ereignis erreicht die QDialog wieder, aber diese zweite Zeit ist nicht auf die umgeleitet: Ich habe eine Lösung gefunden QListWidget erneut. Ich nehme an, dass es zum QDialog-Elternteil umgeleitet wird und dort verarbeitet wird (nichts tuend).

Wenn es erlaubt ist, möchte ich die Frage offen lassen, weil ich mich immer noch wundere, warum ich die Flagge selbst verwalten musste und das isAccepted() - Flag nicht wie bei meinem ersten Versuch verwenden konnte . Ich fürchte, ich habe nicht verstanden, was sich hinter der Szene mit Ereignisflags während der Ereignisausbreitung in Qt abspielt.

Antwort

1

Hinweis: Dies gilt für Qt5 - Dinge können in Qt4 anders funktionieren.

Wenn Sie self.myList.wheelEvent(scrollEvent) anrufen, ruft dies intern QListView.wheelEvent(event) auf, wodurch ein neues QWheelEvent erstellt und an das entsprechende Rollbalken-Widget weitergeleitet wird. Wenn die Bildlaufleiste das Ereignis nicht verarbeiten kann, wird das akzeptierte Flag auf false gesetzt. Dies führt dazu, dass das Ereignis sofort erneut in den Dialog propagiert wird, und das Ganze wird wieder herumlaufen.

Sobald Sie das Ereignis an das Listen-Widget senden, können Sie das Akzeptieren-Flag nicht zurücksetzen, bis myList.wheelEvent() zurückgibt. Aber natürlich, wenn die Scrollleiste des Listen-Widgets das Ereignis ignoriert, kann es niemals zurückgeben, da es sofort einen unendlichen Regress eingeht.

Das Aufrufen von event.flag() vor dem Weiterleiten des Ereignisses hat keine Auswirkungen, da die Bildlaufleiste es standardmäßig auf false setzt und es nur auf true setzt, wenn es das Ereignis explizit behandelt.

Angesichts all dies scheint Ihre Lösung mit einem externen Flag die einzig mögliche (es ist etwas analog zu dem blockSignals Mechanismus).

+0

Sind Sie sicher, dass Sie einen "Slot" manuell aufrufen, in diesem Fall wird durch das Aufrufen von QListView.wheelEvent (event) ein neues QWheelEvent generiert? – Pablovx

+0

Ich meine, ich sende das Ereignis als Parameter, es scheint mir nicht logisch, dass es ein neues erzeugt. – Pablovx

+0

Entschuldigung, gerade entdeckt Newline wird nicht in den Kommentaren akzeptiert. ;) Die Tatsache, dass die Bildlaufleiste das Ereignisflag jedoch standardmäßig auf false setzt, erklärt die Situation, auch wenn es immer dasselbe Ereignis ist und kein neues erstellt wird. Danke für Ihre Hilfe! – Pablovx

Verwandte Themen