如何在PyQt4中用FigureCanvas创建多个独立弹出式图表?
Using FigureCanvas to Create Independent Chart Windows in PyQt4
Got it, let's tackle this problem. You want to replace plt.show() with FigureCanvas to generate 3 independent chart windows (instead of embedding them into one window), while keeping the original button and progress bar functionality. Here's a complete working solution:
Modified Full Code
import sys from PyQt4.QtGui import * from PyQt4.QtCore import * from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure import pandas as pd class ChartWindow(QMainWindow): def __init__(self, dataframe, parent=None): super(ChartWindow, self).__init__(parent) self.setWindowTitle("Matplotlib Chart") # Create matplotlib figure and Qt canvas widget self.figure = Figure() self.canvas = FigureCanvas(self.figure) self.setCentralWidget(self.canvas) # Plot the dataframe on the figure ax = self.figure.add_subplot(111) dataframe.plot(grid=1, ax=ax) # Refresh the canvas to render the plot self.canvas.draw() class App(QMainWindow): def __init__(self): super(App, self).__init__() self.setGeometry(500, 300, 820, 350) self.setWindowTitle("Program") # Buttons btnposx = 30 btnposy = 50 self.btn4 = QPushButton('Load', self) self.btn4.move(btnposx, btnposy + 220) self.btn4.released.connect(self.thread) # ProgressBar self.pb = QProgressBar(self) self.pb.move(btnposx + 150, btnposy + 220) self.pb.resize(470, 27) self.show() @pyqtSlot(float) def load(self, val): self.pb.setValue(val) @pyqtSlot(object) def plot(self, pq): # Create a new independent chart window for each plot signal chart_win = ChartWindow(pq) chart_win.show() def thread(self): self.thread_ = Thread() self.thread_.pb_signal.connect(self.load, Qt.QueuedConnection) self.thread_.plot_signal.connect(self.plot, Qt.QueuedConnection) self.thread_.start() class Thread(QThread): pb_signal = pyqtSignal(float) plot_signal = pyqtSignal(object) def __init__(self, *args, **kwargs): QThread.__init__(self, *args, **kwargs) def __del__(self): self.wait() @pyqtSlot() def run(self): val = 0 self.pb_signal.emit(20) l = range(50000000) for i in l: val += 1 self.pb_signal.emit(60) self.pb_signal.emit(100) pq = pd.DataFrame(data = {'col1':[1,2,3,4,5,6], 'col2':[6,5,4,3,2,1]}) self.plot_signal.emit(pq) self.plot_signal.emit(pq) self.plot_signal.emit(pq) return if __name__ == '__main__': app = QApplication(sys.argv) ex = App() ex.show() sys.exit(app.exec_())
Key Changes Explained
- Added
ChartWindowClass: This is a standaloneQMainWindowsubclass—each instance acts as an independent top-level window. Inside it, we create a matplotlibFigure(the plot container) and aFigureCanvas(the PyQt widget that renders the figure), then set the canvas as the window's central widget. - Updated
plotSlot: Instead of relying onplt.show(), we now spawn a newChartWindowfor every incomingplot_signaland callshow()on it. This replicates the original behavior of 3 separate chart windows, but uses PyQt's native window system instead of matplotlib's pyplot wrapper. - Removed
matplotlib.pyplotImport: We don't needpltanymore because we're using matplotlib's object-oriented API directly withFigureandFigureCanvas, which integrates cleaner with PyQt.
This solution preserves all your original functionality (button trigger, progress bar updates, independent charts) while using FigureCanvas as requested.
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

