connectSlotsByName mit QUiLoader

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
acilander
User
Beiträge: 4
Registriert: Freitag 16. September 2011, 14:17

Hallo,
ich benutze Pyside, lade ein "*.ui" file dynamisch mit QUiLoader und möchte die Signale mit den Slots automatisch mit "connectSlotsByName" verbinden. Das kriege ich leider nicht hin. Wenn ich die Signale manuell verbinde funktioniert es. Hat jemand eine Idee was ich hier falsch mache?

Code: Alles auswählen

import sys, os
from PySide.QtUiTools import *
from PySide.QtCore import *
from PySide.QtGui import *

class Gui(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        loader = QUiLoader()
        self.ui = loader.load('GUI.ui')
        self.ui.show()
        QMetaObject.connectSlotsByName(self.ui)
    
    def on_pushButton_clicked(self):
       self.ui.StatusLabel.setText("pushed")
        
def main(args):
    app = QApplication(args)
    window=Gui()
    #window.ui.pushButton.clicked.connect(window.on_pushButton_clicked)
    sys.exit(app.exec_())

if __name__ == "__main__":
    main(sys.argv)
lunar

@acilander: Du verwendest ".load()" und ".connectSlotsByName()" falsch. Richtig wäre dies:

Code: Alles auswählen

loader = QUiLoader()
self.ui = loader.load('GUI.ui', self)
QMetaObject.connectSlotsByName(self)
Das nächste Mal lies die Dokumentation bitte selbst…
acilander
User
Beiträge: 4
Registriert: Freitag 16. September 2011, 14:17

Hallo lunar,

danke für den Hinweis. Ich habe meinen Code entsprechend geändert und mit die Dokumentation nochmal angeschaut. Der zweite Parameter für die load()-Funktion ist optional. Hier fehlt mir das grundsätzliche Verständnis, wann dieser Parameter gesetzt werden muss, und wann nicht. Da muss ich noch mehr Erfahrung sammeln.
Bei connectSlotsByName() wird ein Objekt übergeben, in diesem Fall self, welches das Signal der Gui enthält und den Slot den ich in der Klasse angelegt habe. Beim Debuggen springt das Programm beim Klicken auf den Button nicht in die entsprechende Funktion. Es scheint noch etwas zu geben, das ich noch nicht verstanden habe. Hast du noch eine Idee in welche Richtung ich weiter suchen könnte?
lunar

@acilander: Bibliotheken versteht man nicht durch Debuggen, sondern nur durch Lesen der Dokumentation. Zu ".connectSlotsByName()" heißt es:
Searches recursively for all child objects of the given object, and […]
Zu ".load()" dann weiter:
Loads a form from the given device and creates a new widget with the given parentWidget to hold its contents.
Fällt Dir die offensichtliche Entsprechung zwischen "parentWidget" und "child objects" auf? Ist Dir jetzt klar, warum Du beides so benutzen musst, wie ich Dir gezeigt habe?

Falls nicht, falls Dir die Begriffe Vater- und Kind-Objekt im Kontext von Qt nichts sagen, dann lese bitte die Grundlagen-Dokumentation:
acilander
User
Beiträge: 4
Registriert: Freitag 16. September 2011, 14:17

So,
jetzt habe ich einen lauffähigen Code hinbekommen. Das Stichwort heißt hier "Decorators". Vor die Funktion die zu einem Slot werden soll musste ich ein @Slot() stellen. Warum das so ist und warum das kaum in einem Beispiel vorkommt das mir über den Weg gelaufen ist, weiß ich noch nicht. Aber auf diese Weise schafft es connectSlotsByName() die Signale mit den Slots zu verbinden.

@lunar. Danke für die Hinweise für die richtige Verwendung von load() und connectSlotsByName()

Code: Alles auswählen

import sys, os
from PySide.QtUiTools import *
from PySide.QtCore import *
from PySide.QtGui import *

class Gui(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        loader = QUiLoader()
        self.ui=loader.load('GUI.ui',self)
        QMetaObject.connectSlotsByName(self)

    @Slot()    
    def on_pushButton_clicked(self):
       self.ui.StatusLabel.setText("pushed")

def main(args):
    app = QApplication(args)
    window=Gui()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main(sys.argv)
Falls jemand das Beispiel nachbauen möchte hier noch der Code für die Datei "GUI.ui"

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>250</width>
    <height>146</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QPushButton" name="pushButton">
   <property name="geometry">
    <rect>
     <x>90</x>
     <y>50</y>
     <width>75</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>Push Me!</string>
   </property>
  </widget>
  <widget class="QLabel" name="StatusLabel">
   <property name="geometry">
    <rect>
     <x>100</x>
     <y>70</y>
     <width>61</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>not pushed</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

acilander, danke für das Beispiel. Qt und speziell PySide ist ein einziges Chaos. Die Dokumentation ist extrem unübersichtlich und versteckt. Außerdem leidet sie da drunter, dass Nokia mein Qt mal wieder neu erfinden zu müssen und man nur noch Sachen zum Telefon-QML findet.
acilander
User
Beiträge: 4
Registriert: Freitag 16. September 2011, 14:17

Hallo Darii,
ich habe auch meine Schwierigkeiten mich in der Doku zurechtzufinden. Das liegt aber daran, dass ich noch Anfänger in Sachen Python bin. Deshalb kann ich nicht Einschätzen in wie weit deine Aussagen zutreffend sind. Aber ich freue mich, wenn jemand mit diesem "Basics-Beispiel" geholfen wird. :D
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Darii hat geschrieben:acilander, danke für das Beispiel. Qt und speziell PySide ist ein einziges Chaos. Die Dokumentation ist extrem unübersichtlich und versteckt. Außerdem leidet sie da drunter, dass Nokia mein Qt mal wieder neu erfinden zu müssen und man nur noch Sachen zum Telefon-QML findet.
WTF? Sry, bessere Dokumentation als bei Qt findet man selten und PySide braucht per se keine (bzw nicht viel) Docs, der Assistant reicht bis auf ein paar Spezialfälle aus.
lunar

@apollo13: Nach einem Monat war diese Bemerkungen jetzt auch nicht mehr nötig ;) Zumal die Bemerkung im Bezug auf die Dokumentation von PySide vollkommen richtig ist, sie ist mit Ausnahme der in Sphinx geschriebenen Modul-Dokumentation ein einziges Wiki-Chaos, und nur weil Du diese Dokumentation nicht benötigst, muss das ja nicht für andere gelten. Wer C++ nicht kann, ist vielleicht durchaus froh darüber, gute und umfangreiche Tutorien zu PySide in Python zu finden… die es aber zur Zeit kaum gibt, zumindest nicht in der offiziellen Dokumentation.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

lunar hat geschrieben:@apollo13: Nach einem Monat war diese Bemerkungen jetzt auch nicht mehr nötig ;)
Au sry, das hab ich übersehen
Zumal die Bemerkung im Bezug auf die Dokumentation von PySide vollkommen richtig ist, sie ist mit Ausnahme der in Sphinx geschriebenen Modul-Dokumentation ein einziges Wiki-Chaos, und nur weil Du diese Dokumentation nicht benötigst, muss das ja nicht für andere gelten.
Gut ich brauch sie für PySide Eigenheiten, da rate ich dann lieber doch nicht ;)
Wer C++ nicht kann, ist vielleicht durchaus froh darüber, gute und umfangreiche Tutorien zu PySide in Python zu finden… die es aber zur Zeit kaum gibt, zumindest nicht in der offiziellen Dokumentation.
Gut das ist ein Argument, wenngleich ich nicht sagen würde dass ich C++ kann. Aber ich denke man sollte auch wenn man C++ nicht kann für normale Fragen durchaus den assistant zu Rate ziehen -- ich denke die meisten werden sich zurecht finden.
Antworten