Actions mit loadUi

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hi, man kann ja bei PyQt4 ein *.ui File ohne vorher zu compilieren direkt laden. Man kann ein Widget automatisch mit einer Funktion connecten, indem man eine Funktion mit

@QtCore.pyqtSignature("")
def on_<Widget>_<Signal>(self):

definiert. Was ich noch nicht herausgefunden habe ist, wie man Actions verarbeiten kann. Es gibt ja die Möglichkeit, die gleiche Funktion durch das Menu, die Toolbar oder über ein Tastenkürzel aufzurufen. Ich hab da auch noch kein Beispiel oder Doku gefunden.

Gibt es da was?
lunar

Das funktioniert auch mit Aktionen (genauer gesagt funktioniert es mit Exemplaren jedes von QObject abgeleiteten Typs unterhalb des aktuellen Objekts). Dokumentiert ist das im Übrigen auch, siehe PyQt4 Reference Guide, Abschnitt 7.5.3 „Connecting Slots By Name“ und QMetaObject::connectSlotsByName().

Nebenbei bemerkt, statt pyqtSignature nimmst Du auch besser pyqtSlot, sofern Du PyQt 4.5 oder neuer verwendest.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich muss das Thema nochmal ausgraben. Bin die ganze Zeit nicht mehr dazu gekommen. Gibt es zu dem Thema irgendwo ein aktuelles Tutorial oder wenigstens mal ein "HelloWorld" Beispiel?

Mit aktuell meine ich, aktualisiert auf Qt4.5 oder später und die Verwendung von UI Files direkt, so wie man es eben nach aktuellem Stand programmieren sollte. Mein "Rapid GUI Programming with Python and Qt" ist leider etwas veraltet.
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
lunar

@burli: Dafür brauchst Du ein Tutorial? Verzeih mir, aber die Thematik ist eigentlich nicht so komplex, dass sie nicht mit einem Blick in die Dokumentation zu klären wäre. Davon abgesehen hat sich daran seit Qt 4.2 oder so nichts geändert, jedes Buch zu Qt4 sollte das entsprechend wiedergeben, egal wie alt.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

das genannte Buch leider nicht. Das verwendet noch * Imports und arbeitet nur mit compilierten ui Files.
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

ich glaube das ist Selbsterklärend:

Code: Alles auswählen

from PyQt4 import QtCore
from PyQt4.uic import loadUiType

QTDESIGNER_UI = loadUiType('hmi.ui')[0]

class Fenster(QtGui.QMainWindow, QTDESIGNER_UI):
    def __init__(self, parent=None):
        super(Fenster, self).__init__(parent)
        self.setupUi(self)
        self.tabWidget.setCurrentIndex(1)
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Danke. Ich nehme mal an, der Rest ist dann ähnlich wie bei compilierten UI Files
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich brauche jetzt doch nochmal Hilfe. Ich habe in meinen Archiven gestöbert und bin über zwei Beispiele gestolpert. Ein Beispiel verwendet loadui, das zweite loaduiType

Code: Alles auswählen

#!/usr/bin/env python
import sys

from PyQt4 import QtCore, QtGui, uic


app = QtGui.QApplication(sys.argv)
form_class, base_class = uic.loadUiType("demo.ui")

class DemoImpl(QtGui.QDialog, form_class):
    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)

        self.setupUi(self)
    
    @QtCore.pyqtSignature("")
    def on_button1_clicked(self):
        for s in "This is a demo".split(" "):
            self.list.addItem(s)


form = DemoImpl()
form.show()
app.exec_()

Code: Alles auswählen

#!/usr/bin/env python
import sys

from PyQt4 import QtCore, QtGui, uic


class DemoImpl(QtGui.QDialog):
    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)
        uic.loadUi("demo.ui", self)

    @QtCore.pyqtSlot(str)
    def on_button1_clicked(self):
        for s in "This is a demo".split(" "):
            self.list.addItem(s)


app = QtGui.QApplication(sys.argv)
widget = DemoImpl()
widget.show()
app.exec_()
Beide verwenden das gleiche ui file

http://pastebin.de/7108

loaduiType wird wohl außerhalb der Klasse definiert und loadui innerhalb. Aber wieso wird einmal @QtCore.pyqtSignature("") und einmal @QtCore.pyqtSlot(str) verwendet? Und wieso funktioniert das Beispiel mit loadui nicht? Wenn ich pyqtSlot(str) gegen pyqtSignature("") austausche geht das Beispiel auch. Wo ist der Wurm drin?
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
lunar

Ich persönlich bevorzuge "loadUi()", weil es weniger zusätzliche Namen in den Namensraum wirft, und weil es bis zur Erzeugung eines Exemplars aufgeschoben werden kann (während "loadUiType()" zur Erzeugung der Klasse funktionieren muss).

pyqtSignature und pyqtSlot haben beide zum Zweck, eine Python-Methode mit C++-Metadaten (e.g. der Signatur) zu versehen, damit Qt (insbesondere "QMetaObject.connectSlotsByName()") in der Methode einen Slot erkennt. Die beiden Dekoratoren unterscheiden sich nur hinsichtlich ihrer Argumente: pyqtSignature nimmt eine Zeichenkette mit einer C++-Signatur entgegen. Eine leere Zeichenkette spezifiziert dabei, dass der Slot kein Argument entgegen nimmt. pyqtSlot dagegen nimmt eine Folge von Python-Typen entgegen. Zusammen mit pyqtSignal gehört sie zum "new-style" Signal-API von PyQt 4.5 und höher, die eingeführt wurde, damit man sich als Python-Entwickler nicht mit C++-Signaturen beschäftigen muss. "pyqtSlot(str)" bedeutet allerdings, dass der Slot ein Argument, nämlich eine Zeichenkette entgegen nimmt, was allerdings tatsächlich nicht der Fall ist. Deswegen funktioniert das Beispiel nicht. "pyqtSlot()" dagegen funktioniert, und ist dasselbe wie "pyqtSignature('')".
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Danke für die Erläuterung. Das bringt mich ein gutes Stück weiter. Hab gestern auch nochmal pyqtSlot("") ausprobiert. Das ging auch. Gibt es einen Unterschied zwischen () und ("")?
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
lunar

Du fragst Sachen ... ich würde mal vermuten, dass beides identisch ist. Aber warum willst Du unbedingt eine leere Zeichenkette übergeben? Eine leere Argumentliste macht Doch viel deutlicher, dass keine Argumente entgegen genommen werden.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

lunar hat geschrieben:Du fragst Sachen ... ich würde mal vermuten, dass beides identisch ist. Aber warum willst Du unbedingt eine leere Zeichenkette übergeben?
Das hab nicht ich programmiert. Das sind Beispiele, die ich gefunden habe. Deshalb frage ich so dumm, damit ich nicht die gleichen Fehler mache.

Danke für die Hilfe
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Antworten