pyqt 5 의 UI 에 matplotlib 도형 을 삽입 하고 실시 간 으로 새로 고침(구덩이 파기 와 구덩이 메 우기)

1.pyqt 5 UI 에 matplotlib 를 삽입 하 는 방법
1.가 져 오기 모듈
가 져 오기 모듈 은 간단 합 니 다.먼저 pyqt 5 를 사용 하 라 고 밝 혔 습 니 다.Figure CanvasQTAgg 를 통 해 캔버스 를 만 들 고 캔버스 의 그림 을 UI 에 표시 할 수 있 습 니 다.pyqt 5 에 해당 하 는 컨트롤 입 니 다.뒤의 그림 은 이 캔버스 에 만 든 다음 에 이 캔버스 에 pyqt 5 컨트롤 을 pyqt 5 UI 에 추가 하고 그 다음 에 matplotlib.figure 의 Figure 를 가 져 옵 니 다.여기 서 주의해 야 할 것 은 matplotlib.figure 의 Figure 입 니 다.matplotlib.pyplot 모듈 의 Figure 가 아니 라 구분 해 야 합 니 다.

import matplotlib
matplotlib.use("Qt5Agg") #     pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg # pyqt5   
import matplotlib.pyplot as plt
# matplotlib.figure         Artist(           Artist   ),       plot  
from matplotlib.figure import Figure 
2.pyqt 5 캔버스 를 만 들 고 스타일 을 간단하게 설정 합 니 다.
캔버스 클래스 를 만 들 고 위 에서 가 져 온 Figure CanvasQTAgg 를 계승 하여 Figure 를 통 해 캔버스 를 만 들 고 부모 클래스 Figure CanvasQTAgg 에 매개 변수 로 전달 합 니 다(여기 가 관건 입 니 다!이 단계 가 없 으 면 모든 것 이 헛 되 고 성공 을 추가 하지 않 습 니 다!)마지막 단계 그림 그리 기 영역 self.axes 추가

class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
         ,      FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' #       
    plt.rcParams['axes.facecolor'] = 'b' #        
    self.width = width
    self.heigh = heigh
    self.dpi = dpi
    self.figs = Figure(figsize=(self.width, self.heigh), dpi=self.dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) #       self.fig,         
    self.axes = self.figs.add_subplot(111)
3.pyqt 5 캔버스 를 만 드 는 구 덩이 를 채 웁 니 다.
위 에서 사용자 정의 캔버스 류 MyMatplotlibFigure 를 쓸 때 오 류 를 알 리 지 않 지만 그림 을 그 릴 때 눈 이 멀 어 집 니 다.오 류 를 알 리 지 않 았 기 때문에 반 짝 거 립 니 다!!!그리고 하나씩 의 심 스 러 운 클래스 와 방법 try...except..print(er),python 이 이 유 를 알려 줬 으 면 좋 겠 어 요.죄송합니다!결국 결 과 는 아무것도 얻 지 못 했다!debug 단일 디 버 깅 을 사용 하여 천천히 분석 하고 힘 들 게 한 걸음 한 걸음 마지막 으로 pyqt 5 에 캔버스 를 추가 하 는 것 을 보 았 을 때 한 모듈 backendqt5.py 파일 의 500 번 째 줄:if self.height()<0 or self.width()<0:debug 의 변수 분석 에서"(,TypeError("int'object is not callable"),)이것 은 무슨 귀신 입 니까?
사실 이것 은 매우 간단 한 잘못 이지 만,조심 하지 않 아 조사 하기 가 매우 번거롭다!!잘못된 이 유 는 일부 프로그래머 들 이 사용자 정의 클래스 에서 외부 전 파 를 받 을 때 전달 하 는 매개 변 수 를 전역 변수 로 자주 바 꾸 기 때 문 입 니 다.예 를 들 어 이 예 에서 초기 화init__방법 이 받 은 세 개의 매개 변수 width,heigh,dpi 를 손 쉽게 썼 습 니 다.

