Variables entre clases para escalar el gráfico en la GUI de PyQt

Estoy creando una GUI que consiste en tener un par de cuadros de entrada de usuario y una gráfica que usará factores en los cuadros de entrada para escalar los datos. La GUI necesitará un botón de aplicación y un botón de exportación. Estoy usando PyQt5 para la GUI y Matplotlib para el trazado. Mi enfoque ha sido crear QWidgets separados para la gráfica y los cuadros de entrada y unirlos en una tercera QMainWindow.

Tengo la GUI apareciendo correctamente

¿Cómo puedo obtener el botón de aplicar para enviar las 3 variables a la clase principal ya la clase de trazado? ¿Sería posible que todo esto suceda dentro de una clase para simplificar cómo funcionarán mis variables?

import sys import matplotlib matplotlib.use("Qt5Agg") from PyQt5 import QtCore from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt5.QtWidgets import * from numpy import arange, sin, pi from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure class AppForm(QWidget): def __init__(self): # Initialize the object as a QWidget and # set its title and minimum width QWidget.__init__(self) self.setWindowTitle('Input') self.setMinimumWidth(400) # Create the QVBoxLayout that lays out the whole form self.layout = QVBoxLayout() # Create the form layout that manages the labeled controls self.form_layout = QFormLayout() self.aFactor = QLineEdit(self) self.mFactor = QLineEdit(self) self.cZone = QLineEdit(self) self.form_layout.addRow('AFactor', self.aFactor) self.form_layout.addRow('MFactor', self.mFactor) self.form_layout.addRow('CZone', self.cZone) self.layout.addLayout(self.form_layout) self.button_box = QHBoxLayout() self.button_box.addStretch(1) self.apply_button = QPushButton("Apply", self) self.output_button = QPushButton("Output", self) self.button_box.addWidget(self.apply_button) self.button_box.addWidget(self.output_button) self.layout.addLayout(self.button_box) self.setLayout(self.layout) self.apply_button.clicked.connect(self.applyButton) def applyButton(self): self.af = self.aFactor self.mf = self.mFactor self.cz = self.cZone print self.af.text(), self.mf.text(), self.cz.text() class MyMplCanvas(FigureCanvas): """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.).""" def __init__(self, parent=None, width=5, height=4, dpi=100, title='title'): self.title = title fig = Figure(figsize=(width, height), dpi=dpi) self.axes = fig.add_subplot(111) fig.suptitle(title) # We want the axes cleared every time plot() is called self.axes.hold(False) self.compute_initial_figure() FigureCanvas.__init__(self, fig) self.setParent(parent) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) def compute_initial_figure(self): pass class MyStaticMplCanvas(MyMplCanvas): """Simple canvas with a sine plot.""" def compute_initial_figure(self): t = arange(0.0, 3.0, 0.01) s = sin(2*pi*t) self.axes.plot(t, s) self.axes.set_ylabel('label1') self.axes.set_xlabel('label') self.axes.grid(True) class ApplicationWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("application main window") self.setMinimumWidth(800) self.setMinimumHeight(600) self.file_menu = QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) self.help_menu = QMenu('&Help', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.help_menu.addAction('&About', self.about) self.main_widget = QWidget(self) l = QVBoxLayout(self.main_widget) form = AppForm() sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100, title='Title 1') l.addWidget(form) l.addWidget(sc) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) #self.statusBar().showMessage("Cool", 2000 def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit() def about(self): QMessageBox.about(self, "About",) if __name__ == '__main__': app = QApplication(sys.argv) aw = ApplicationWindow() aw.setWindowTitle("PyQt5 Matplot Example") aw.show() #sys.exit(qApp.exec_()) app.exec_() 

Hay varias opciones aquí:

(a) Realice el trabajo en la clase principal: en lugar de conectar el botón en AppForm a un método en AppForm , haga lo mismo en ApplicationWindow .

 self.form = AppForm() self.sc = MyStaticMplCanvas(....) self.form.apply_button.clicked.connect(self.applyButton) def applyButton(self): tx = self.form.aFactor.text() # do something with tx # eg call a method from MplCanvas self.sc.someMethod(tx) 

(b) Utilice señales y ranuras: cree un signla en AppForm . Una vez que se hace clic en el botón, applyButton puede emitir esta señal con el contenido relevante. En ApplicationWindow conecte esa señal a un método que pueda utilizar los datos suministrados de alguna manera. También puedes conectarlo directamente a un método de MplCanvas .

 class AppForm(QWidget): mysignal = pyqtSignal(object) def __init__(self): .... self.apply_button.clicked.connect(self.applyButton) def applyButton(self): self.mysignalemit((self.aFactor.text(),self.mFactor.text(), self.cZone()) ) class ApplicationWindow(QMainWindow): def __init__(self): .... self.form = AppForm() self.sc = MyStaticMplCanvas(....) self.form.mysignal.connect(self.useButtonResults) self.form.mysignal.connect(self.sc.someMethod) def useButtonResults(self, obj): a,b,c = obj # do something with a, b, c 

(c) Use una sola clase para hacer todo: simplemente coloque todo en una sola clase y haga lo que quiera.