【问题标题】:matplotlib figure zoom: ticklabels don't get updated (Python)matplotlib 图形缩放:ticklabels 没有得到更新(Python)
【发布时间】:2016-09-16 11:47:57
【问题描述】:

我用 Python 设计了一个软件,可以根据微控制器数据制作实时绘图。您可以将其视为某种示波器。我使用 matplotlib 库来绘制绘图,并将其嵌入到 PyQt4 GUI 中。我实现了一个zoom按钮来放大图形(缩放只影响y限制):

很遗憾,yticklabels 没有得到更新。我尝试了几件事(比如在正确的 QWidget 上调用 repaint() 函数),但无济于事。所以我决定向 StackOverflow 寻求帮助。您可以在下面找到一个找出问题的代码示例。数据是模拟的,因此您无需连接微控制器。通常,您应该能够复制/粘贴此示例,并毫无问题地运行它。点击几次zoom按钮,你就会注意到我的问题。

import sys
import os
from PyQt4 import QtGui
from PyQt4 import QtCore
import functools

import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt4Agg")

from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

def setCustomSize(x, width, height):
    sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
    sizePolicy.setHorizontalStretch(0)
    sizePolicy.setVerticalStretch(0)
    sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
    x.setSizePolicy(sizePolicy)
    x.setMinimumSize(QtCore.QSize(width, height))
    x.setMaximumSize(QtCore.QSize(width, height))

''''''

class CustomMainWindow(QtGui.QMainWindow):

    def __init__(self):

        super(CustomMainWindow, self).__init__()

        # Define the geometry of the main window
        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle("my first window")

        # Create FRAME_A
        self.FRAME_A = QtGui.QFrame(self)
        self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name())
        self.LAYOUT_A = QtGui.QGridLayout()
        self.FRAME_A.setLayout(self.LAYOUT_A)
        self.setCentralWidget(self.FRAME_A)

        # Place the zoom button
        self.zoomBtn = QtGui.QPushButton(text = 'zoom')
        setCustomSize(self.zoomBtn, 100, 50)
        self.zoomBtn.clicked.connect(self.zoomBtnAction)
        self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))

        # Place the matplotlib figure
        self.myFig = CustomFigCanvas()
        self.LAYOUT_A.addWidget(self.myFig, *(0,1))

        self.show()

    ''''''


    def zoomBtnAction(self):
        print("zoom in")
        self.myFig.zoomIn(5)

    ''''''



''' End Class '''


class CustomFigCanvas(FigureCanvas, TimedAnimation):

    def __init__(self):

        self.addedData = []
        print(matplotlib.__version__)

        # The data
        self.xlim = 200
        self.n = np.linspace(0, self.xlim - 1, self.xlim)
        a = []
        b = []
        a.append(2.0)
        a.append(4.0)
        a.append(2.0)
        b.append(4.0)
        b.append(3.0)
        b.append(4.0)
        self.y = 50 + ((rd.random()*a[0] + 0.2)*np.sin(self.n/(b[0]*rd.random() + 0.2))) + ((rd.random()*a[1] + 0.1)*np.sin(self.n/(b[1]*rd.random() + 0.2))) + ((rd.random()*a[2] + 0.1)*np.sin(self.n/(b[2]*rd.random() + 0.2)))

        # The window
        self.fig = Figure(figsize=(5,5), dpi=100)
        self.ax1 = self.fig.add_subplot(111)


        # self.ax1 settings
        self.ax1.set_xlabel('time')
        self.ax1.set_ylabel('raw data')
        self.line1 = Line2D([], [], color='blue')
        self.line1_tail = Line2D([], [], color='red', linewidth=2)
        self.line1_head = Line2D([], [], color='red', marker='o', markeredgecolor='r')
        self.ax1.add_line(self.line1)
        self.ax1.add_line(self.line1_tail)
        self.ax1.add_line(self.line1_head)
        self.ax1.set_xlim(0, self.xlim - 1)
        self.ax1.set_ylim(0, 100)


        FigureCanvas.__init__(self, self.fig)
        TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)




    def _draw_frame(self, framedata):
        margin = 2
        while(len(self.addedData) > 0):
            self.y = np.roll(self.y, -1)
            self.y[-1] = self.addedData[0]
            del(self.addedData[0])


        self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
        self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
        self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
        self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]

    def new_frame_seq(self):
        return iter(range(self.n.size))

    def _init_draw(self):
        lines = [self.line1, self.line1_tail, self.line1_head]
        for l in lines:
            l.set_data([], [])

    def addData(self, value):
        self.addedData.append(value)

    def zoomIn(self, value):
        bottom = self.ax1.get_ylim()[0]
        top = self.ax1.get_ylim()[1]
        bottom += value
        top -= value
        self.ax1.set_ylim(bottom,top)


''' End Class '''



if __name__== '__main__':
    app = QtGui.QApplication(sys.argv)
    QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
    myGUI = CustomMainWindow()


    sys.exit(app.exec_())

''''''

注意:我的系统配置如下:

  • Windows 10
  • Anaconda python 包已安装
  • 用于 GUI 的 PyQt4 库
  • 用于绘图的 matplotlib 库

非常感谢您的帮助。

【问题讨论】:

    标签: python python-3.x matplotlib plot pyqt


    【解决方案1】:

    我相信我找到了答案。 CustomFigCanvas() 类中的zoomIn 函数应包含以下指令:

    self.draw()
    

    所以zoomIn函数如下:

    class CustomFigCanvas(FigureCanvas, TimedAnimation):
    
        def __init__(self):
            # ...
    
        ''''''
    
        def zoomIn(self, value):
            bottom = self.ax1.get_ylim()[0]
            top = self.ax1.get_ylim()[1]
            bottom += value
            top -= value
            self.ax1.set_ylim(bottom,top)
            self.draw() # <- this is the solution
    
        ''''''
    
    ''' End Class '''
    

    很抱歉给您带来不便。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多