Die verrückten Layouts im QT Designer

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute,

ich arbeite zur Zeit mit dem QT Designer 4.8. Dort habe ich schon einige Oberflächen gestaltet. Nun bin ich an einem Punkt gekommen, wo mich die Layouts irgendwie verrückt machen. Ich verbinde die einzelnen Widgets, die zusammen gehören entsprechend (horizontal oder vertikal) und am Ende muss dann das ganze Fenster mit dem Layout Grid versehen werden, damit die einzelnen Widgets beim Verändern des Fensters auch mit bewegen. Wenn ich das aber tue, dann "verrutscht" alles auf dem Fenster. Nichts ist dann an Ort und Stelle wie es vorher war. Nun wollte ich mal fragen, ob es hier jemanden gibt, der sich mit dem QT Designer sehr gut auskennt und einmal drüber schauen könnte?

Ich habe hier bei Pastebin mein Fenster in zweifacher Version hochgeladen. Einmal mit einigen Layouts. Die Widgets sind nur an den Stellen platziert, wo ich sie haben möchte. Und die Layouts sind auch schon angewendet worden. Nur habe ich hier den letzten Schliff weggelassen, also dieses Grid-Layout, welches man auf das Fenster anwendet, damit die Widgets sich entsprechend bewegen. Die zweite Version hat keine Layouts. Die Widgets liegen "lose" auf dem Fenster, da wo ich sie haben möchte.

Hier die beiden Versionen:
Version 1: Mit Layouts
Version 2: Ohne Layouts
(Das sind beide *.ui-Dateien. Quelltext runterladen und die Datei dann mit der Endung *.ui versehen.)

Bei beiden Versionen ist soweit alles in Ordnung. Wenn ich aber Version eins den letzten Schliff verpasse, und der Form Grid verpasse, dann verrutscht alles ins bodenlose. Alles sieht mächtig chaotisch aus. Und ich hätte gerne, dass sich jemand mal freiwillig das Ganze anschaut. Wie gesagt, in Version habe ich so weit wie es geht "erfolgreich" überall die entsprechenden Layouts verpasst. Nur wenn die Form das Grid-Layout bekommt, "verrutscht" alles sehr stark.

Vielleicht übersehe ich etwas?
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Ich versuche das mal zu sortieren.

Version 2 kannst du verwerfen. Absolut positionierte Widgets sind die Hölle, vor allem wenn dein Fenster in der Größe veränderlich sein soll. Also, keine "frei schwebenden" Elemente konstruieren.

Version 1 ließe sich mit etwas Klick-Aufwand so umbauen, dass du dein Ziel erreichst, allerdings nicht über den Weg, da jetzt einfach ein GridLayout auf die Form anzuwenden. Hast ja bereits selbst entdeckt, dass dies nicht zu dem gewünschten Ergebnis führt. Du musst dich fragen, warum du einen Unterschied zwischen dem Window und anderen Widgets machst. So wie du andere Elemente gruppierst, kannst du doch die restlichen analog anordnen.

Prinzipiell würde ich dir empfehlen, das GUI deutlich modularer zu gestalten. Du hast da mittlerweile einen Grad der Komplexität erreicht, bei dem sich das Zerlegen der einzelnen Bereiche in verschiedene *.ui Dateien anbietet. Soll nur ein Rat sein, musst du nicht umsetzen.

Ich persönlich fange bei Layouts immer von "außen" an. D.h. ich hätte dem MainWindow gleich direkt zu Beginn ein Layout verpasst und weitere Widget unmittelbar darin arrangiert. Nachträgliches Ändern kann im Designer manchmal etwas hässlich sein, gerade wenn Container plötzlich auf eine Breite/Höhe von 0 zusammen schrumpfen und sich nicht mehr selektieren lassen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Madmartigan: Version war dazu da, dass die anderen selbst "rumspielen" können, und sich nicht erst mit meinen Layouts befassen müssen. Das heißt, ich will es den anderen nicht zumuten, dass sie mein halbfertiges Fenster "auseinander" pflücken müssen. War also für "Selbst-Experimente" gedacht.

