Matplotlib Graph in Main Window einbinden

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

Ich versuche gerade eine Klasse matplotlibWidget zu programmieren. Allerdings gelingt es mir nicht, innerhalb der Klasse Ui_MainWindow Instanzattribute zu deklarieren, z.b wenn ich ein Label definieren will.

In diesem Skript ist die Klasse definiert:

Code: Alles auswählen

__version__ = "1.0.0"

from PyQt4.QtGui import QSizePolicy
from PyQt4.QtCore import QSize

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure

class matplotlibWidget(Canvas):
 
    def __init__(self,parent=None,title='',xlabel='',ylabel='',
                 xlim=None,ylim=None,
                 width=4,height=3,dpi=100,hold=False):
                     
        self.figure = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.figure.add_subplot(111)
        self.axes.set_title(title)
        self.axes.set_xlabel(xlabel)
        self.axes.set_ylabel(ylabel)

        Canvas.__init__(self, self.figure)
        self.setParent(parent)

        Canvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
        Canvas.updateGeometry(self)
Hier möchte ich Attribute ändern:

Code: Alles auswählen

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.mplwidget = matplotlibWidget(self.centralwidget)
        self.mplwidget.setGeometry(QtCore.QRect(150, 20, 400, 300))
        self.mplwidget.setObjectName(_fromUtf8("mplwidget"))
        '''Hier ist das Problem. X-LABEL wird im Graph nicht angezeigt'''
        self.mplwidget.xlabel='X-LABEL'
        '''-----'''
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))

from class_example import matplotlibWidget
BlackJack

@qwert2: Da wo Du etwas ändern willst steht normalerweise ein Kommentar ganz oben das man an dem Quelltext nichts ändern sollte. Der ist ja generiert und wird folglich überschrieben wenn man etwas an der zugrundeliegenden *.ui-Datei ändert und den Quelltext daraus dann neu generiert.

Den generierten Quelltext bindet man üblicherweise in einem selbst geschriebenen Modul ein in dem man eine Klasse schreibt die von der generierten Klasse erbt oder diese kapselt. An der Stelle kann man dann auch manuell noch Widgets in die GUI einbauen.

Insgesamt sollte man aber auch vom generieren des Quelltextes weg kommen und direkt die *.ui-Datei zur Laufzeit laden. Damit spart man sich den unnötigen Zwischenschritt über die Quelltextgenerierung.
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

Das verstehe ich nicht ganz. Wieso sollte ich am Quelltext nichts ändern dürfen? Ich habe den Quelltext aus einer .ui Datei generiert und hatte eigentlich vor, ein paar Änderungen daran vorzunehmen (Ich kann ja z.B auch die Zeile self.mplwidget.setGeometry(QtCore.QRect(150, 20, 400, 300)) z.B zu self.mplwidget.setGeometry(QtCore.QRect(150, 20, 400, 500)) ändern). Es gibt bei manchen PQt Versionen kein Matplotlibwidget. Deswegen wollte ich ein eigenes programmieren, allerdings möchte ich nicht auf die ganzen anderen Wiget-Klassen, die vom Designer erzeugt werden verzichten. Ich sollte erwähnen, dass ich nicht wirklich mit den Details von Python vertraut bin und in manchen Angelegenheiten total ahnungslos bin.

Ich rufe das MainWindow in einem seperaten Skript auf:

Code: Alles auswählen

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

from Window import Ui_MainWindow

from PyQt4 import QtCore, QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s
try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
            QtGui.QMainWindow.__init__(self, parent, f)
            self.setupUi(self)

application = QApplication(sys.argv)  
frame=MainWindow()

frame.show()
sys.exit(application.exec_())
auch hier kann ich nichts am Wiget ändern z.B wenn ich schreibe:
frame.mplwidget.xlabel='X-Label'
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Dein Problem hat nichts damit zu tun, dass Du generierten Code änderst. Generierten Code zu ändern ist ein Problem für sich.

Die Klasse matplotlibWidget hat kein Attribut "xlabel".
In der Zeile
self.mplwidget.xlabel='X-LABEL'
wird also nicht das vorhandene xlabel geändert, sondern ein neues xlabel Attribut erzeugt, das aber niergendwo sonst benutzt wird.

Die Klasse matplotlibWidget hat jedoch eine Membervariable axes und darüber solltest Du den x-Label ändern können:
self.mplwidget.axes.set_xlabel('X-LABEL')
a fool with a tool is still a fool, www.magben.de, YouTube
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

aber im Konstruktor von meiner Klasse steht doch xlabel
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

