2016-04-06 6 views
9

Ich habe nach einem Arbeitsbeispiel gesucht, wie man ein Matplotlib-Diagramm in pyside einbetten kann, das mit dem QT-Designer erstellt wird, während die Logik in einer separaten Datei bleibt. Ich weiß, dass es zahlreiche Beispiele im Web gibt, aber keiner von ihnen verwendet den QT-Designer und erstellt dann eine separate Datei, um die Logik hinzuzufügen, in der das Matplitlib-Plot einem Widget hinzugefügt wird. Ich fand ein Beispiel, das 'fast' funktioniert http://blog.rcnelson.com/building-a-matplotlib-gui-with-qt-designer-part-1/, aber in meiner Version ist es nicht möglich, "Ändern Sie die layoutName Eigenschaft von" verticalLayout "zu" mplvl "".Matplotlib in Pyside mit Qt Designer (PySide)

So habe ich die folgenden spezifischen Fragen: Ich bin nicht klar, in welches Element kann dieses Grundstück in Pyside Qt Designer eingebettet werden. Ist es ein einfaches "Widget" (da es kein matplotlib-Widget in pyside gibt). Wenn ja, wie kann ich dann das Diagramm zu diesem Widget hinzufügen? Oder muss ich eine 'FigureCanvas' mit Qt Designer erstellen? Ist das überhaupt möglich? Wenn das so ist, wie?

Hier ist das einfachste mögliche Design, das ich mit dem Pysid-Qt-Designer beim Einbetten eines Widgets machen kann (ist das korrekt?). Wie kann ich jetzt ein Matplotlib-Plot hinzufügen?

Wie in einer der Antworten vorgeschlagen, habe ich jetzt die Qwidget zu MyStaticMplCanvas gefördert und den Namen von Qwidget zu mplvl bearbeitet.

automatisch mit pyside Qt Designer erstellte Datei und kompiliert mit pyside-uic ui.ui -o ui.py -x

ui.py wie folgt aussieht:

# -*- coding: utf-8 -*- 

# Form implementation generated from reading ui file 'gui.ui' 
# 
# Created: Wed Apr 20 14:00:02 2016 
#  by: pyside-uic 0.2.15 running on PySide 1.2.2 
# 
# WARNING! All changes made in this file will be lost! 

from PySide import QtCore, QtGui 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(444, 530) 
     self.centralwidget = QtGui.QWidget(MainWindow) 
     self.centralwidget.setObjectName("centralwidget") 
     self.mplvl = MyStaticMplCanvas(self.centralwidget) 
     self.mplvl.setGeometry(QtCore.QRect(120, 190, 221, 161)) 
     self.mplvl.setObjectName("mplvl") 
     MainWindow.setCentralWidget(self.centralwidget) 
     self.menubar = QtGui.QMenuBar(MainWindow) 
     self.menubar.setGeometry(QtCore.QRect(0, 0, 444, 21)) 
     self.menubar.setObjectName("menubar") 
     MainWindow.setMenuBar(self.menubar) 
     self.statusbar = QtGui.QStatusBar(MainWindow) 
     self.statusbar.setObjectName("statusbar") 
     MainWindow.setStatusBar(self.statusbar) 

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

    def retranslateUi(self, MainWindow): 
     MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) 

from mystaticmplcanvas import MyStaticMplCanvas 

if __name__ == "__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    MainWindow = QtGui.QMainWindow() 
    ui = Ui_MainWindow() 
    ui.setupUi(MainWindow) 
    MainWindow.show() 
    sys.exit(app.exec_()) 

wie kann ich jetzt Hinzufügen eines Plots in das mplvl-Objekt aus einer separaten .py-Datei?

+2

Sie nicht 'PyQt' und' PySide' Importe im gleichen Prozess mischen. Ich schlage vor, dass Sie alles aus dem Modul "matplotlib.backends.qt_compat" importieren, wo wir die Unterschiede unterschei- den. – tacaswell

+1

Der Code von pyside wird automatisch von pyside-uic erzeugt, also muss ich irgendwie bleiben. Es sei denn du sagst es ist nicht möglich? – Nickpick

+1

Ich hatte ein ähnliches Problem - obwohl es einige Unterschiede gibt. Bitte überprüfen Sie diesen Beitrag auf stackoverflow: http://stackoverflow.com/questions/36665850/matplotlib-animation-inside-your-own-pyqt4-gui/36669876#36669876 Ich hoffe, es hilft. –

Antwort

7

Ich bin kein Experte in dieser Angelegenheit so ist es nicht der sauberste Weg, dies zu tun sein könnte, aber hier einige Arbeits Code zum Einstieg:

  • Ich denke, der einfachste Weg, Widgets hinzufügen ist über ein ich habe gerade Ihre Plotter vererben FigureCanvas
  • und sagte QxxxxLayout
  • dann matplotlib mit PySide
zu arbeiten

ui.py:

from PySide import QtCore, QtGui 

