QtDesigner output umwandeln und in script einbinden

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

ich verwende Ubuntu als Betriebssystem und Eclipse als IDE. Mit dem QtDesigner habe ich ein Dialog-fenster erstell und nun möchte ich in einem script das Fenster aufrufen.
Dabei habe ich anhand dieses tutorials http://zetcode.com/tutorials/pyqt4/german/ ein Hauptfenster erstellt das in der Menubar bestimmte icons hat, die bestimmte actionen starten usw...

Nun zu meinem Problem, ich möchte per mausclick auf einem icon das Dialog-fenster öffnen das ich zuvor mit dem Designer erstellt hab.
Zuerst hab ich die ui datei umkonvertiert und mit:

Code: Alles auswählen

from Dialog import *
in meinem script importiert.
Hiermit definiere ich welche Funktion:

Code: Alles auswählen

input = QtGui.QAction(QtGui.QIcon.fromTheme('list-add'), 'Input', self)
        input.setShortcut('Ctrl+I')
        input.setStatusTip('Set Input Files')
        self.connect(input, QtCore.SIGNAL('triggered()'), self.input)
beim klick ausgeführt wird.
Wie kann ich jetzt per input-Funktion das Dialog-fenster öffnen?
Ich habe schon einige sachen versucht und auch lange im netz gesucht, aber anscheinend wird das nicht so gemacht. Ich habe wohl einen generellen Denkfehler?

Gruß Air
lunar

@airtime Du musst eben eine Methode implementiernen, in der Du ein Exemplar Deiner Dialog-Klasse erzeugst, und anzeigst. Wo liegt Dein spezifisches Problem?
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

ich habe mit der methode versucht das fenster zu erstellen:

Code: Alles auswählen

def input(self):
        dia = QtGui.QApplication(sys.argv)
        icon = Ui_dialog()
        icon.show()
        dia.exec_()
aber es kommt die Fehlermeldung das es nicht die Möglichkeit hat das show attribut zu nutzen.
Kann das sein, das ich noch irgendwie den Konstruktor verändern muss oder so?

Gruß Air
lunar

@airtime Die vom UI-Compiler erzeugten Klassen sind keine Widgets, sondern enthalten nur die Definition des Inhalts. Du musst sie zusammen mit der entsprechenden Widget-Klasse verwenden, in Deinem Fall "QDialog". Bitte lese die Dokumentation, um zu erfahren, wie das geht.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

sowie in der Doku beschrieben hab ich es auch ausprobiert, aber irgendwie mache ich etwas falsch.
Die Beispiele sind immer nur auf ein einzelnes script bezogen.
Also ich habe meine Methode zu folgendem geändert:

Code: Alles auswählen

    def input(self):
        QtGui.QDialog.__init__(self)        
        self.ui = Ui_dialog()
        self.ui.setupUi(self)
Aber es fehlt doch das anzeigen? Oder sind die connections essentiell (sollten erstmal nicht sein)?
Ich verstehe nicht wie ich aus der Funktion der MainWindowclass die Uiclass anzeigen kann.
Muss ich einfach nur eine neue Klasse im script erstellen?

Gruß Air
lunar

@airtime Das kann auch nicht funktionieren, Du rufst ".__init__()" an der völlig verkehrten Stelle auf, und versuchst anschließend, die Oberfläche nicht im neuen Dialog, sondern im aktuellen Fenster anzuzeigen. Bitte lese den Abschnitt über Klassen im offiziellen Tutorial, bevor Du weiterarbeitest. Ich fürchte, Dir fehlt Grundwissen über Klassen und Vererbung, welches für die Programmierung graphischer Oberflächen wirklich essentielles Grundwissen ist.

Ich fürchte auch, ich kann Dir nicht weiterhelfen, bevor Du nicht selbst ohne meine Erklärung verstehst, warum der Quelltext in Deinem Beitrag nicht funktioniert. Der fehlen zu viele Grundlagen.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

