Seite 1 von 1
matplotlib
Verfasst: Sonntag 19. Dezember 2010, 21:12
von mushroom
Hallo,
nach meinen ersten Versuchen mit Python und der Qt Gui bin ich mit meinem Projekt schon etwas vorwärts gekommen. Nun hatte ich vor aus einer Datei einen Datensatz in meinem GUI (ein QtDialog) mittels matplotlib graphisch darzustellen. Aus verschiedenen Quellen habe ich beispielhaft folgendes:
Code: Alles auswählen
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 14 13:28:06 2010
@author: Markus
"""
# for command-line arguments
import sys
#Python Qt4 bindings for GUI objects
from PyQt4 import QtCore, QtGui
#GUI
from test import Ui_Dialog
#matplolib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MyDialog(QtGui.QMainWindow, Ui_Dialog):
def __init__(self):
super(MyDialog, self).__init__()
self.plot = Freq()
self.setCentralWidget(self.plot)
# self.lineEdit.setText('blub')
class Freq(QtGui.QWidget):
def __init__(self, *args):
QtGui.QWidget.__init__(self, *args)
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
self.ax.plot(range(4))
self.ax.grid()
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myDialog = MyDialog()
myDialog.show()
sys.exit(app.exec_())
Das GUI ist hier:
http://paste.pocoo.org/show/307111/. Obiges Beispiel funktioniert soweit erstmal. Nun ist mein Problem bei Verwendung der GUI, wenn ich
in
ändere, es nicht mehr funktioniert. Habe in das GUI deswegen mit dem QTDesigner direkt ein MatplotlibWidget eingefügt. Nur habe ich es nicht geschafft darauf zuzugreifen. Was muß ich tun?
Wo ich gerade bei Grafiken bin. Habe später noch vor 3D-Grafiken direkt im Dialog einzubinden. Die Grafik soll interaktiv sein, also dargestelltes Modell dreh- und zoombar sein. Dazu habe ich mir verschiedene Pakete schonmal angeschaut: VPython, VTK und Maya. Von der Bedienung her scheint mir ersteres sehr einfach zu sein. Allerding habe ich keine Möglichkeit gefunden, es direkt in die GUI einzubinden. Bei Maya scheint dies möglich zu sein, sieht mir aber ziemlich kompliziert aus. Habt ihr da Empfehlungen?
Grüße
Markus
Re: matplotlib
Verfasst: Sonntag 19. Dezember 2010, 23:23
von lunar
@mushroom: Was Du zuerst tun musst, ist richtig fragen. „Funktioniert nicht“ ist keine sinnvolle Fehlerbeschreibung. Erkläre also bitte, was genau passiert und welche Fehlermeldungen dabei auftreten. Zeige auch bitte in Zukunft die vom Designer erstellte Datei (Endung ".ui") und nicht das, was der UI-Compiler daraus macht.
Sieht der Quelltext tatsächlich so wie gezeigt aus, dann kannst Du innerhalb von MyDialog einfach mit "self.mplwidget" auf das Steuerelement von "matplotlib" zugreifen. Falls das nicht klappt, dann zeige bitte die vollständige Fehlermeldung.
Re: matplotlib
Verfasst: Montag 20. Dezember 2010, 11:27
von mushroom
Hallo lunar,
sorry, hatte mich da gestern wohl schon etwas zu lange mit dem problem beschäftigt. Hier zunächst erstmal die ui-Datei:
http://paste.pocoo.org/show/307301/.
Das Beispiel oben funktioniert nun erstmal dahingehend, daß ein Fesnter erzeugt wird und entprechend auch geplottet wird. Wenn ich nun aber dazu übergehe und meine GUI test.ui bzw. test.py verwende unter Abänderung auf
erhalte ich als Fehler:
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 45, in <module>
myDialog = MyDialog()
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 27, in __init__
self.setCentralWidget(self.plot)
AttributeError: 'MyDialog' object has no attribute 'setCentralWidget'
Auskommentieren von
lässt den Fehler entsprechend verschwinden und wird dann aber nur ein leeres Fenster erzeugt. Kommentiere ich nun die Zeile
wieder "ein", erhalte ich die Fehlermeldung
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 46, in <module>
myDialog = MyDialog()
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 30, in __init__
self.lineEdit.setText('blub')
AttributeError: 'MyDialog' object has no attribute 'lineEdit'
Entsprechend bewirkt ein Hinzufügen der Zeile
nur
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 46, in <module>
myDialog = MyDialog()
File "C:\Users\Markus\Documents\Python\projects\test\main.py", line 28, in __init__
self.mplwidget.grid()
AttributeError: 'MyDialog' object has no attribute 'mplwidget'
Bei beiden letzten Änderungen verstehe ich nicht, warum es nicht funktioniert.
Grüße
Markus
Re: matplotlib
Verfasst: Montag 20. Dezember 2010, 14:06
von Rekrul
QDialog hat kein setCentralWidget().
Re: matplotlib
Verfasst: Montag 20. Dezember 2010, 18:59
von lunar
Soll heißen, wenn Du im Designer ein "QMainWindow" entwirfst, dann musst Du das auch in eine Unterklasse von "QMainWindow" einfügen. Du kannst nicht wahlfrei verschiedene Typen mischen, und dann erwarten, dass die Oberfläche trotzdem korrekt funktioniert.
Am vom Designer erzeugten Quelltext sollten im Übrigen auch keine Änderungen durchgeführt werden, die Warnung am Anfang des Quelltexts ist nicht zum Spaß da.
Re: matplotlib
Verfasst: Montag 20. Dezember 2010, 19:10
von mushroom
Genau das ist ja das Problem. Ich habe ja im QtDesigner ein QDialog entworfen und wollte dieses GUI nun verwenden, indem ich
in
geändert habe. Zugriff auf das MatplotlibWidget sollte dann, wie du schon geschrieben hast über self.mplwidget erfolgen und das eben funktioniert leider nicht.
Re: matplotlib
Verfasst: Montag 20. Dezember 2010, 19:29
von lunar
Hast Du die im Designer erstellte Datei auch erneut kompiliert?
Re: matplotlib
Verfasst: Dienstag 21. Dezember 2010, 17:44
von mushroom
Hallo lunar,
ja, die Datei ist neu kompiliert, funktioniert leider imer noch nicht mit dem Code wie ich ihn habe. Allerdings habe ich jetzt zumindest durch Ergänzen des Codes in der Methode __init__(self) (Klasse MyDialog) mit
wieder Zugriff auf
Bleibt allerdings weiter das Problem, daß in der Grafik nichts geändert wird. Mit folgendem Code
Code: Alles auswählen
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 14 13:28:06 2010
@author: Markus
"""
# for command-line arguments
import sys
#Python Qt4 bindings for GUI objects
from PyQt4 import QtCore, QtGui
#GUI
from test import Ui_Dialog
#matplolib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
#class MyDialog(QtGui.QMainWindow, Ui_Dialog):
class MyDialog(QtGui.QDialog, Ui_Dialog):
def __init__(self):
super(MyDialog, self).__init__()
# self.setCentralWidget(self.plot)
self.setupUi(self)
self.mplwidget.plot = Freq()
self.lineEdit.setText('blub')
self.mplwidget.grid()
class Freq(QtGui.QWidget):
def __init__(self, *args):
QtGui.QWidget.__init__(self, *args)
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
self.ax.plot(range(40))
self.ax.grid()
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myDialog = MyDialog()
myDialog.show()
sys.exit(app.exec_())
erhalte ich die Fehlermeldung
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\Markus\Pythonprojekte\Test\main.py", line 50, in <module>
myDialog = MyDialog()
File "C:\Users\Markus\Pythonprojekte\Test\main.py", line 34, in __init__
self.mplwidget.grid()
AttributeError: 'MatplotlibWidget' object has no attribute 'grid'
Re: matplotlib
Verfasst: Dienstag 21. Dezember 2010, 18:16
von lunar
Woher kommt "MatplotlibWidget" denn überhaupt? Denn ganz offensichtlich entsprechen die Attribute dieses Objekts nicht Deinen Erwartungen. Das wäre jetzt folglich der Zeitpunkt, an dem ein Blick in die Dokumentation obligatorisch ist.
Re: matplotlib
Verfasst: Sonntag 2. Januar 2011, 18:33
von mushroom
So, mal wieder mit dem Problem nach den Feiertagen beschäftigt.
Also die Klasse MatplotlibWidget ist ein Element des QtGUI und wird über mplwidget angesprochen. Hier die von pyuic4 erstellte Datei
http://paste.pocoo.org/show/313188/ bzw. das ui selbst
http://paste.pocoo.org/show/313193/
Eine Suche nach dem Modul matplotlibwidget brachte leider keinen Erfolg, finde weder über google etwas brauchbares noch auf der Webseite von matplotlib oder der QT Reference.
Re: matplotlib
Verfasst: Sonntag 2. Januar 2011, 18:59
von mushroom
Hmm, wie es der Zufall so will, doch etwas gefunden:
http://paste.pocoo.org/show/313201/
Code: Alles auswählen
# -*- coding: utf-8 -*-
#
# Copyright © 2009 Pierre Raybaut
# Licensed under the terms of the MIT License
"""
MatplotlibWidget
================
Example of matplotlib widget for PyQt4
Copyright © 2009 Pierre Raybaut
This software is licensed under the terms of the MIT License
Derived from 'embedding_in_pyqt4.py':
Copyright © 2005 Florent Rougon, 2006 Darren Dale
"""
__version__ = "1.0.1"
from PyQt4.QtGui import QSizePolicy, QIcon
from PyQt4.QtCore import QSize
import os.path as osp
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
rcParams['font.size'] = 9
def get_icon(name):
"""Return Matplotlib icon *name*"""
return QIcon(osp.join(rcParams['datapath'], 'images', name))
class MatplotlibWidget(Canvas):
"""
MatplotlibWidget inherits PyQt4.QtGui.QWidget
and matplotlib.backend_bases.FigureCanvasBase
Options: option_name (default_value)
-------
parent (None): parent widget
title (''): figure title
xlabel (''): X-axis label
ylabel (''): Y-axis label
xlim (None): X-axis limits ([min, max])
ylim (None): Y-axis limits ([min, max])
xscale ('linear'): X-axis scale
yscale ('linear'): Y-axis scale
width (4): width in inches
height (3): height in inches
dpi (100): resolution in dpi
hold (False): if False, figure will be cleared each time plot is called
Widget attributes:
-----------------
figure: instance of matplotlib.figure.Figure
axes: figure axes
Example:
-------
self.widget = MatplotlibWidget(self, yscale='log', hold=True)
from numpy import linspace
x = linspace(-10, 10)
self.widget.axes.plot(x, x**2)
self.wdiget.axes.plot(x, x**3)
"""
def __init__(self, parent=None, title='', xlabel='', ylabel='',
xlim=None, ylim=None, xscale='linear', yscale='linear',
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)
if xscale is not None:
self.axes.set_xscale(xscale)
if yscale is not None:
self.axes.set_yscale(yscale)
if xlim is not None:
self.axes.set_xlim(*xlim)
if ylim is not None:
self.axes.set_ylim(*ylim)
self.axes.hold(hold)
Canvas.__init__(self, self.figure)
self.setParent(parent)
Canvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QSize(w, h)
def minimumSizeHint(self):
return QSize(10, 10)
#===============================================================================
# Example
#===============================================================================
if __name__ == '__main__':
import sys
from PyQt4.QtGui import QMainWindow, QApplication
from numpy import linspace
class ApplicationWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.mplwidget = MatplotlibWidget(self, title='Example',
xlabel='Linear scale',
ylabel='Log scale',
hold=True, yscale='log')
self.mplwidget.setFocus()
self.setCentralWidget(self.mplwidget)
self.plot(self.mplwidget.axes)
def plot(self, axes):
x = linspace(-10, 10)
axes.plot(x, x**2)
axes.plot(x, x**3)
app = QApplication(sys.argv)
win = ApplicationWindow()
win.show()
sys.exit(app.exec_())
Wende ich das gegebene Beispiel in meiner Datei
http://paste.pocoo.org/show/313231/ an, so wird auch das dem Code mehr oder weniger Erwartete dargestellt. Es wird nicht in das vorhandene Widget gezeichnet sondern einfach ein neues Widget erzeugt und auf das vorhandene überlagert.