self.width = width
self.heigh = heigh
self.dpi = dpi
 그리고 이어서 호출!문 제 는 바로 여기에 있다.사실 네 뒤에 호출 이 있 든 없 든 모두 물 러 날 것 이다!!!!왜 일 까요?
Figure CanvasQTAgg 부모 클래스 에서 backend 가 져 왔 기 때 문 입 니 다.qt5.py 모듈,backendqt5 모듈 내부 에 도 같은 변수 이름 self.width 와 self.heigh 를 사 용 했 습 니 다.그래서 여기 서 위의 쓰기 로 부모 변 수 를 덮어 씁 니 다.올 바른 표기 법:

class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
         ,      FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' #       
    plt.rcParams['axes.facecolor'] = 'b' #        
    #     Figure, Figure matplotlib  Figure,  matplotlib.pyplot   Figure
    #       ,width, heigh        ,   self.width、self.heigh      ,  self.width、self.heigh       FigureCanvasQTAgg     ,         
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) #       self.fig,         (          )
    self.axes = self.figs.add_subplot(111) #      
여기 서 직접 전 삼 문 자 를 사용 하면 됩 니 다.이 몇 개의 매개 변 수 는 뒤에 사용 할 수 없습니다.만약 에 사용 할 수 있다 면 마음대로 이름 을 바 꾸 십시오.예 를 들 어 self.w=width self.h=heigh
4、pyqt 5 UI 에 캔버스 추가
간단 한 창 을 만 들 고 label 을 추가 합 니 다.위 에 만 든 사용자 정의 캔버스 류 를 예화 하고 변수 self.canvas 로 인 스 턴 스 를 받 습 니 다.이것 은 pyqt 5 의 컨트롤 에 해당 합 니 다.label 에 레이아웃 을 만 들 고 레이아웃 에 캔버스 self.canvas 를 추가 합 니 다.
만약 에 matplotlib 의 그림 을 Ui 에 추가 하 는 것 이 라면 plotcos 라 는 그림 그리 기 방법 은 어디 에 두 어도 되 고 위의 사용자 정의 클래스 에 이 방법 을 추가 할 수 있 습 니 다.마지막 으로 그림 을 그 리 는 두 줄 만 간단하게 수정 하면 됩 니 다.

