PyQt - Ereignisprogrammierung mit QEvent

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
lunar

xWolf hat geschrieben:Da ich meine Dialoge nicht per Schreiberei erstelle, sondern mit dem Qt-Designer musste ich immer noch QtGui. voranstellen.
Huch? Editierst du etwa direkt die per pyuic generierten Quellcode-Dateien?

Das sollte man nicht tun. Man sollte sogar pyuic im Allgemeinen meiden. Benutze lieber das "uic"-Modul, und erzeuge in einem separaten Modul eine Instanz der Benutzeroberfläche per "uic.loadUi":

Code: Alles auswählen

from PyQt4 import ui
from PyQt4.QtGui import QMainWindow

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.ui = loadUi('/path/to/my/file.ui')
Anschließend kannst du auf die Attribute der Benutzeroberfläche über "self.ui" zugreifen, z.B. so (angenommen, du hast im Designer ein Label namens "my_label" erzeugt):

Code: Alles auswählen

self.ui.my_label.setText('Spam with eggs, please!')
In einem eigenen Modul kannst du PyQt4 dann so importieren, wie du lustig bist, nur solltest du dabei explizite Imports anwenden, sprich keine *-Imports wie in meinem Beispiel. Ich nutze normalerweise auch explizite Imports, im Beispiel wollte ich aber Zeit sparen.
Ok,Meine Begriffsstutzigkeit bitte ich zu entschuldigen.
Nichts für ungut, ich hab auch etwas überreagiert ;)
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

lunar hat geschrieben: Huch? Editierst du etwa direkt die per pyuic generierten Quellcode-Dateien?
Auf keinen Fall, da ja alle Aenderungen verloren gehen sobald ich wieder mit Qt-Design arbeite.
Ich speichere die dialog.ui (aus Qt-Design) und dann uebersetzte ich mittels

Code: Alles auswählen

pyuic4 -o dialog.py dialog.ui
Das wars.

Aber warum pyuic meiden?

Wolf
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

xWolf hat geschrieben:Aber warum pyuic meiden?
Weil Codegenerierung unpraktisch ist. Man muss sich erinnern ihn immer neu zu generieren, man muss zwei Dateien statt einer rumschleppen, der Stil des Codes ist nicht unbedingt der, den man selbst nutzt, man (oder auch andere Contributors) wird nicht verleitet im Quellcode rumzueditieren...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

xWolf hat geschrieben:
lunar hat geschrieben:Huch? Editierst du etwa direkt die per pyuic generierten Quellcode-Dateien?
Auf keinen Fall, da ja alle Aenderungen verloren gehen sobald ich wieder mit Qt-Design arbeite.
Dann kannst du PyQt4 doch importieren, wie du willst, und bist nicht unbedingt an "from PyQt4 import QtGui" gebunden!
Aber warum pyuic meiden?
Leonidas hat gute Gründe genannt. Dazu kommt noch, dass der erzeugte Code nicht der beste ist, und innerhalb von Paketen mitunter Probleme bereitet.

Bei der Verwendung von pyuic ist es mir früher (noch unter Qt3) oft passiert, dass ich lange nach einem Fehler gesucht habe, der – wie sich dann herausstellte – nur daher rührte, dass ich zwar die UI-Datei im Designer bearbeitet, nicht aber den generierten Code neu erzeugt hatte. Sowas vermeidet man, wenn man sich nicht von der Code-Generierung abhängig macht.
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

OK, ihr habt recht.

Wolf
lunar

Zum einen wird der Code nur dann automatisch generiert, wenn man eine IDE nutzt, die das durchführt. Viele hier – mich eingeschlossen – nutzen keine IDE. Ich persönlich programmiere im Texteditor und rufe den Designer manuell auf. Dann müsste ich auch die Code-Generierung manuell durchführen.

Du scheinst den Verzicht auf pyuic gleichzusetzen mit dem Verzicht auf den Designer. Das ist nicht der Fall, man kann den Designer auch ohne pyuic nutzen. Dafür gibt es das Modul "PyQt4.uic", welches Funktionen bereitstellt, um das UI-Objekt direkt aus der vom Desginer erzeugten UI-Datei zu laden.
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

Ja es klappt zwar mit dem Tastenkuerzel Ctrl+K aber clicke ich mit der Maus auf den Button ist Sense.
Der Unterschied zwischen Deinem Programm und meinem ist: Du startest ein Application-Window und setzt dort die Toolbar rein. Mein Dialog ist ein Dialog, der aus einem Applications-Window gestartet wird. Im Dialog funktioniert das aber nicht mehr so.
Sch....

OK, also muss ich doch nach dem Focus suchen.
Denn wenn ich mit der Maus oder der Tab-Taste den Cursor in das Textfenster setze, dann muss doch eigendlich ein getFocus-Ereignis ausgeloest werden.
Ebenso, wenn ich per Tab oder Maustaste den Focus auf ein Anderes Steuerelemnt setze muesste es doch ein lostFocus-Ereignis geben.
Die Classendokumentation weist ja darauf hin, dass es diese Ereignisse gibt, nur weiss ich nicht wie ich dieses Ereignis programmiere.

