2016-04-06 18 views
9

Ho cercato un esempio funzionante su come incorporare un grafico matplotlib in campagna che viene creato con il progettista QT mantenendo la logica in un file separato. So che ci sono numerosi esempi sul web ma nessuno di questi usa effettivamente la finestra di progettazione QT e quindi crea un file separato per aggiungere la logica in cui la trama matplitlib viene aggiunta a un widget. Ho trovato un esempio che 'quasi' funziona http://blog.rcnelson.com/building-a-matplotlib-gui-with-qt-designer-part-1/ ma ma nella mia versione non è possibile "Cambiare la proprietà layoutName da" verticalLayout "a" mplvl "".Matplotlib in Phare con Qt Designer (PySide)

Quindi ho le seguenti domande specifiche: Non sono chiaro in quale elemento tale trama può essere incorporata in Phare Qt Designer. È un semplice "widget" (dato che non esiste un widget matplotlib disponibile in campagna). In tal caso, come posso quindi aggiungere la trama a quel widget? O devo creare un 'FigureCanvas' con Qt Designer? Ciò è effettivamente possibile? Se é cosi, come?

Ecco il disegno più semplice che posso fare con il progettista Qt di Phare per incorporare un widget (è corretto?). Come posso aggiungere una trama matplotlib su di essa?

Come suggerito in una delle risposte, ho promosso Qwidget a MyStaticMplCanvas e modificato il nome di Qwidget in mplvl.

generato automaticamente file con PySide Qt Designer e compilato con PySide-UIC ui.ui -o ui.py -x

ui.py assomiglia a questo:

# -*- 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_()) 

come posso ora aggiungi una trama nell'oggetto mplvl da un file .py separato?

+2

Non si può mescolare '' PyQt' e PySide' importazioni nello stesso processo. Vi suggerisco di importare tutto dal modulo 'matplotlib.backends.qt_compat' dove spessiamo su quali sono le differenze. – tacaswell

+1

Il codice di campagna viene generato automaticamente da pyside-uic quindi ho bisogno di rimanere in qualche modo. A meno che tu non stia dicendo che non è possibile? – Nickpick

+1

Ho avuto un problema simile, anche se ci sono alcune differenze. Si prega di controllare questo post su StackOverflow: http://stackoverflow.com/questions/36665850/matplotlib-animation-inside-your-own-pyqt4-gui/36669876#36669876 Spero che aiuti. –

risposta

7

Io non sono un esperto di quella materia in modo che potrebbe non essere il modo più pulito di fare questo, ma qui è un codice di lavoro per iniziare:

  • Penso che il modo più semplice per aggiungere i widget è attraverso un QxxxxLayout
  • poi ho appena fatto il tuo Plotter ereditare da FigureCanvas
  • e detto matplotlib di lavorare con PySide

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)) 

Per questo è necessario solo aggiungere la tela per mplvl in QtDesigner

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_()) 

Ora quello che è rimasto è probabilmente di modificare il FigureCanvas per renderlo delle giuste dimensioni e proporzioni, quindi dovresti essere in grado di ottenere quello che vuoi guardando this example o the other.

Buona fortuna!

+0

Per chiarire: un widget deve essere inserito in un layout. In questo caso il wiedget si chiama mplvl e il layout verticale vLayout. Dopo che il codice sopra funzionerà. – Nickpick

+0

L'unico piccolo problema è che la trama è tagliata in basso un po '. C'è qualcosa che può essere fatto al riguardo? – Nickpick

+0

Quello che ti consiglio di fare è il seguente: all'interno di QtDesigner, aggiungi una prima area di scroll in cui metti un layout verticale (sostituisci '' mplvl''). Quindi aggiungi i grafici all'interno di questo layout. Il problema delle dimensioni sull'asse verticale deriva semplicemente dal tuo '' self.mplvl.setGeometry (QtCore.QRect (150, 150, 251, 231)) '', che è troppo piccolo. – Silmathoron

3

Dai un'occhiata alla all'esempio matplotlib di incorporare in QT4: http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html

Qui essi definiscono un paio di classi che implementano un widget matplotlib in un'applicazione QT4, per esempio la classe MyStaticMplCanvas.Il trucco per utilizzare questa classe all'interno di QT Designer consiste nell'utilizzare un QWidget standard, fare clic con il pulsante destro del mouse e selezionareImmettere il nome della classe MyStaticMplCanvas in Promoted class name e il nome file in cui questa classe viene trovata in header file (l'estensione .h viene aggiunta, ma ignorato nel codice python). Fare clic su Add e Promote.

Ora dopo la compilazione dall'UIC il codice Python dovrebbe essere simile a:

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

from mystaticmplcanvas import MyStaticMplCanvas 
+1

Questo è sicuramente un passo nella giusta direzione. L'unico problema che ho ora è che self.setParent (parent) restituisce un errore: TypeError: argomenti non corrispondono ad alcuna chiamata sovraccaricata: QWidget.setParent (QWidget): l'argomento 1 ha un tipo inatteso 'PySide.QtGui.QWidget' QWidget. setParent (QWidget, Qt.WindowFlags): l'argomento 1 ha un tipo inatteso 'PySide.QtGui.QWidget' – Nickpick

+1

Assicurati di importare solo da PySide e niente da PyQt4. Probabilmente il tuo matplotlib usa PyQt4 di default. Le prime linee del tuo script impostano il back-end corretto in matplotlib, come nella risposta di Silmathoron. – Rob

+0

Ora ho modificato la domanda originale per mostrare meglio lo stato attuale delle cose – Nickpick

Problemi correlati