class MainDialogImgBW_(QtWidgets.QMainWindow):
  """
    UI   ,       。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("  matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)

  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.aexs.plot(t, s)
    self.canvas.figs.suptitle("sin") #     
2.실시 간 으로 matplotlib 그림 의 구 덩이 를 새로 고 칩 니 다.
실시 간 으로 이미 지 를 새로 고치 고 인터넷 을 통 해 조회 하면 기본적으로 천편일률 적 인 결 과 는 클 린 이 이전의 이미 지 를 지우 고 다시 plot,그리고 draw()를 다시 그 리 는 것 이다.다른 게시 물 에서 가장 대표 적 인 3 부작 절 차 는 다음 과 같다.

self.axes.cla()
self.axes.plot(x, y, 'o',xx,yy)
self.draw()
 이 세 곡 은 맞 지만 그들 이 말 하 는 것 이 좀 간단 할 뿐이다.어떤 세부 사항 은 주의해 야 한다.그렇지 않 으 면 똑 같이 새로 고치 거나 잘못 보고 하고 반 짝 거리 지 않 을 것 이다.주의해 야 할 구 덩이 는 draw()입 니 다.그들의 댓 글 은 간단 하기 때문에 그들의 self 가 몇 가지 의미 가 있 는 지 모 르 겠 습 니 다.일반적인 상황 에서 이렇게 쓰 는 것 은 틀 립 니 다.**cla()는 그림 그리 기 영역 을 비 웠 습 니 다.plot()는 그림 을 다시 그 렸 습 니 다.이 두 가 지 는 그림 그리 기 영역 에 대한 작업 이지 만 draw()는 그림 그리 기 영역 이 아 닙 니 다.그리고 draw()만 으로 는 부족 합 니 다.flush이벤트()그렇지 않 으 면 캔버스 를 새로 고침 하 는 과정 에서 우연히 반 짝 일 수 있 습 니 다.**완전한 정확 한 코드 는 다음 과 같다.

class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
         ,      FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' #       
    plt.rcParams['axes.facecolor'] = 'b' #        
    #     Figure, Figure matplotlib  Figure,  matplotlib.pyplot   Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) #       self.fig, 
    self.axes = self.figs.add_subplot(111) #      
  def mat_plot_drow_axes(self, t, s):
    """
                
    :return:
    """
    self.axes.cla() #      

    self.axes.spines['top'].set_visible(False) #       
    self.axes.spines['right'].set_visible(False) #       
    #    、    (0,0)   
    # self.axes.spines['bottom'].set_position(('data', 0)) #   y        0
    self.axes.spines['left'].set_position(('data', 0)) #   x        0
    self.axes.plot(t, s, 'o-r', linewidth=0.5)
    self.figs.canvas.draw() #          ,self.figs.canvas
    self.figs.canvas.flush_events() #     self.figs.canvas

class MainDialogImgBW(QtWidgets.QMainWindow):
  """
    UI   ,       。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("  matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)

  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.mat_plot_drow_axes(t, s)
    self.canvas.figs.suptitle("sin") #     


if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())
**주의해 야 할 점 은 캔버스 를 다시 그 리 는 표기 법 입 니 다.self.draw()도 self.axes.draw()나 self.figs.draw()도 아니 고 self.figs.canvas.draw()와 self.figs.canvas.flush 입 니 다.이벤트(),이 두 코드 를 쓸 때 스마트 알림 이 없습니다!(제 가 사용 하 는 pycharm 은 이 구덩이 에 빠 졌 을 수도 있 습 니 다.다른 IDE 가 알려 줄 지 모 르 겠 습 니 다)**여기 서 알려 드릴 것 은 self.figs.canvas.draw()만 self.figs.canvas.flush 가 없습니다.이벤트()때 도 다시 그립 니 다.하지만 실행 중 에 반 짝 일 수 있 으 므 로 안전 합 니 다.
3.matplotlib 를 실시 간 으로 업데이트 하 는 또 다른 방법
위 에 서 는 axes.cla()방식 으로 도 표를 새로 고 치 는 것 입 니 다.그러나 만 날 수 있 습 니 다.다음 그림 은 앞의 도표 와 완전히 다 릅 니 다.캔버스 배경 색 등 이 다 릅 니 다.그러면 위의 axes.cla()로 그림 구역 만 정리 하면 부족 합 니 다.캔버스 figure.clf()를 정리 해 야 합 니 다.이곳 을 잘 보 세 요.그림 구역 을 정리 하 는 방법 은 cla()입 니 다.캔버스 를 치 우 는 것 은 clf()한 글자 차이 다.또 주의해 야 할 점 은 캔버스 를 정리 한 후에 캔버스 에 있 는 그림 구역 axes 도 정리 하고 axes 를 다시 추가 해 야 한 다 는 것 입 니 다.전체 코드 는 다음 과 같 습 니 다.

class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
         ,      FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    #     Figure, Figure matplotlib  Figure,  matplotlib.pyplot   Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) #       self.fig, 
  def mat_plot_drow(self, t, s):
    """
                
    :return:
    """
    self.figs.clf() #     ,   clf()
    self.axes = self.figs.add_subplot(111) #               
 self.axes.patch.set_facecolor("#01386a") #   ax      
    self.axes.patch.set_alpha(0.5) #   ax         
    self.figs.patch.set_facecolor('#01386a') #         
    self.axes.spines['bottom'].set_color('r') #        
    self.axes.spines['top'].set_visible(False) #       
    self.axes.spines['right'].set_visible(False) #       
    #    、    (0,0)   
    # self.axes.spines['bottom'].set_position(('data', 0)) #   y        0
    self.axes.spines['left'].set_position(('data', 0)) #   x        0
    self.axes.plot(t, s, 'o-r', linewidth=0.5)
    self.figs.canvas.draw() #          ,self.figs.canvas
    self.figs.canvas.flush_events() #     self.figs.canvas