wenn ich

Code: Alles auswählen

self.mplwidget = matplotlibWidget(self.centralwidget,xlabel='HOHO')
schreibe im MainWindow, dann funktioniert es.
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

@MagBen
Sorry, du hast recht, das wird ja anders übergeben
BlackJack

@qwert2: Der Quelltext ist ja generiert und wenn Du im Designer an der *.ui-Datei etwas änderst und dann den Quelltext neu generierst, dann werden damit alle Änderungen die Du vorher an dem generierten Quelltext gemacht hast überschrieben. Darum ist da ja auch eine Warnung in dem generierten Quelltext:

Code: Alles auswählen

# Form implementation generated from reading ui file 'test.ui'
#
# Created: Fri Mar 13 12:53:08 2015
#      by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
Aber wie gesagt ist der Zwischenschritt über eine Python-Quelltextdatei sowieso veraltet. Man kann die *.ui-Datei mit Hilfe des `PyQt4.uic`-Moduls zur Laufzeit laden und entweder das dabei erzeugte Widget-Exemplar dann als eigenständiges Objekt verwenden oder eine Klasse von gleichen Widget-Typ schreiben und den ganzen Inhalt des geladenen Widgets dort einfügen lassen.

Damit spart man sich auch das Problem das die Quelltextdateien die man unter Versionskontrolle stellt nicht ohne einen zusätzlichen Build-Schritt benutzbar sind. Alternativ müsste man sonst ja generierten Quelltext committen, was eher unschön ist.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

BlackJack hat geschrieben:Aber wie gesagt ist der Zwischenschritt über eine Python-Quelltextdatei sowieso veraltet. Man kann die *.ui-Datei mit Hilfe des `PyQt4.uic`-Moduls zur Laufzeit laden und entweder das dabei erzeugte Widget-Exemplar dann als eigenständiges Objekt verwenden oder eine Klasse von gleichen Widget-Typ schreiben und den ganzen Inhalt des geladenen Widgets dort einfügen lassen.

Damit spart man sich auch das Problem das die Quelltextdateien die man unter Versionskontrolle stellt nicht ohne einen zusätzlichen Build-Schritt benutzbar sind. Alternativ müsste man sonst ja generierten Quelltext committen, was eher unschön ist.
Bezug zum X-Label?
a fool with a tool is still a fool, www.magben.de, YouTube
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

" Der Quelltext ist ja generiert und wenn Du im Designer an der *.ui-Datei etwas änderst und dann den Quelltext neu generierst, dann werden damit alle Änderungen die Du vorher an dem generierten Quelltext gemacht hast überschrieben. Darum ist da ja auch eine Warnung in dem generierten Quelltext:"

Ja das war mir schon klar. Ich habe den Quelltext auch nur einmalig generiert, ändere ihn und lade ihn ins Modul. Die ui-Datei verwende ich ja dann nicht mehr
BlackJack

@MagBen: Wenn das nicht in generiertem Quelltext gestanden hätte, dann hätte ich mir den durchgelesen und die Frage beantworten können. Wenn Dir meine Antworten nicht passen dann ignorier sie doch einfach. Oder geh ins Heise-Forum und troll da rum. ;-)
qwert2
User
Beiträge: 18
Registriert: Donnerstag 8. Januar 2015, 12:53

@BlackJack
Ist ja kein Grund zickig zu werden. Das Forum ist nun mal da zum freien Gedankenaustausch (wobei ich diesbezüglich zugegebenermaßen wenig beizutragen habe) und unpassende/falsche Antworten dürfen ja auch als solche benannt werden. Ist ja nicht böse gemeint. Ich danke euch beiden jedenfalls für eure hilfreichen Vorschläge.
BlackJack

@qwert2: Das Zitat mit einer schnippischen, rethorischen Frage darunter ist dummes herumtrollen. Das darf man doch noch als solches benennen. Vor allem war *der* Kommentar ja eher dazu gedacht den Gedankenaustausch einzuschränken, denn die Frage dahinter ist ja im Grunde warum ich denn ein anderes Problem mit dem Code anspreche als das mit der Beschriftung der X-Achse. Na weil ich es kann, weil ich es wichtig fand, und weil das der Grund war warum ich gar nicht erst bis zu dem Code gelesen habe wo das Problem mit der Beschriftung war.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

@BlackJack: Wenn Du meinen Hinweis, dass Du Offtopic bist, als "dummes herumtrollen" aufgenommen hast, dann bitte ich um Entschuldigung.
a fool with a tool is still a fool, www.magben.de, YouTube
Antworten