Das mit dem Tipp, von außen nach innen zu arbeiten werde ich mal ausprobieren. Was ich allerdings noch nicht ganz verstanden habe: modularer. Das heißt den oberen Teil wo allgemeine Informationen hinkommen extra gestalten und als *.ui-Datei abspeichern, den unteren Teil ebenso modular gestalten und dann die Cover-Ecke auch? Und all diese Teile dann über Python "zusammensetzen"? Klingt echt kompliziert.
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Sophus hat geschrieben:Klingt echt kompliziert.
GUI-Programmierung ist kompliziert! Daran scheitern viele, auch solche, die ansonsten sehr gute Programmierer sind.

Das Trennen des Ganzen erleichtert es dir, Änderungen wesentlich einfacher zu implementieren. Du musst dich nicht um das ganze Interface sorgen, nur weil du irgendwo vielleicht ein Layout entfernt hast. In deinem Fall wäre nicht sicher gestellt, dass durch sowas die ganze Form derangiert werden würde. Darüber hinaus werden die Klassen deutlich kleiner und übersichtlicher. Wenn ich manche 1000+ Zeilen GUI-Klassen mancher meiner Kollegen sehe, kommt mir die Grütze zu den Ohren raus. Das will niemand "maintainen". Mehr Modularität bringt dir zudem ein weiteren Vorteil: komplexere Widgets bzw. ganze Teile der GUI werden wiederverwendbar.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Madmartigan: Gibt es dazu Beispiele, wo man sowas lernen kann? Ich kann es mir beim besten Willen nicht vorstellen bzw. wüsste nicht wie ich ansetzen solle. Angenommen ich habe meine Form, die du ja bereits gesehen hast, in drei Teilen zerlegt. Wie würde man vorgehen um diese drei Teile wieder zusammen zu fügen, so dass es dann für den End-Anwender aussieht wie ein einziges Fenster?
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Beispiele gibt es sicher zahlreiche im Internet, etwaige Suchmaschinen helfen bestimmt, Entsprechendes zu finden.

Prinzipiell ändert sich an dem Konzept des dynamischen Ladens von *.ui Dateien nichts. Statt einer einzelnen Datei lädst du mehrere und musst im letzten Schritt die geladenen Objekte nur dem Hauptfenster zuweisen. Das machst du indem du nach dem Laden der "SubWidgets" diesen den Platzhalter im Hauptfenster als Parent zuweist.

Bsp: 2x UI Dateien -> 1x Typ QMainWindow (A), 1x Typ QWidget (B)
Pseudo Code:
uic -> lade (A)
uic -> lade (B)
setze Parent von (B) auf (A) -> das machst du per QWidget.setParent(...), was natürlich bedeutet, du musst den Parent-Widgets im Designer einen Objektnamen geben.

Das ist der minimal erforderliche Schritt. Danach kannst du die Objekte nach deinen Vorstellungen platzieren, in Layouts packen usw.
Ich hoffe, das macht das Prinzip deutlich.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Madmartigan: Vielen Dank. Da ich nicht weiß, wonach ich in der Suchmaschine suchen soll, hilft mir zum Beispiel Google auch nicht weiter. Hat dieser Vorgang einen bestimmten Terminus? Und zu der QMainWindow()-Geschichte. Man darf in seinem Programm nur einmal QMainWindow() verwenden, richtig? Und QMainWindow() wird bei mir schon einmal verwendet, und zwar bei der MDI-Form. All anderen Fenster werden entweder also QDialog oder QWidget behandelt.

Ich habe mir mal deinen Vorschlag angesehen, bin aber noch nicht weit gekommen:

Code: Alles auswählen

from PyQt4.QtCore import *
from PyQt4.QtGui  import *

import sys

class FirstWindow(QWidget):

    def __init__(self, parent=None):

        super(FirstWindow, self).__init__(parent)
        self.form_widget_buttons = FormWidgetButton(self)
        self.form_widget_lineedit = FormWidgetLineEdit(self)



