2016-04-06 4 views
9

Я искал рабочий пример, как встраивать график matplotlib в pyside, который создается с помощью конструктора QT, сохраняя логику в отдельном файле. Я знаю, что в Интернете есть множество примеров, но ни один из них фактически не использует конструктор QT, а затем создает отдельный файл, чтобы добавить логику, где график matplitlib добавлен в виджет. Я нашел пример, который «почти» работает http://blog.rcnelson.com/building-a-matplotlib-gui-with-qt-designer-part-1/, но в моей версии невозможно «изменить свойство layoutName с« verticalLayout »на« mplvl »».Matplotlib в Pyside с дизайнером Qt (PySide)

У меня есть следующие конкретные вопросы: Я не понимаю, в какой предмет этот сюжет можно встроить в конструктор Pyside Qt. Это простой «виджет» (поскольку в pyside нет виджета matplotlib). Если да, то как я могу добавить сюжет к этому виджету? Или мне нужно создать «FigureCanvas» с Qt Designer? Это вообще возможно? Если да, то как?

Вот простейший возможный дизайн, который я могу сделать с дизайнером Pyside Qt при встраивании виджета (это правильно?). Как я могу добавить график matplotlib поверх него?

Как было предложено в одном из ответов, я теперь продвинул Qwidget в MyStaticMplCanvas и отредактировал имя Qwidget для mplvl.

Автоматически сгенерированный файл с PySide Qt Designer и скомпилирован с PySide-UIC ui.ui -o ui.py -x

ui.py выглядит следующим образом:

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

как я могу прямо сейчас добавить участок в объект mplvl из отдельного файла .py?

+2

Вы не можете смешивать '' PyQt' и PySide' импорта в том же процессе. Я предлагаю вам импортировать все из модуля matplotlib.backends.qt_compat', где мы подгоняем различия. – tacaswell

+1

Код pyside автоматически генерируется pyside-uic, поэтому мне нужно как-то остаться. Разве вы не говорите, что это невозможно? – Nickpick

+1

У меня была аналогичная проблема - хотя есть некоторые отличия. Пожалуйста, ознакомьтесь с этим сообщением в stackoverflow: http://stackoverflow.com/questions/36665850/matplotlib-animation-inside-your-own-pyqt4-gui/36669876#36669876 Надеюсь, это поможет. –

ответ

7

Я не эксперт по этому вопросу, поэтому он не может быть чистым способом сделать это, но вот некоторые рабочий код, чтобы вы начали:

  • Я думаю, что самый простой способ добавить виджеты осуществляется через QxxxxLayout
  • тогда я просто сделал свой Plotter наследовать от FigureCanvas
  • и сказал matplotlib работать с 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)) 

Для этого вам просто нужно добавить холст mplvl в 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_()) 

Теперь то, что осталось, вероятно, чтобы настроить FigureCanvas чтобы сделать его правильным размером и пропорциями, чтобы вы могли получить то, что хотите, посмотреть на this example или the other.

Удачи вам!

+0

Чтобы уточнить: виджет нужно поместить в макет. В этом случае wiedget называется mplvl и вертикальной компоновкой vLayout. После этого приведенный выше код будет работать. – Nickpick

+0

Единственная небольшая проблема заключается в том, что сюжет немного отрезан внизу. Есть ли что-нибудь, что можно сделать по этому поводу? – Nickpick

+0

Я советую вам сделать следующее: внутри QtDesigner добавьте первую область прокрутки, где вы поместите вертикальный макет (замените '' mplvl''). Затем добавьте графики внутри этого макета. Проблема размера на вертикальной оси просто исходит из вашей '' self.mplvl.setGeometry (QtCore.QRect (150, 150, 251, 231)) '', которая слишком мала. – Silmathoron

3

Посмотрите на Matplotlib примере внедрения в QT4: http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html

Здесь они определяют пару классов, реализующих Matplotlib виджет в приложении QT4, например класс MyStaticMplCanvas.Трюк для использования этого класса внутри QT Designer заключается в использовании стандартного QWidget, щелкните его правой кнопкой мыши и выберите Promote to ... Заполните имя класса MyStaticMplCanvas под номером Promoted class name и имя файла, в котором этот класс находится под header file (добавлено расширение .h, но игнорируется в коде python). Нажмите Add и Promote.

Теперь после компиляции МСЖД, код питон должен быть похож на:

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

from mystaticmplcanvas import MyStaticMplCanvas 
+1

Это определенно шаг в правильном направлении. Единственная проблема, с которой я столкнулся сейчас, это то, что self.setParent (parent) дает ошибку: TypeError: аргументы не соответствуют перегруженному вызову: QWidget.setParent (QWidget): аргумент 1 имеет неожиданный тип 'PySide.QtGui.QWidget' QWidget. setParent (QWidget, Qt.WindowFlags): аргумент 1 имеет неожиданный тип «PySide.QtGui.QWidget» – Nickpick

+1

Убедитесь, что вы импортируете только из PySide и ничего из PyQt4. Вероятно, ваш matplotlib по умолчанию использует PyQt4. Первые строки вашего скрипта устанавливают правильный бэкэнд в matplotlib, как в ответе Сильматорона. – Rob

+0

Теперь я отредактировал исходный вопрос, чтобы лучше показать текущий статус вещей – Nickpick

Смежные вопросы