2017-12-02 251 views
0

我試圖儘量縮短範例。有一個similar question on SO。與上述問題提供的答案相反,我想定義一個MatplotlibFigure類,以便我可以重用代碼。我在函數make_tab1中添加了對圖的實例的引用self.figure = MatplotlibFigure(),並將self.figure添加到splitter。按鈕似乎工作,因爲我可以使用導航工具欄保存圖形。但是,該軸沒有顯示在GUI中。在Pyqt中嵌入Matplotlib畫布的實例 - 陰謀沒有顯示

爲什麼軸不可見?

import sys 
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QAction, QTabWidget, QVBoxLayout,\ 
          QHBoxLayout, QGridLayout, QSplitter, QFrame, QTextEdit, QFileDialog, QGroupBox,\ 
          QButtonGroup, QLabel, QRadioButton 

from PyQt5 import QtCore 

import matplotlib 
from matplotlib import figure 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar 

class MatplotlibFigure(QWidget): 

    # constructor 
    def __init__(self): 
     super().__init__() 
     #self.layout = QBoxLayout() 
     self.figure = matplotlib.figure.Figure() 
     self.canvas = FigureCanvas(self.figure) 
     self.toolbar = NavigationToolbar(self.canvas, self) 
     #self.layout.addWidget(self.canvas) 

    def plot(self): 
     self.figure.clf() 
     ax = self.figure.add_subplot(111) 
     x = [i for i in range(100)] 
     y = [i**0.5 for i in x] 
     ax.plot(x, y, 'g*-') 
     self.canvas.draw_idle() 
     print('PLOTTED') 


class MainApp(QMainWindow): 
    """ This creates the main Window and configures its look 
    """ 
    def __init__(self): 
     ''' 
     Initializes the class with standard parameters 
     ''' 
     super().__init__() 
     self.title = 'Data Analysis App' 

     # start at top left corner of the screen 
     self.left = 0 
     self.top = 0 

     # set the window height and width 
     self.width = 1280 
     self.height = 780 

     # set the styles of fonts etc. 
     self.setStyleSheet('font-size: 16pt') 

     # call the makeUI method 
     self.makeUI() 

    def makeUI(self): 
     # set window geometry 
     self.setWindowTitle(self.title) 
     self.setGeometry(self.left, self.top, self.width, self.height) 

     # generate the tab layout 
     self.table_widget = MyTableWidget() 
     self.setCentralWidget(self.table_widget) 

     # apparently we have to call the show method in order to show it 
     self.show() 


class MyTableWidget(QWidget): 
    """ 
    Initializes the tab layout 
    """ 

    def __init__(self): 
     super().__init__() 
     self.layout = QVBoxLayout(self) 

     # initialize the tab screens 
     self.tabs = QTabWidget() 

     # add the tab screens to the tab widget 
     self.tabs.resize(600, 600) 

     # make the layout of the tabs 
     self.make_tab1() 

     # initialize the tabs 
     self.layout.addWidget(self.tabs) 
     self.setLayout(self.layout) 

    def make_tab1(self): 
     """Style of tab 1 is created here""" 

     '''Defines master layout of tab1''' 
     tab1 = QWidget() 
     tab1.layout = QHBoxLayout() 

     '''Button Section''' 

     # converts the data into excel and pandas dataframe 
     btn_plot_data = QPushButton('Plot data') 
     btn_plot_data.clicked.connect(self.plot_data) 


     '''Button layout section''' 
     btn_layout = QVBoxLayout() 
     btn_layout.addWidget(btn_plot_data) 
     btn_layout.addStretch(1) 

     '''Page layout section ''' 

     left = QFrame() 
     left.setLayout(btn_layout) 

     self.figure = MatplotlibFigure() 

     # combine the buttons and the canvas in a splitter layout 
     splitter1 = QSplitter(QtCore.Qt.Horizontal) 
     splitter1.addWidget(left) 
     splitter1.addWidget(self.figure) 
     splitter1.setSizes([5, 400]) 


     # add the last splitter to the layout 
     tab1.layout.addWidget(splitter1) 
     tab1.setLayout(tab1.layout) 
     self.tabs.addTab(tab1, 'Get Data Module') 

    ''' Methods section 
    ''' 
    def plot_data(self): 
     self.figure.plot() 


if __name__ == '__main__': 
    """ This code block is always the same and makes sure that e.g. STRG+C kills the window etc. 
    """ 
    app = QApplication(sys.argv) 
    ex = MainApp() 
    sys.exit(app.exec()) 

回答

2

你忘了你的MatplotlibFigure類設置佈局(記住,這是一個QWidget你的情況,不畫布)

def __init__(self): 
    super().__init__() 
    #self.layout = QBoxLayout() 
    self.figure = matplotlib.figure.Figure() 
    self.canvas = FigureCanvas(self.figure) 
    self.toolbar = NavigationToolbar(self.canvas, self) 

    layout = QVBoxLayout(self) 
    layout.addWidget(self.toolbar) 
    layout.addWidget(self.canvas) 
+0

我不明白:我在該類中創建了一個佈局,併爲其添加了小部件。到現在爲止還挺好。然後我將這個類的實例(一個QWidget)傳遞給分離器。分配器現在如何關於佈局? – Moritz

+0

我接受了你的回答,因爲這個解決方案有效果,如果我改變窗口大小,劇情自動調整大小 – Moritz

+0

分割器只是你添加到它的所有小部件的容器 - 每個小部件都有自己的佈局,它自己的子部件例如,將'print(splitter1.children())'添加到'make_tab1' – erocoar

2

您需要家長設置爲FigureCanvas

self.canvas.setParent(self) 

enter image description here

+0

這是一個通用的辦法或者是這個解決方案matplotli b具體?或換句話說:這是一種在OO編程期間一般發生的模式嗎? – Moritz

+0

這是一個Qt規則,一個窗口小部件在默認位置(0,0)中的父窗口小部件中繪製(除非它是父窗口小部件),或者通過另一個解決方案顯示的佈局來放置它。 – eyllanesc