2017-09-29 13 views
0

大きなプロジェクトの一環として、Pyqt5に埋め込まれたmatplotlibのグラフを更新しています。私は散点に注釈を追加して削除するonpickイベントを持っています。下のような方法で私のプロットを更新した後、onPickフィーチャは2回登録されます。正しく削除されていないものがあります。私は、私の問題を修正するだろう、図のほかに私が何を明らかにするのだろうと思っていた。matplotlib onPickイベントを2回登録する

単純な例の問題を強調:

import sys 

from PyQt5.QtGui import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 

class plot(QWidget): 
    def __init__(self): 
     super().__init__() 
    self.figure = plt.figure() 
    self.canvas = FigureCanvas(self.figure) 

    self.Layout = QVBoxLayout() 

    self.xarray = [1,2,3,4,5,6] 
    self.yarray = [6,7,5,4,2,1] 

    update_btn = QPushButton("Update Plot", self) 
    self.Layout.addWidget(update_btn, 1) 
    update_btn.clicked.connect(self.updateplot) 

    self.createplot() 

    self.setLayout(self.Layout) 

def updateplot(self): 

    self.xarray = [6,7,5,3,2,1] 
    self.figure.clear() 
    self.createplot() 

def createplot(self): 

    ax = self.figure.add_subplot(1,1,1) 
    ax.grid() 
    val = self.displayval(ax) 
    self.plot = ax.plot(self.xarray, self.yarray,'o', marker = 'o', c= 'b', picker = 5)[0] 

    self.Layout.addWidget(self.canvas, 2) 
    self.canvas.draw() 

def displayval(self, ax): 
    def onPick(event): 
     print("connecting") 
     plot = event.artist 

     xval = plot.get_xdata() 
     yval = plot.get_ydata() 
     ind = event.ind 

     if xval[ind].size > 1 or yval[ind].size > 1: return 

     xy = (xval[ind][0], yval[ind][0]) 

     ann = ax.annotate('(%f , %f)' % xy, xy= xy) 

     self.figure.canvas.draw() 

    self.figure.canvas.mpl_connect('pick_event', onPick) 
    return onPick 

if __name__ == '__main__': 
    appl = QApplication(sys.argv) 
    main = plot() 
    main.show() 
    sys.exit(appl.exec_()) 

注:私は、しかし、これは私のプログラムでデータを正しくレンダリングされません

ax.set_xaxis() 

ようなもので、軸の値を更新しようとしているため、代替的な答えが好ましい。

+1

プロットを更新するたびに、新しいpick_eventが登録されると思います。したがって、一度更新するとonPickは2回呼び出されます.2回更新すると3回呼び出されます。更新機能に依存せず、一度だけ登録する必要があります。 – ImportanceOfBeingErnest

+1

私は@ImportanceOfBeingErnestに同意します。 'figure.clear()'の直後や 'displayval()'の中で接続する前のように、プロットを消去するときにシグナル/スロットを切断する必要があります。 – bnaecker

+0

@bnacker 'displayval()'でシグナル/イベントキューをクリアするのは、回避策としては良いアイデアです。私はそれをどうやって行うのか分かりますか?しかし、私はこれをしないで、問題を解決する理由は、キャンバス上に2つのアクションを登録しています。 –

答えて

0

ここでは、問題の解決方法を示します。 @ImportanceOfBeingErnestに問題が発生した理由を説明してくれてありがとう。そこから問題を解決することができました。一旦更新されると、オンクリック注釈は一度しか起こらない。解決策はdisplayvalを一度呼び出し、axを 'self.ax'に変更してオブジェクト変数を更新することだけです。

import sys 

from PyQt5.QtGui import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 

class plot(QWidget): 
    def __init__(self): 
     super().__init__() 

     self.figure = plt.figure() 
     self.canvas = FigureCanvas(self.figure) 

     self.Layout = QVBoxLayout() 

     self.xarray = [1,2,3,4,5,6] 
     self.yarray = [6,7,5,4,2,1] 
     self.init_trigger = True 

     update_btn = QPushButton("Update Plot", self) 
     self.Layout.addWidget(update_btn, 1) 
     update_btn.clicked.connect(self.updateplot) 

     self.createplot() 

     self.setLayout(self.Layout) 

    def updateplot(self): 

     self.xarray = [6,7,5,3,2,1] 
     self.figure.clear() 
     self.createplot() 

    def createplot(self): 


     self.ax = self.figure.add_subplot(1,1,1) 
     self.ax.grid() 
     if self.init_trigger: val = self.displayval() 
     self.plot = self.ax.plot(self.xarray, self.yarray,'o', marker = 'o', c= 'b', picker = 5)[0] 

     self.Layout.addWidget(self.canvas, 2) 
     self.canvas.draw() 
     self.init_trigger = False 

    def displayval(self): 
     def onPick(event): 
      print("connecting") 
      plot = event.artist 

      xval = plot.get_xdata() 
      yval = plot.get_ydata() 
      ind = event.ind 

      if xval[ind].size > 1 or yval[ind].size > 1: return 

      xy = (xval[ind][0], yval[ind][0]) 

      ann = self.ax.annotate('(%f , %f)' % xy, xy= xy) 

      self.figure.canvas.draw() 

     self.figure.canvas.mpl_connect('pick_event', onPick) 
     return onPick 

if __name__ == '__main__': 
    appl = QApplication(sys.argv) 
    main = plot() 
    main.show() 
    sys.exit(appl.exec_()) 
関連する問題