QtTimer beim Abfangen eines Events

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hi Community,

ich steh gerade vor einem Rätsel. Ich möchte events aus einer Liste abfangen, überlade die Methode die dies tut und erhalte komische Fehlermeldungen, die für mich keinen Sinn ergeben :P

Code: Alles auswählen

<PyQt4.QtCore.QTimerEvent object at 0x0330DF60>
TypeError: invalid result type from OwnList.event()
und das ziemlich oft, sodass mein Programm unbedienbar wird.

Hier der Code:

Code: Alles auswählen

from PyQt4 import QtGui

import sys

class OwnList(QtGui.QListWidget):
    def __init__(self, parent=None):        
         QtGui.QListWidget.__init__(self, parent)   
    
    def event(self, e):
        print e
        
        
class MainWindow(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        secondvbox = QtGui.QVBoxLayout()        
        self.setLayout(secondvbox)
        secondvbox.addWidget(OwnList())
        
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
Kann mich jemand auf den wohl offensichtlichen Fehler hinweisen?

Natürlich könnte man das einfach so machen:

Code: Alles auswählen

self.connect(bla, QtCore.SIGNAL('itemSelectionChanged()'), self.test)
Aber in anderen Tutorials und von Java kenn ich es eben wie oben:
http://www.zetcode.com/tutorials/pyqt4/ ... ndsignals/

Grüße,
anogayales
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Schau Dir mal die Fehlermeldung an und die Dokumentation zu der Funktion (http://doc.qt.nokia.com/4.6/qwidget.html#event). PyQt erwartet hier einen Rückgabewert vom Typ bool, Du gibst aber None zurück (wird implizit von Python zurückgegeben).

Auch solltest Du Dir vielleicht nochmal die Doku zum Eventhandling in Qt durchlesen. Das ist nämlich sehr mächtig. So kannst Du z.B. höher abstrahierte Handler nutzen oder Events gezielt filtern und umlenken. In der Regel ist es nicht notwendig, auf eine lowlevel-Funktion wie event() zurückzugreifen.

Und wenn es nur darum geht, dass itemSelectionChanged() mitgeteilt zubekommen, ist Dein letzter Vorschlag der "qtonischste", wobei es hier inzwischen eine pythonischere Syntax gibt.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Vielen Dank!

Ich hab mir mal kurz das "new-style" signal passing angeguckt:

Code: Alles auswählen

self.activated[str].connect(self.handle_string)
Und bin zu keinem Ergebnis in meinem Minimalbeispiel gekommen:

Code: Alles auswählen

self.bla.connect(self.bla.itemSelectionChanged)
Das kann's ja irgendwie nicht sein.

Grüße,
anogayales
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

anogayales hat geschrieben: Und bin zu keinem Ergebnis in meinem Minimalbeispiel gekommen:

Code: Alles auswählen

self.bla.connect(self.bla.itemSelectionChanged)
Das kann's ja irgendwie nicht sein.
Richtig! Du vermischst auch Signals und Slots!

Code: Alles auswählen

self.bla.itemSelectionChanged.connect(self.test)
Zumindest müßte es so lauten nach Deinem obigen Beispiel!)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Vielen Dank!

Funktioniert wunderbar. Ja, ihr habt recht, das mit den Signalen und Slots werden ich mir wohl angucken müssen!


Diese Frage ist ein wenig OT:
Ich möchte eine maximale Breite eines Layouts festlegen. Möchte aber deswegen keine eigene Klasse implementieren:

Code: Alles auswählen

class OwnVLayout(QtGui.QVBoxLayout):
    def __init__(self, parent=None):        
        QtGui.QVBoxLayout.__init__(self, parent)
        
    def maximumSize(self):
        return QtCore.QSize(50,50)
Ich habe keine weg gefunden, wie ich das einer Normalen QtGui.QVBoxLayout Instatz übergeben kann.
Irgendwelche Ideen?

Grüße,
anogayales
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Neue Frage -> neuer Thread. So findet das ja niemand externes, um entweder zu antworten, oder wenn er das Problem sucht.

Guckst Du hier:
http://doc.qt.nokia.com/4.6/qvboxlayout-members.html

Und dort vermutlich setSizeConstraint().

Was ich mich jedoch frage: Wozu das ganze? Überlass es doch dem LayoutManager und dem User, wie er das gerne haben möchte.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Massive OT:

Ich möchte eben sowas erzielen:

Code: Alles auswählen

-------------
| |           |
| |           |
| |           |
| |           |
-------------

Sprich, der linke Teil soll kleiner sein als der Rechte, demnach sag ich dem linken BoxLayout: "Werde max. x groß"

Klappt auch wunderbar, will halt diese unnütze klasse weg, da es ja anscheinend auch einfacher geht.

Der von dir genannte Teil habe ich mir schon angeschaut, habe aber keine Möglichkeit gefunden, dem auch wirklich Parameter zu übergeben. Kann dem nur ein Enum übergeben.

Ist mein Ansatz vielleicht auch total falsch, und man benutzt für sowas ein anderes Layout. Gibt es vielleicht auch eins, bei dem der Benutzt selbst bestimmen kann wie groß er den linken Teil haben will?

Grüße,
anogayales
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Poste das doch mal als Mockup-Screenshot mit dem QtDesigner! (Also ohne Layout-Zuweisung und zieh das alles per Hand so hin, wie es sein soll).

Ich vermute das kann man auch anders lösen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Weil das hier ein wenig durcheinander geworfen wird:
signal/slot != event (auf API-Ebene)

In Qt existieren mit dem Signal/Slot-Mechanismus und dem Eventsystem 2 Benachrichtigungsysteme auf API-Ebene. Theoretisch würde man mit Verrenkungen auch mit einem der beiden auskommen. Bedenkt man allerdings die Herkunft Qts von C++ und das Fehlen von Objektbenachrichtigungen (auf diesen Teil der OOP-Spezifikation von Smalltalk reagieren C++-Leute allergisch, wohl aus Neid ;) ) so ist der Signal-Slot-Mechanismus ein möglicher Weg, wenn vielleicht auch unelegant umgesetzt (Die Qt-Leute wurden ziemlich heftig gescholten für die Makroverrenkungen des MOC-Aufsatzes.) Auf API-Ebene ist das ganze dann schön einfach gehalten, wie überhaupt Qt durch eine simple und trotzdem mächtige API in C++ glänzt (Beispiel: threading unter C++).