vielen Dank. Deine Antwort hat glaube ich schon das meißte beantwortet was ich wissen wollte. Zu meinem Grundwissen, naja ich benutze mehrere Programmiersprachen und die vielen Formatierungen bringen mich dan schon etwas durcheinander. Bezüglich Vererbung gebe ich zu das mir da noch was fehlt. Ich werde mir das Tutorial mal anschauen, aber wahrscheinlich brauche ich nur eine Klasse die den ui Dialog initialisiert und den dann über die Funktion aus der main klasse aufrufen läst.

Gruß Air
lunar

@airtime Die meisten regelmäßigen Mitglieder dieses Forums benutzen mehrere, oft ganz unterschiedliche Sprachen.

Ja, letztlich Du musst Du nur eine Klasse erzeugen, die von "QDialog" erbt und die Benutzerschnittstelle des Dialogs erstellt. Diese Klasse kannst Du dann in der Hauptklasse benutzen, um Deinen Dialog anzuzeigen.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

also ich hab mit follgendem script das mit dem designer erstellte interface aufgerufen:

Code: Alles auswählen

#!/usr/bin/python

import sys
from PyQt4 import QtGui, QtCore
from designer import ui

class MeinDialog(QtGui.QDialog, ui): 
    def __init__(self): 
        QtGui.QDialog.__init__(self) 
        self.setupUi(self)


app = QtGui.QApplication(sys.argv)
dia = MeinDialog()
dia.show()
sys.exit(app.exec_())
Mein Problem ist sobald ich in meinem hauptscript in der mainwindow Klasse den dialog aufrufen will passiert nichts.
Ich habe mit:

Code: Alles auswählen

class MeinDialog(QtGui.QDialog, Ui_Input_Selection): 
    def __init__(self): 
        QtGui.QDialog.__init__(self) 
        self.setupUi(self)
die Klasse erstellt und in der funktion den Aufruf mit:

Code: Alles auswählen

def input(self):
        dia = MeinDialog()
        dia.show()
probiert. Aber es passiert nichts.

Gruß Air
deets

Das ist murks. Du sollst doch nicht von Ui_Input_Selection erben, sondern *nur* von QDialog. So wie hier:

http://www.riverbankcomputing.co.uk/sta ... igner.html
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

vielen Dank für die Hilfe, aber dieser murks steht auf der seite:

Code: Alles auswählen

class ImageDialog(QDialog, Ui_ImageDialog):
    def __init__(self):
        QDialog.__init__(self)

        # Set up the user interface from Designer.
        self.setupUi(self)
Ich habe es dann mal umgeändert zu:

Code: Alles auswählen

class MeinDialog(QtGui.QDialog): 
    def __init__(self): 
        QtGui.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = Ui_Input_Selection()
        self.ui.setupUi(self)
aber das Problem besteht immer noch.
Ich denke es müsste noch was bei dem Aufruf in der funktion falsch sein, aber was?

Gruß Air
deets

Ah, ich dachte der inheritance-Ansatz waere mit Qt4 verschwunden. Und hatte nur das erste Beispiel quergelesen.

Bist du sicher, dass die Funktion aufgerufen wird? Und hast du die richtige Qt-Klasse eingestellt im Designer? Die kann ja Widget, Dialog oder MainWindow sein. Wenn es mit der App funktioniert, dann ist es vielleicht ein Mainwindow - und funktioniert nicht fuer Dialoge.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

also das sollte eigentlich alles stimmen. Bin mir aber etwas unsicher weil in der erstellten Ui Klasse attribute wie object und _fromUtf8 genutzt werden.
Die funktion wird aufgerufen und ist diese auch richtig?

Code: Alles auswählen

    def input(self):
        dia = MeinDialog()
        dia.show()
das ist mir zu wenig code, zwar gibt es noch keine rückgabe werte usw. aber die Einbindung in das mainwindow fehlt mir (da das mainwindow den ablauf bestimmt).
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

ok mit accept und exec funktioniert es. Das dies meine erste python gui ist würde ich noch fragen ob das auch vom programmier style ok ist?