class MainDialogImgBW(QtWidgets.QMainWindow):
  """
    UI   ,       。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("  matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)

  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.mat_plot_drow(t, s)
    self.canvas.figs.suptitle("sin") #     


if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())
4.animation 방식 으로 matplotlib 새로 고침
만약 에 UI 에서 리 셋 빈도 가 매우 높다 면 예 를 들 어 주식 이나 선물의 tick 데 이 터 는 위의 리 셋 방식 이 좀 부족 하 다.리 셋 도 할 수 있 지만 화면 이 반 짝 일 수 있 는 상황 이 매우 불편 하고 고주파 리 셋 은 animation 방식 으로 리 셋 할 수 있다.
animation 을 사용 하려 면 matplotlib.animation 모듈 을 가 져 오 는 FuncAnimation 방법 을 추가 해 야 합 니 다.모든 가 져 오기 모듈 은 다음 과 같 습 니 다.

import matplotlib
matplotlib.use("Qt5Agg") #     pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg # pyqt5   
import matplotlib.pyplot as plt
from matplotlib.figure import Figure 
from matplotlib.animation import FuncAnimation
Func Animation 의 기 초 는 여기 서 설명 하지 않 습 니 다.포럼 에서 검색 하면 찾 을 수 있 습 니 다.구덩이 가 존재 할 수 있 는 곳 만 제시 하고 데이터 업데이트 함 수 는 그림 그리 기 방법 plot 에 포 함 됩 니 다.tick 내의(이것 이 형식 오류 라 고 생각 하지 마 세 요).여기 코드 바로 올 리 기:

class MyMatPlotAnimation(FigureCanvasQTAgg):
  """
         ,        (   )FigureCanvasQTAgg,        
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    #     Figure, Figure matplotlib  Figure,  matplotlib.pyplot   Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatPlotAnimation, self).__init__(self.figs) 
    self.figs.patch.set_facecolor('#01386a') #         
    self.axes = self.figs.add_subplot(111)

  def set_mat_func(self, t, s):
    """
           
    """
    self.t = t
    self.s = s
    self.axes.cla()
    self.axes.patch.set_facecolor("#01386a") #   ax      
    self.axes.patch.set_alpha(0.5) #   ax         

    # self.axes.spines['top'].set_color('#01386a')
    self.axes.spines['top'].set_visible(False) #       
    self.axes.spines['right'].set_visible(False) #       

    self.axes.xaxis.set_ticks_position('bottom') #   ticks(  )      
    self.axes.yaxis.set_ticks_position('left') #   ticks(  )       
    #    、    (0,0)   
    # self.axes.spines['bottom'].set_position(('data', 0)) #   x   Y 0  
    self.axes.spines['left'].set_position(('data', 0)) #   y  x 0  
    self.plot_line, = self.axes.plot([], [], 'r-', linewidth=1) #   ‘,'    
    
  def plot_tick(self):
    plot_line = self.plot_line
    plot_axes = self.axes
    t = self.t
    
    def upgrade(i): #      plot_tick        
      x_data = [] #              self  ,           
      y_data = []
      for i in range(len(t)):
        x_data.append(i)
        y_data.append(self.s[i])
      plot_axes.plot(x_data, y_data, 'r-', linewidth=1)
      return plot_line, #       ‘,'    ,     
      
    ani = FuncAnimation(self.figs, upgrade, blit=True, repeat=False)
    self.figs.canvas.draw() #         

class MainDialogImgBW(QtWidgets.QMainWindow):
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("  matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatPlotAnimation(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)

  def plotcos(self):
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.set_mat_func(t, s)
    self.canvas.plot_tick()


if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())
pyqt 5 를 자세히 설명 하 는 UI 에 matplotlib 그래 픽 을 삽입 하고 실시 간 으로 새로 고침(구 덩이 를 파 거나 구 덩이 를 메 우 는 것)하 는 글 을 소개 합 니 다.더 많은 관련 pyqt 5 에 matplotlib 그래 픽 내용 이 들 어 있 습 니 다.이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기