Wann brauche ich nun Signal/Slots und wann Eventhandling?
Das ist zum einen eine Frage des Gustos (wie gesagt lassen sich beide mit Verrenkungen für quasi alles nutzen), der Vorgabe der Qt-API (bestimmte Ereignisse werden von Qt schon als Signal oder Event bereitgestellt) also auch des Einsatzzweckes. Generell würde ich nicht gegen die API programmieren, d.h. Ereignisse, die als Signal vorliegen, würde ich so weiternutzen etc. Zum Einsatzzweck liesse sich sagen, dass ein Event eher als "Rundmail" (besser Kettenmail) zu verstehen ist, also etwas, was prinzipiell alle Objekte angehen könnte während ein Signal dedizierte Empfänger hat. Ein Event durchläuft hierbei die Objekthierarchie und kann an entsprechender Stelle abgefangen, umgeleitet, ignoriert oder in irgendeiner Weise abgearbeitet werden. Wichtig hierbei ist, dass man die weitere Auslieferung des Events in der Hierarchie beeinflussen kann. (Das geht für Signale nicht in der Form, hier stehen die Empfänger gleichwertig nebeneinander.) Beispiele für solche Events sind Tasten/Mouse-Events oder Darstellungsbelange wie "Neuzeichnen" oder "Größenänderung".
In der Regel braucht man als API-Benutzer nur den Signal-Ansatz für Objekt-zu-Objekt-Benachrichtigungen und den Eventweg zum Behandeln von bestimmten von Qt bereitgestellten Events, die man als Eventhandler umsetzt. Das Erstellen eigener Events wird erst dann interessant, wenn man ein eigenes Toolkit mit Qt bauen möchte und auf die Routing-Funktion des Eventsystems angewiesen ist.
Zuletzt geändert von jerch am Dienstag 18. Mai 2010, 11:23, insgesamt 1-mal geändert.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Vielen Dank für diese informative Klarstellung!

Wird mir sicherlich bei der Erabeitung von Qt weiter helfen! :D
lunar

@jerch: Signale und Slots sind kein Aufsatz auf das Event-System, sondern ein unabhängiger Callback-Mechanismus. Signale werden nicht durch Ereignisse dargestellt, die Ereignisschleife ist nie mit der Abarbeitung von Signalen befasst.

Im Allgemeinen nimmt man immer Signale und Slots. Das Ereignissystem ist nur dann wichtig, wenn man Ereignisse des Fenstersystems verarbeiten möchte.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

lunar hat geschrieben:@jerch: Signale und Slots sind kein Aufsatz auf das Event-System, sondern ein unabhängiger Callback-Mechanismus. Signale werden nicht durch Ereignisse dargestellt, die Ereignisschleife ist nie mit der Abarbeitung von Signalen befasst.
Ich war der Meinung, dass nicht die Abarbeitung der Signale sondern die Callback-Registrierung über Events erfolgt. Ist aber nicht so, es ist komplett losgelöst vom Eventsystem. Danke für den Hinweis. (Ich hab es mal geändert, um nichts Falsches stehen zu lassen.)
lunar hat geschrieben:Das Ereignissystem ist nur dann wichtig, wenn man Ereignisse des Fenstersystems verarbeiten möchte.
Das gilt halt nur für den Standardfall der GUI-Programmierung. Qt will durchaus mehr sein als ein GUI-Toolkit, nicht umsonst befindet sich das Eventsystem in QtCore. So nutzt z.B. die Statemachine auch das Eventsystem und ist losgelöst vom Fenstersystem.
lunar

jerch hat geschrieben:
lunar hat geschrieben:Das Ereignissystem ist nur dann wichtig, wenn man Ereignisse des Fenstersystems verarbeiten möchte.
Das gilt halt nur für den Standardfall der GUI-Programmierung. Qt will durchaus mehr sein als ein GUI-Toolkit, nicht umsonst befindet sich das Eventsystem in QtCore. So nutzt z.B. die Statemachine auch das Eventsystem und ist losgelöst vom Fenstersystem.
Ok, stimmt, ich habe Unsinn erzählt. Danke für die Korrektur.
Antworten