Seite 1 von 1

PyQt: Widget im Dialog adressieren

Verfasst: Mittwoch 18. März 2009, 22:29
von schnupp
Hallo,

ich habe ein Dialogfenster (MeinDialog(QtGui.QDialog, Dlg)) und in diesem ein Widget (widgetGrafik) in das ich z.B. ein Rechteck (drawRect) zeichnen möchte per paintEvent.

Wie bringe ich drawRect dazu, dass der Koordinatenursprung im Widget liegt und nicht im Dialog?

Grüße
Frank

Verfasst: Donnerstag 19. März 2009, 00:09
von lunar
Du musst eben in das Widget zeichnen und nicht in den Dialog. Du hast doch jetzt hoffentlich keine ausführlichere Antwort erwartet?

Verfasst: Donnerstag 19. März 2009, 00:53
von schnupp
:roll:

Na, das ist mir schon klar.
Mein paintEvent sieht erst einmal so aus:

Code: Alles auswählen

   def paintEvent(self, event):
      painter = QtGui.QPainter(self)
      painter.setPen(self.pen)
      painter.setBrush(self.brush)
      painter.drawRect(10,10,20,20)
Damit wird natürlich in den Dialog gemalt, da self der Dialog ist.
Dann habe ich mein widgetGrafik, das vorher hier gebaut wird:

Code: Alles auswählen

class MeinDialog(QtGui.QDialog, Dlg):
   def __init__(self):
      QtGui.QDialog.__init__(self)
      self.setupUi(self)
und so definiert wird:

Code: Alles auswählen

        self.widgetGrafik = QtGui.QWidget(Hauptdialog)
        self.widgetGrafik.setGeometry(QtCore.QRect(10, 360, 441, 191))
        self.widgetGrafik.setObjectName("widgetGrafik")
Jetzt würde ich sagen, na gut, dann bau ich soetwas:

Code: Alles auswählen

def paintEvent(self.widgetGrafik, event):
Aber das geht scheinbar nicht so, wie ich mir das vorstelle
:wink:

Verfasst: Donnerstag 19. März 2009, 10:04
von lunar
Du musst dein QWidget mit einem Exemplar einer von QWidget abgeleiteten Klasse ersetzen, und in dieser Klasse dann paintEvent überschreiben. Man kann nicht von "außerhalb" in Widgets zeichnen, zumindest nicht plattformübergreifend.

Verfasst: Donnerstag 19. März 2009, 11:42
von schnupp
Danke! Das werde ich gleich mal probieren...

Verfasst: Donnerstag 19. März 2009, 23:33
von schnupp
Das bekomme ich hin, wenn ich das Widget nicht mit dem QtDesigner erzeuge.
Sollte man denn ggf. nur das Layout bauen und dann im Programm das Widget in das Layout fügen? Macht das Sinn? Zumindest habe ich das schon in zwei Beispielen gesehen...

Grüße
Frank

Verfasst: Donnerstag 19. März 2009, 23:44
von snafu
Ich wüsste nicht, wo das Problem sein soll. Du schreibst die Klasse halt mit in die Datei, die sich um deine Gui kümmert. Falls du das Widget auch in anderen Projekten benötigst, könntest du ja ein Modul ``customized_widgets`` (oder so ähnlich) erstellen, wo dann die Klassen deiner angepassten Widgets definiert sind.

Verfasst: Freitag 20. März 2009, 00:15
von schnupp
Da schaffe ich inzwischen schon. Mein Problem liegt darin, dass ich mit dem Designer ein leeres Widget erzeuge, in das ich zeichnen möchte und jetzt nicht sagen kann, wie ich das richtig einbinde.

Der Designer erzeugt ja sowas:

Code: Alles auswählen

class Ui_Hauptdialog(object):
    def setupUi(self, Hauptdialog):
Im setupUi wird dann u.a. auch mein leeres Widget definiert.

Wenn ich das ohne den Designer erzeugen würde, hätte ich mein Layout und definiere vorher sowas:

Code: Alles auswählen

class MeinWidget(QtGui.QDialog):
   def __init__(self,parent):
      QtGui.QLabel.__init__(self, parent)
      self.parent = parent

   def paintEvent(self, event):
      print "Widget!"
und lege das Widget in das Layout.
Aber über den das setpUi kann ich nicht sagen, wie ich dran komme um das paintEvent zu erzeugen.
Tja, das sind wohl Anfängerprobleme... :wink:

Verfasst: Freitag 20. März 2009, 01:37
von jerch
Du kannst das z.B. über benutzerdefinierte Klassen im QDesigner erreichen (es muß ja nicht gleich ein Modul für den Designer sein).

So gehts:
- Angepaßte Klasse schreiben z.B. CustomPaintWidget(QWidget) in custompaintwidget.py
- Im Designer alles fertig layouten mit der Basisklasse Deines CustomPaintWidgets.
- Rechtsklick auf Dein Hauptwidget --> Benutzerdefinierte Klassen
- Im Dialog die Basisklasse und den Klassennamen setzen, also QWidget und CustomPaintWidget; unter include-Datei darf für Python nur der Modulname erscheinen, hier custompaintwidget
- Zum Schluß Rechtsklick auf das "Platzhalterwidget" --> Als Platzhalter für ben. Klasse --> CustomPaintWidget

Der uic-Loader kann das richtig auflösen, wobei er manchmal Probleme macht, wenn die CustomKlasse in der selben Datei ist wie die MainKlasse (zirkulärer Import etc.)

Grüße Jerch

Addendum:
Solltest Du ein komplexeres Design in Deiner CustomKlasse brauchen, geht das auch wieder über ui-files. Mit diesem "Schachtelprinzip" (Matroschka) kannst Du Dir quasi Deinen eigenen Widgetbaukasten erstellen.
Was ich noch vergessen habe: Du kannst dieses CustomWidget auch in die linke Seitenleiste zu den anderen Widgets ziehen, es erscheint dann unter "Ablage".

Verfasst: Montag 23. März 2009, 09:14
von schnupp
Danke! Damit sollte es jetzt hoffentlich weiter gehen. Zumindest hänge ich nicht mehr an meinem alten Problem... :wink:

Verfasst: Montag 23. März 2009, 19:55
von schnupp
Klasse! Das funktioniert - sogar einfacher als erwartet...