Code: Alles auswählen

    def input(self):
        dia = MeinDialog()
        dia.accept()
        dia.show()
        dia.exec_()
Gruß Air
deets

accept ist sinnlos, so wie du das benutzt. Das ist ein Slot der durch einen Button aufgerufen werden soll, damit exec_ einen vernuenftigen Rueckgabewert liefert.

Und wenn ich die Doku verstehe, ist auch das show im exec_ mit inbegriffen.

Bezueglich der Code-Qualitaet: 4 Zeilen sind etwas wenig, um's zu beurteilen.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hi,

ich wollte eigentlich nur wissem ob der aufruf ok ist. Zudem ist reichlich code zuvor zusehen, aber ich will niemanden bitten sich den gesamten quellcode anzuschauen.
Irgendwie habe ich wohl meine Fragen falsch gestellt. Deswegen hier nochmal eine Zusammenfassung mit der Antwort.
Ich denke das könnte anderen Beginnern helfen.

Frage:
-Wie binde ich eine ui (mit QtDesigner erstellt) in ein script ein? Zudem ist in dem script schon ein MainWindow vorhanden.
Antwort:
-Erstelle in dem script eine Klasse die von QDialog erbt und die Klasse von der ui datei einbindet

Code: Alles auswählen

class MeinDialog(QtGui.QDialog): 
    def __init__(self): 
        QtGui.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = Ui_Input_Selection()
        self.ui.setupUi(self)
-Der Aufruf im MainWindow kann mit Hilfe von einem icon in der Menübar visualisiert werden. Natürlich müsste man hier den Aufruf dem MainWindow Richtlinien anpassen (Button usw.)

Code: Alles auswählen

input = QtGui.QAction(QtGui.QIcon.fromTheme('list-add'), 'Input', self)
        input.setShortcut('Ctrl+I')
        input.setStatusTip('Set Input Files')
        self.connect(input, QtCore.SIGNAL('triggered()'), self.input)
-Der Aufruf wird mit Hilfe der funktion (hier input) durchgeführt. Da es sich um einen modalen Dialog handelt wird exec_ und nicht show genutzt.

Code: Alles auswählen

    def input(self):
        dia = MeinDialog()
        dia.exec_()
Für weitere Kritik und Tipps wäre ich sehr dankbar. Vorallem wenn etwas grundsätzlich falsch sein sollte.

Gruß Air
BlackJack

@airtime: So ganz grundsätzlich fehlt mir wo das `parent`-Objekt für den Dialog angegeben wird. Was vielleicht auch der Grund ist warum Du eine weitere Ereignisschleife starten musst, um das anzuzeigen.

Für das verbinden von Signalen und Slots gibt es einen besseren Weg:

Code: Alles auswählen

self.connect(input, QtCore.SIGNAL('triggered()'), self.input)
# =>
input.triggered.connect(self.input)
lunar

airtime hat geschrieben:

Code: Alles auswählen

    def input(self):
        dia = MeinDialog()
        dia.show()
Dieser Quelltext funktioniert nicht, da "MeinDialog()" kein "parent" hat. Dann kommen sich Python und Qt bei der Speicherverwaltung in die Quere, so dass der Dialog von Python gelöscht wird, bevor Qt die Chance hat, ihn anzuzeigen. Folgendes funktioniert:

Code: Alles auswählen

[code=python]class MeinDialog(QtGui.QDialog): 
    def __init__(self, parent=None): 
        QtGui.QDialog.__init__(self, parent)
        # Set up the user interface from Designer.
        self.ui = Ui_Input_Selection()
        self.ui.setupUi(self)
class MainWindow(QtGui.QMainWIndow):
# …
def input(self):
dia = MeinDialog(self)
dia.show()[/code]
Beachte das "self" im Aufruf von "MeinDialog()", sowie den neuen Parameter "parent" für "MeinDialog.__init__()". Diese zwei Dinge sind in PyQt essentiell, damit die Speicherverwaltung funktioniert. Setze immer das "parent"-Argument bei der Erzeugung von Qt-Objekten.
Antworten