class FormWidgetLineEdit(QWidget):

    def __init__(self, parent):        
        super(FormWidgetLineEdit, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.lineEdit = QLineEdit()
        self.layout.addWidget(self.lineEdit)

        self.lineEdit2 = QLineEdit()
        self.layout.addWidget(self.lineEdit2)

        self.setLayout(self.layout)
        
class FormWidgetButton(QWidget):

    def __init__(self, parent):        
        super(FormWidgetButton, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.button1 = QPushButton("Button 1")
        self.layout.addWidget(self.button1)

        self.button2 = QPushButton("Button 2")
        self.layout.addWidget(self.button2)

        self.setLayout(self.layout)

app = QApplication([])
foo = FirstWindow()
foo.show()
sys.exit(app.exec_())
Ich habe hier also drei Klassen. In der FirstWindow()-Klasse sollen dann die anderen beiden Klasse FormWidgetLineEdit und FormWidgetButton zusammen vereint werden, so dass am Ende nur ein Fenster mit LineEdit und zwei Buttons zusehen ist. In der FirstWindow habe ich zwei Instanzen erstellt, damit die beiden Klassen schon einmal eingebunden sind. Und was jetzt?
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Jetzt setzt du Parent deiner Objekte auf die Instanz der FirstWindow-Klasse. Gib der Instanz ebenfalls ein Layout (vertikal/horizontal/etc...) und füge beide Widgets diesem Layout hinzu.
Et voilà, fertig.

Allerdings hast du das GUI ja jetzt via Code erstellt und nicht *.ui Dateien geladen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Madmartigan: Ich habe deshalb mit dem Code eine GUI erstellt, weil ich es für einen Beispiel ausreichend empfand. Das Prinzip ist ja nachher das gleiche oder? Ich habe nun das gemacht was du gesagt hast. In der FirstWindow() habe ich ein vertikales Layout gesetzt, und die anderen beiden Widgets dessen Layout zum Inhalt gemacht. Nur das Setzen vom Parent habe ich nicht ganz verstanden. Wenn ich mir Zeile 13 und 14 anschaue, dann wurden die Klasse ja mit self an die FirstWindow()-Klasse gebunden. Also bei mir klappt der Aufruf, und es wird tatsächlich nur ein Fenster angezeigt. Wieder habe ich was neues hinzugelernt :) Danke dir. Aber wenn ich was mit den Parent noch was übersehen habe, kannst du es mir mal genauer erklären?

Code: Alles auswählen

from PyQt4.QtCore import *
from PyQt4.QtGui  import *

import sys

class FirstWindow(QWidget):

    def __init__(self, parent=None):
        
        super(FirstWindow, self).__init__(parent)
        self.layout_1 = QVBoxLayout(self)
        
        self.form_widget_buttons = FormWidgetButton(self)
        self.form_widget_lineedit = FormWidgetLineEdit(self)

        
        # Create a layout in this instance
        self.layout_1.addWidget(self.form_widget_buttons)
        self.layout_1.addWidget(self.form_widget_lineedit)


class FormWidgetLineEdit(QWidget):

    def __init__(self, parent):        
        super(FormWidgetLineEdit, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.first_window = FirstWindow()

        self.setParent(self.first_window)


        self.lineEdit = QLineEdit()
        self.layout.addWidget(self.lineEdit)

        self.lineEdit2 = QLineEdit()
        self.layout.addWidget(self.lineEdit2)

        self.setLayout(self.layout)
        
class FormWidgetButton(QWidget):

    def __init__(self, parent):        
        super(FormWidgetButton, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.button1 = QPushButton("Button 1")
        self.layout.addWidget(self.button1)

        self.button2 = QPushButton("Button 2")
        self.layout.addWidget(self.button2)

        self.setLayout(self.layout)

app = QApplication([])
foo = FirstWindow()
foo.show()
sys.exit(app.exec_())
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Code: Alles auswählen

class FirstWindow(QWidget):
    def __init__(self, parent=None):
        super(FirstWindow, self).__init__(parent)
        self.form_widget_buttons = FormWidgetButton(self)
        self.form_widget_lineedit = FormWidgetLineEdit(self)
        layout = QVBoxLayout()
        layout.addWidget(self.form_widget_buttons)
        layout.addWidget(self.form_widget_lineedit)
        self.setLayout(layout)
Du brauchst für Layouts nicht jedesmal eine Membervariable anlegen, wenn Du das Layout nur im Konstruktor benutzt. Das QWidget hat sowieso schon Properties dafür, insbesondere eine Methode layout(), die Du mit einer Membervariablen self.layout überdecken würdest: http://doc.qt.io/qt-4.8/qwidget.html#layout
Es ist auch unnötig parent immer explizit zu übergeben, der parent wird von Qt selbst gesetzt, wenn Du ein Widget oder ein Layout zu einem parent hinzufügst.

Du kannst Deine GUI-Komponenten auch von einem Layout anstatt von QWidget ableiten:

Code: Alles auswählen

from PyQt4.QtCore import *
from PyQt4.QtGui  import *
 
import sys
 
class FirstWindow(QWidget):
    def __init__(self):
        super(FirstWindow, self).__init__()
        self.form_widget_buttons = FormWidgetButton()
        self.form_widget_lineedit = FormWidgetLineEdit()
        layout = QVBoxLayout()
        layout.addLayout(self.form_widget_buttons)
        layout.addLayout(self.form_widget_lineedit)
        self.setLayout(layout)
 
class FormWidgetLineEdit(QVBoxLayout):
    def __init__(self):        
        super(FormWidgetLineEdit, self).__init__()
        self.lineEdit = QLineEdit()
        self.addWidget(self.lineEdit)
        self.lineEdit2 = QLineEdit()
        self.addWidget(self.lineEdit2)
       
class FormWidgetButton(QVBoxLayout):
    def __init__(self):        
        super(FormWidgetButton, self).__init__()
        self.button1 = QPushButton("Button 1")
        self.addWidget(self.button1)
        self.button2 = QPushButton("Button 2")
        self.addWidget(self.button2)
 
app = QApplication([])
foo = FirstWindow()
foo.show()
sys.exit(app.exec_())
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@MagBen: Besten Dank. Eine Frage: Du hast gesagt, dass man die GUI-Komponenten auch vom Layout ableiten kann, anstatt vom QWidget, richtig? Damit ich das auch richtig lerne. Welche Vor- und Nachteile habe ich, wenn ich vom QWidgets ableite, anstatt vom Layout oder andersrum? Könnte es irgendwann Schwierigkeiten geben?

Und nur zur Kontrolle. In meinem Fall werden in der FirstWindow()-Klasse die Klassen FormWidgetButton() und FormWidgetLineEdit() zum Inhalt von layout.addWidge(). Und da (wie du es bereits erklärt hast) die layout()-Methode sozusagen im QWidget bereits eingebettet ist brauche ich die Parents (hier: self) nicht an die beiden Klassen zu übergeben, weil QT hier merkt, dass die beiden Klassen zum Inhalt vom Layout gesetzt wurden, und QT deshalb Parent selbst setzt. Ich hoffe, dass ich mich richtig und verständlich ausgedrückt 8)
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Sophus: Vom Widget sollte man immer dann ableiten, wenn man die Funktionalität des Widgets erweitern bzw an seine Bedürfnisse anpassen möchte. Ein Layout ist immer eine Ansammlung von Widgets.

Wenn du z.B. an mehreren Stellen die Button-Kombination "Weiter", "Zurück", "Abbrechen" benötigst, dann könntest du dafür von einem horizontalen Layout ableiten und dieses für die gewünschten Fenster / Ansichten einsetzen.

Von einem Widget könnte man hingegen ableiten, wenn es sich z.B. um ein Eingabefeld für ein Passwort handeln soll. Das wäre dann `QLineEdit` als Basisklasse. In dessen `__init__()`-Methode würde man das Textfeld so vorkonfigurieren, dass alle eingegebenen Zeichen als runde schwarze Punkte erscheinen, oder was auch immer.

Kurzum: In der Fragestellung kann es eigentlich nicht um eine Abwägung von Vor- und Nachteilen gehen. Vielmehr solltest du erkennen, wann du in einer Situation bist, wo ein Layout benötigt wird und wann du wiederum auf einem Widget arbeiten willst. Dies habe ich ja mit den beiden vorherigen Beispielen (hoffentlich verständlich) erläutert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@MagBen: Bei deinen letzten beiden Klassen handelt es sich IMHO nicht um Widgets, sondern um Layouts. Ich halte deine Ausführungen an der Stelle für irreführend. Ein Widget kann zwar seinerseits ein Layout mit "Unter-Widgets" haben. Aber das Layout dient lediglich dazu, die Anordnung der "Einzelteile" festzulegen. Ein Layout sollte *nicht* für Funktionalität zuständig sein, die über die Anordungslogik hinausgeht. Das Setzen von Farben, Textinhalt und das Definieren von wie auch immer geartetem Verhalten gehört immer ins Widget. Hier sollte man deshalb auch eine klare Trennung zwischen Layout und Widget vollziehen und eben nicht soweit gehen, dass man sagt, dass ein Widget ja manchmal auch irgendwie ein Layout wäre.

EDIT: Genau genommen sprichst du ja von "GUI-Komponenten". Dem würde ich sogar zustimmen, sofern man den Begriff so definiert, dass eine Komponente sozusagen ein abstrakter Begriff ist, dessen konkrete Ausprägung entweder aus einem Widget oder einem Layout bestehen kann. Mag sein, dass ich dich hier missverstanden habe. Nichtsdestotrotz war mein Eindruck, dass Sophus hierdurch fälschlicherweise dachte, man könne Layout und Widget mehr oder weniger gleichwertig behandeln.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@snafu: Besten Dank.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Sophus hat geschrieben:Eine Frage: Du hast gesagt, dass man die GUI-Komponenten auch vom Layout ableiten kann, anstatt vom QWidget, richtig? Damit ich das auch richtig lerne. Welche Vor- und Nachteile habe ich, wenn ich vom QWidgets ableite, anstatt vom Layout oder andersrum? Könnte es irgendwann Schwierigkeiten geben?
Zähl die Codezeilen. Mit von QWidget abgeleiteten Klassen hast Du noch eine extra Verpackungsschicht drumherum, bei vom Layout abgeleitete Klassen ist es nur eine Verpackung. Das ist auch der Grund warum ich die ganzen parent Variablen weglassen würde, es bleibt dann zum Schluss nur noch der Code übrig, der wirklich der Anwendung Funktionalität bringt.

Explizites setzen von parent ist eigentlich nur notwendig, wenn man während der Laufzeit GUI-Komponenten von einem parent Widget entfernen will und woanders weiterbenutzen möchte.
Sophus hat geschrieben:Könnte es irgendwann Schwierigkeiten geben?
Nein, solltest Du die von einem Layout abgeleitete GUI-Komponente als QWidget mal brauchen, dann steckst Du sie einfach in ein QWidget mit der Methode setLayout()
snafu hat geschrieben:Bei deinen letzten beiden Klassen handelt es sich IMHO nicht um Widgets, sondern um Layouts.
Deshalb habe ich sie im Text auch als GUI-Komponenten bezeichnet. Die Klassennamen habe ich stehengelassen, da ich gerne möglichst viel vom Originalcode beibehalte, wenn ich Verbesserungsvorschläge mache. In einer richtigen Anwendung würde ich aber weder Widget noch Layout in den Namen packen, es fängt ja auch nicht jede Stringvariable mit str an oder jede Integer mit i, sondern z.B. sowas wie AddressEditor, wenn alle Eingabefelder zusammen die Eingabe einer Adresse erlauben (egal ob auf Widget oder Layout).
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute,

irgendwie scheint mir das modulare Arbeiten mit den *.ui-Dateien nicht ganz zu funktionieren.

Wichtige Informationen: Dateien für das Beispiel-Projekt.

- push_button.ui
- text_edit.ui
- ui.qrc
- ui_rc.py

Für diejenigen, die das gesamte Beispiel in einem Rutsch laden wollen, hier die *.zip-Datei.

Szenario:
Nun, ich habe hier drei Klassen, einmal Combine_Window (in main_project.py), PushButton_Window (in frm_push_button_window.py) und TextEdit_Window (in frm_text_edit_window). In der Combine_Window()-Klasse werden die letzten beiden Klassen instanziiert. Anschließend werden die instanziierten Klassen in ein horizontales Layout gesetzt. In den Klassen PushButton_Window und TextEdit_Window werden jeweilige *ui-Dateien aus der Ressourcen-Dateien geladen. Sobald ich das Beispiel ausführe, und die Combine_Window()-Klasse starte, bekomme ich eine Fehlermeldung - Siehe am Ende des Beitrages.

main_project.py

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding:utf-8 -*-

FILE_NAME = "main_project.py"

import os
import sys
import time


from PyQt4.QtGui import QApplication, QVBoxLayout, QWidget

from frm_push_button_window import PushButton_Window
from frm_text_edit_window import TextEdit_Window
import ui_rc
 
class Combine_Window(QWidget):
    def __init__(self):
        super(Combine_Window, self).__init__()

        self.form_widget_buttons = PushButton_Window(self)
        self.form_widget_textedit = TextEdit_Window(self)
        layout = QVBoxLayout()
        layout.addLayout(self.form_widget_buttons)
        layout.addLayout(self.form_widget_textedit)
        self.setLayout(layout)

app = QApplication([])
foo = Combine_Window()
foo.show()
sys.exit(app.exec_())
frm_push_button_window.py

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding:utf-8 -*-

FILE_NAME = "frm_push_button_window.py"

import os
import sys

from PyQt4.QtCore import Qt, QFile
from PyQt4.uic import loadUi
from PyQt4.QtGui import QWidget


BASE_PATH = os.path.dirname(os.path.abspath(__file__))

class PushButton_Window(QWidget):
    def __init__(self, parent):

        QWidget.__init__(self, parent)

        UI_PATH = QFile(":/ui_file/push_button.ui")

        try:
            UI_PATH.open(QFile.ReadOnly)
            self.ui_create_user = loadUi(UI_PATH, self)
            UI_PATH.close()
            print "STATUS [OK]  (", FILE_NAME, "): GUI is loaded from PyQt4"
        except Exception as ex:
            print "STATUS [FAILED]  (", FILE_NAME, "):", ex
        except:
            print "STATUS [FAILED]  (", FILE_NAME, "): Unexpected error:", sys.exc_info()[0]
            raise


    def closeEvent(self, event):
        pass
frm_text_edit_window.py

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding:utf-8 -*-

FILE_NAME = "frm_push_button_window.py"

import os
import sys

from PyQt4.QtCore import Qt, QFile
from PyQt4.uic import loadUi
from PyQt4.QtGui import QWidget

BASE_PATH = os.path.dirname(os.path.abspath(__file__))

class TextEdit_Window(QWidget):
    def __init__(self, parent):

        QWidget.__init__(self, parent)

        UI_PATH = QFile(":/ui_file/text_edit.ui")

        try:
            UI_PATH.open(QFile.ReadOnly)
            self.ui_create_user = loadUi(UI_PATH, self)
            UI_PATH.close()
            print "STATUS [OK]  (", FILE_NAME, "): GUI is loaded from PyQt4"
        except Exception as ex:
            print "STATUS [FAILED]  (", FILE_NAME, "):", ex
        except:
            print "STATUS [FAILED]  (", FILE_NAME, "): Unexpected error:", sys.exc_info()[0]
            raise


    def closeEvent(self, event):
        pass
Fehlermeldung
Traceback (most recent call last):
File "D:/Dan/Python/xarphus/test_project/main_project.py", line 29, in <module>
foo = FirstWindow()
File "D:/Dan/Python/xarphus/test_project/main_project.py", line 24, in __init__
layout.addLayout(self.form_widget_buttons)
TypeError: QBoxLayout.addLayout(QLayout, int stretch=0): argument 1 has unexpected type 'PushButton_Window'
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Sophus:
Steht doch in der Fehlermeldung: addLayout erwartet einen Typen QLayout, das sind Deine Widgets aber nicht.

Deine Fehlerbehandlung in den Widgetklassen ist unsinnig - Du fängst alle Fehler, um sie per print auszugeben, sorgst aber nicht dafür, dass das Programm nach Fehler noch in einem gültigen Zustand ist. Dann brauchst Du die Fehlerbehandlung nicht, da unbehandelte Fehler ja schon ausgebenen werden und Du damit "debuggen" kannst.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: zusätzlich zu dem was jerch schon zu Deinem Code gesagt hat, hier noch ein paar Anmerkungen:
- nicht jede Python-Datei braucht eine Shebang-Zeile, sondern nur solche, die auch tatsächlich zum Ausführen gedacht sind
- FILE_NAME selbst zu definieren ist überflüssig, weil der Dateiname schon in __file__ steht.
- ach __file__ kennst Du schon, aber BASE_PATH wird nirgends benutzt, kann also weg
- UI_PATH ist keine Konstante, sollte also auch nicht wie eine geschrieben werden
- für log-Ausgaben gibt es das Modul logging, das Du statt Deiner print benutzen solltest
- was ist an einer allgemeinen Exception erwartet, erwartest Du in Deinem Programm etwa NameErrors?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@jerch: Wenn ich dich richtig verstanden habe, dann meinst du, ich solle an statt die addLayout()-Methode die addWidget()-Methode benutzen?

@Sirius3: Ich werde die Bemerkungen berücksichtigen.

Vielen Dank euch.
Antworten