class Ui_Form(object): 
    def setupUi(self, Form): 
     Form.setObjectName("Form") 
     Form.resize(533, 497) 
     self.mplvl = QtGui.QWidget(Form) 
     self.mplvl.setGeometry(QtCore.QRect(150, 150, 251, 231)) 
     self.mplvl.setObjectName("mplvl") 
     self.vLayout = QtGui.QVBoxLayout() 
     self.mplvl.setLayout(self.vLayout) 
     self.retranslateUi(Form) 
     QtCore.QMetaObject.connectSlotsByName(Form) 

    def retranslateUi(self, Form): 
     Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8)) 

Dazu müssen Sie nur QtDesigner die Leinwand zu mplvl in hinzufügen

main.py:

import matplotlib 
matplotlib.use('Qt4Agg') 
matplotlib.rcParams['backend.qt4'] = 'PySide' 
from matplotlib.backends.backend_qt4agg import (
    FigureCanvasQTAgg as FigureCanvas, 
    NavigationToolbar2QT as NavigationToolbar) 
from matplotlib.figure import Figure 
from PySide import QtGui, QtCore 
import random 

from weakref import proxy 
from ui import Ui_Form 


class Plotter(FigureCanvas): 
    def __init__(self, parent): 
     ''' plot some random stuff ''' 
     self.parent = proxy(parent) 
     # random data 
     data = [random.random() for i in range(10)] 
     fig = Figure() 
     super(Plotter,self).__init__(fig) 
     # create an axis 
     self.axes = fig.add_subplot(111) 
     # discards the old graph 
     self.axes.hold(False) 
     # plot data 
     self.axes.plot(data, '*-') 

    def binding_plotter_with_ui(self): 
     self.parent.vLayout.insertWidget(1, self) 

if __name__ == "__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    Form = QtGui.QWidget() 
    ui = Ui_Form() 
    ui.setupUi(Form) 
    # plotter logic and binding needs to be added here 
    plotter = Plotter(ui) 
    plotter.binding_plotter_with_ui() 
    plotter2 = Plotter(ui) 
    plotter2.binding_plotter_with_ui() 
    Form.show() 
    sys.exit(app.exec_()) 

Nun, was übrig bleibt, ist wahrscheinlich die FigureCanvas zwicken um es in die richtige Größe und Proportionen zu bringen, sollten Sie in der Lage sein, zu bekommen, was Sie sehen wollen this example oder the other.

Viel Glück!

+0

Zur Klarstellung: Ein Widget muss in ein Layout eingefügt werden. In diesem Fall heißt das Wiedget mplvl und das vertikale Layout vLayout. Danach funktioniert der obige Code. – Nickpick

+0

Das einzige kleine Problem ist, dass die Handlung an der Unterseite ein wenig abgeschnitten ist. Kann man etwas dagegen tun? – Nickpick

+0

Was ich Ihnen rate, ist folgendes: Fügen Sie in QtDesigner einen ersten Bildlaufbereich hinzu, in den Sie ein vertikales Layout einfügen (ersetzen Sie '' mplvl''). Fügen Sie dann die Plots innerhalb dieses Layouts hinzu. Das Größenproblem auf der vertikalen Achse kommt einfach von Ihrer '' self.mplvl.setGeometry (QtCore.QRect (150, 150, 251, 231)) '', die zu klein ist. – Silmathoron

3

Werfen Sie einen Blick auf die matplotlib Beispiel in QT4 Einbetten: http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html

Hier definieren sie ein paar Klassen ein matplotlib Widget in einer QT4 Anwendung Implementierung, zum Beispiel die Klasse MyStaticMplCanvas.Der Trick zur Verwendung dieser Klasse in QT Designer besteht darin, ein Standard-QWidget zu verwenden, mit der rechten Maustaste darauf zu klicken und Promote to ... zu wählen. Geben Sie den Klassennamen MyStaticMplCanvas unter Promoted class name ein, und den Dateinamen, unter dem diese Klasse gefunden wird, unter header file (die Erweiterung .h wird hinzugefügt), aber im Python-Code ignoriert). Klicken Sie auf Add und Promote.

nun nach der Kompilierung von uic der Python-Code sollte wie folgt aussehen:

from PySide import QtCore, QtGui 
class Ui_Form(object): 
    def setupUi(self, Form): 
     ... 
     self.mplvl = MyStaticMplCanvas(Form) 
     ... 

from mystaticmplcanvas import MyStaticMplCanvas 
+1

Das ist definitiv ein Schritt in die richtige Richtung. Das einzige Problem, das ich jetzt habe, ist, dass self.setParent (übergeordnet) einen Fehler gibt: TypeError: Argumente stimmen mit keinem überladenen Aufruf überein: QWidget.setParent (QWidget): Argument 1 hat den unerwarteten Typ 'PySide.QtGui.QWidget' QWidget. setParent (QWidget, Qt.WindowFlags): Argument 1 hat den unerwarteten Typ 'PySide.QtGui.QWidget' – Nickpick

+1

Stellen Sie sicher, dass Sie nur aus PySide und nichts aus PyQt4 importieren. Wahrscheinlich verwendet deine Matplotlib standardmäßig PyQt4. Die ersten Zeilen Ihres Skripts legen das korrekte Backend in Matplotlib fest, wie in der Antwort von Silmathoron. – Rob

+0

Ich habe jetzt die ursprüngliche Frage bearbeitet, um den aktuellen Status der Dinge besser anzuzeigen – Nickpick