Hmmm.
Nimmt wohl kein Ende.

Wolf
lunar

Zum zweiten Mal: Änderungen des Fokus kannst du über das Signal "QApplication.focusChanged" abfangen, focusLost und dergleichen braucht man nur, wenn man eigene Widgets implementiert.

Den Unterschied zwischen deinem und meinem Code habe ich nicht verstanden, und ohne Code kann ich da auch wenig zu sagen. Poste Quellcode, der dein Problem zeigt, dann kann ich dir helfen, ansonsten kann ich allenfalls im Dunkeln stochern. Müsste ich das tun, würde ich sagen, dass der Button den Focus stiehlt. Die Lösung für dieses Problem aber habe ich bereits im zweiten Beispiel gezeigt ...
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

Also dem Protokoll wegen lasse ich meinen obigen Beitrag stehen.
Habe auch eine Klickie-Loesung gefunden.

Ich setze im Qt-Designer die Focus-Policy auf "No-Focus" und schon klappt es.
Leider kann ich dann den Button nicht mehr mit der Tab-Taste anspringen, aber Herrgott - man kann doch nicht alles haben im Leben.

Aber das mit meinen angesprochenen gotFocus und lostFocus-Ereignissen, dass wuerde mich schon interessieren wie es funktioniert, da ich diese Ereignisse aus VB und dem OOffice kenne und ich da starke Verwendung haette.

Koennte da mal ...??? :roll:

Dank Euch

Wolf
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

Hey Lunar,

Du bist schneller als die Polizei erlaubt. Es muss doch tiefe Nacht bei Dir sein. Bei mir in USA ist es jetzt 20:00 !!!!
lunar hat geschrieben:Zum zweiten Mal: Änderungen des Fokus kannst du über das Signal "QApplication.focusChanged" abfangen, focusLost und dergleichen braucht man nur, wenn man eigene Widgets implementiert.
Wo und wie baue ich denn diese Ereignisroutine ein?
Das ist echt mein Problem.
QApplication.focusChanged wo steht das in der Klassendefinition und wie sieht so eine Zeile aus?. Kannst Du mir eine Beispielzeile geben?
Poste Quellcode, der dein Problem zeigt, dann kann ich dir helfen, ansonsten kann ich allenfalls im Dunkeln stochern.
NEIN!!!!!! Den Code willst Du nicht sehen!!!!!
Du wuerdest Haare verlieren - in Sekunden um Jahre altern - die Welt verfluchen in der Du geboren wurdest....
Da Du mir so tapfer hilfst, tue ich Dir das nicht an. :)
Müsste ich das tun, würde ich sagen, dass der Button den Focus stiehlt.
Ja, tat er und zur Strafe bekommt er keinen Focus mehr :D .
Siehe oben.

Wolf
lunar

xWolf hat geschrieben:Wo und wie baue ich denn diese Ereignisroutine ein?
Das ist echt mein Problem.
QApplication.focusChanged wo steht das in der Klassendefinition und wie sieht so eine Zeile aus?. Kannst Du mir eine Beispielzeile geben?
http://paste.pocoo.org/show/107871/ <- so sieht das aus, wenn du das zuletzt fokussierte Widget speicherst.

Ich persönlich würde aber einfach zwei Aktionen in das Kontextmenü der Widgets einfügen. Das halte ich für besseres UI-Design
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

lunar hat geschrieben:Ich persönlich würde aber einfach zwei Aktionen in das Kontextmenü der Widgets einfügen. Das halte ich für besseres UI-Design
Das wird wohl meine naechste Versuchsaktion sein. Ein Eintrag im Kontextmenue finde ich auch sehr elegant.

Allerdings muss ich sagen, das Tastenkuerzel (in meinem Falle Ctrl+k) ist beim Schreiben natuerlich ein echter Geschwindigkeitsvorteil.

Nochmals vielen Dank fuer Deine Geduld.

Wolf
lunar

Auch Aktionen im Kontextmenü lassen sich mit Tastenkürzeln versehen.
Benutzeravatar
xWolf
User
Beiträge: 62
Registriert: Sonntag 2. November 2008, 01:21
Wohnort: China

lunar hat geschrieben:Auch Aktionen im Kontextmenü lassen sich mit Tastenkürzeln versehen.
OK, Du beschaeftigst mich ja ganz schoen.
Das Problem wird dann wohl ein neuer thread.

Danke

Wolf
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

lunar hat geschrieben:

Code: Alles auswählen

from PyQt4 import ui
from PyQt4.QtGui import QMainWindow

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.ui = loadUi('/path/to/my/file.ui')
Da sind ein paar Flüchtigskeitsfehler drin (Zeile 1+7). Hier ein (ich hoffe doch sehr) lauffähiges Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import QtGui, uic


class MyMainWindow(QtGui.QMainWindow):

    def __init__(self, ui_file='/path/to/my/file.ui', parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.ui = uic.loadUi(ui_file, self)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    app.exec_()
Antworten