2017-01-26 10 views
1

私の目標は、ユーザーがクリックしたサブプロットを特定することです。より正確には、matplotlibクラスでは、event.inaxesを使用してサブプロットを識別できます。すばらしいです。しかし、私はQtウィジェットクラスでそのイベントを取得することはできません。 私は間違いなく何かを逃しています... ここに私の最新の "厄介な"試みのコードがあります。どのように処理するかに関する提案?Python 2.7 Qt Matplotlib:イベントからのサブプロットIDリファレンス

私はPythonのエキスパートです。 InventoryChartsWidgetはメインウィジェット(ある TheConnectorが ChartFigureは(希望マウスイベントを含む)matplotlibのクラスであるシグナル/スロットQTクラスです:Pythonの2.7は、3つのクラスがあります

from __future__ import print_function 
from __future__ import division 

import sys 

from PyQt4 import QtGui 
from PyQt4 import QtCore 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

from matplotlib.figure import Figure 
from matplotlib.backend_bases import key_press_handler 
from matplotlib.backend_bases import Event 
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg as FigureCanvas, 
NavigationToolbar2QT as NavigationToolbar) 

#Connect InventoryChartsWidget to ChartFigure: QT 
class TheConnector(QtCore.QObject): 

    selecteddataregion=pyqtSignal(name='selecteddataregion') 

    def emitsignal(self,xmin,xmax,ymin,ymax): 
     self.selecteddataregion.emit() 

#Chart including events: MATPLOTLIB 
class ChartFigure(Figure): 

def onclick(self,event): 
    #MAIN ISSUE 
    #HOW TO RETURN THE subplot axes to class InventoryChartsWidget?  

    if event.button==1 : 
     self.ConnSbPlt.emitsignal(1.0,1.0,2.0,2.0) 
     print('OK: Axes is ... ', event.inaxes) 

def __init__(self,Conn): 
    #Init the Matplotlib  
    Figure.__init__(self) #initialize the orginal class, see also super() 
    super(ChartFigure, self).__init__() 
    self.canvas=FigureCanvas(self) 
    self.ConnSbPlt=Conn 

#Chart including events: QT 
class InventoryChartsWidget(QtGui.QDialog): 

def __init__(self, parent=None,xlimlow=0,xlimhigh=100,ylimlow=0,ylimhigh=100, G_array=[], N_array=[], ddom_array=[], hdom_array=[], speciesDict={}): 

    QMainWindow.__init__(self, parent) 

    #Fake stupid data 
    self.mG_array = [2] * 10 
    self.mHdom_array = [0.5] * 10 

    #jte to make sur I have it 
    self.xdata_start=-1.0 

    #fake plot to get a member of type subplot: UGLY! 
    #Attempt to create a member object "axes" 
    self.tabFake = QtGui.QWidget() 
    self.tabFake = self.create_tab(self.tabFake) 
    self.tabFake.plots = [] 
    self.subPlotFake = self.tabFake.fig.add_subplot(111) 

    print("here is OK; it exists ...", self.subPlotFake) 

    self.create_main_frame() 

    self.setModal(False) 
    self.setVisible(True) 
    self.show() 


def create_main_frame(self): 
    #Associate a Qwidget with the InventoryChartsWidget widget 

    print("OK here too; it exists ... ",self.subPlotFake) 

    self.main_frame = QtGui.QWidget() 
    LesTabs = QtGui.QTabWidget() 
    self.tabG = QtGui.QWidget() 

    #Fill the tab with Matplotlib object and draw the charts 
    self.tabG=self.create_tab(self.tabG) 
    self.on_draw_G(self.tabG) 
    self.tabG.fig.subplots_adjust(left=0.02,bottom=0.05,right=1,top=0.95,wspace=0.2,hspace=0.2) 

    LesTabs.addTab(self.tabG,"Chart") 

    grid = QGridLayout() 
    grid.addWidget(LesTabs, 0, 0) 
    self.main_frame.setLayout(grid) 
    self.setLayout(grid) 
    self.layout().addWidget(self.main_frame) 


def UpdatePlot_DataSelection(self): 
    #SLOT 
    print("Get connected here process the data in the subplot XX...") 


def on_draw_G(self,tab): 
    #Juts one subplot for test purpose 
    tab.fig.clear() 
    tab.plots = [] 
    subPlot = tab.fig.add_subplot(111) 
    subPlot.hold(False) 
    tab.plots.append(subPlot) 
    self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
    subPlot = tab.fig.add_subplot(122) 
    subPlot.hold(False) 
    tab.plots.append(subPlot) 
    self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
    tab.canvas.draw()  

def create_tab(self,tab):  
    #Create the tab widget, associated with Matplotlib plot 

    print("OK member exists ... ", self.xdata_start) 
    print("OK member exists ",self.tabFake) 

    #ISSUE HERE: don't understand 
    #print("NOT OK !!! member does not exist Why ? ",self.subPlotFake) 

    Conn=TheConnector() 
    #MATPLOTLIB 
    tab.fig = ChartFigure(Conn) 
    tab.canvas = FigureCanvas(tab.fig) 
    tab.canvas.setParent(tab) 
    tab.canvas.setFocusPolicy(Qt.StrongFocus) 
    tab.canvas.setFocus() 

    #connect signal to slot 
    Conn.selecteddataregion.connect(self.UpdatePlot_DataSelection) 

    tab.mpl_toolbar = NavigationToolbar(tab.canvas, tab) 

    vbox = QVBoxLayout() 
    vbox.addWidget(tab.canvas) 
    vbox.addWidget(tab.mpl_toolbar) 
    tab.setLayout(vbox) 

    tab.canvas.mpl_connect('button_press_event', tab.fig.onclick) 

    return tab  

def on_key_press(self, event): 
    #Keyboard input: standard mpl key press 
    key_press_handler(event, self.canvas, self.mpl_toolbar) 

def PlotData_G(self, plot, G_array, hdom_array): 
    # Plot G 
    plot.hold(False) 
    plot.scatter(x=hdom_array, y=G_array, marker='+',linewidths=1.5) 
    plot.set_autoscaley_on(True) 
    plot.tick_params(labelsize=8) 

def main(): 
app = QApplication(sys.argv) 
form = InventoryChartsWidget(xlimlow=0,xlimhigh=60,ylimlow=0,ylimhigh=80) 
form.show() 
app.exec_() 

if __name__ == "__main__": 
main() 

に使用する(選択の余地を)持っていませんQt;ここに私のサブプロットのIDが必要です)

ご協力いただければ幸いです。ありがとうございました。

+0

「厄介な」おそらく正しい単語です。私はそのような構造が意味をなさないケースを想像することはできません。このコードで問題を解決するには、slotが処理できるようにmatplotlibイベントを含むシグナルを出力するのが最もよいでしょう。もっと一般的に言えば、私はこれらの3つのクラスを持っていて、そのうちの1つでイベントをキャッチして、後でそれを他のクラスに移すという意味はありません。 – ImportanceOfBeingErnest

+0

イラストレーションコードを新鮮で独立して見ていただき、ありがとうございます。これはもちろん、質問の本質を説明する元のコードの非常に単純化された非常に短いバージョンです。 3つのクラスは意味があります(少なくとも要件が変更されるまで...)。イベントをキャッチして転送することについては、クラスのエンタングルメントではなく階層を維持することです( - >構造体)。 – vava

答えて

0

ここでは動作する解決策があります。真の制限は、我々はもちろんのことができます ...多分それが誰かを助けることができる(適切に変数が...それに使用を得ることができない宣言の欠如より具体的に)Pythonで

from __future__ import print_function 
from __future__ import division 

import sys 

from PyQt4 import QtGui 
from PyQt4 import QtCore 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

from matplotlib.figure import Figure 
from matplotlib.backend_bases import key_press_handler 
from matplotlib.backend_bases import Event 
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg as FigureCanvas, 
NavigationToolbar2QT as NavigationToolbar) 


#Connect InventoryChartsWidget to ChartFigure: QT 
class TheConnector(QtCore.QObject): 

    selecteddataregionARG=pyqtSignal(object,name='selecteddataregionIN') 

    def emitsignalEvent(self,TheEvent): 
     self.selecteddataregionARG.emit(TheEvent)  

#Chart including events: MATPLOTLIB 
class ChartFigure(Figure): 

def onclick(self,event): 
    #MAIN ISSUE 
    #HOW TO RETURN THE subplot axes to class InventoryChartsWidget class?  

    if event.button==1 : 
     print('Event: Axes is ... ', event.inaxes) 
     self.ConnSbPlt.emitsignalEvent(event.inaxes) 

def __init__(self,Conn): 
    #Init the Matplotlib  
    Figure.__init__(self) #initialize the orginal class, see also super() 
    super(ChartFigure, self).__init__() 
    self.canvas=FigureCanvas(self) 
    self.ConnSbPlt=Conn 

#Chart including events: QT 
class InventoryChartsWidget(QtGui.QDialog): 

def __init__(self, parent=None,xlimlow=0,xlimhigh=100,ylimlow=0,ylimhigh=100, G_array=[], N_array=[], ddom_array=[], hdom_array=[], speciesDict={}): 

    QMainWindow.__init__(self, parent) 

    #Fake stupid data 
    self.mG_array = [2] * 10 
    self.mHdom_array = [0.5] * 10 

    #jte to make sur I have it 
    self.xdata_start=-1.0 

    self.create_main_frame() 

    self.setModal(False) 
    self.setVisible(True) 
    self.show() 


def create_main_frame(self): 
    #Associate a Qwidget with the InventoryChartsWidget widget 

    self.main_frame = QtGui.QWidget() 
    LesTabs = QtGui.QTabWidget() 
    self.tabG = QtGui.QWidget() 

    #Fill the tab with Matplotlib object and draw the charts 
    self.tabG=self.create_tab(self.tabG) 
    self.on_draw_G(self.tabG) 
    self.tabG.fig.subplots_adjust(left=0.02,bottom=0.05,right=1,top=0.95,wspace=0.2,hspace=0.2) 

    LesTabs.addTab(self.tabG,"Chart") 

    grid = QGridLayout() 
    grid.addWidget(LesTabs, 0, 0) 
    self.main_frame.setLayout(grid) 
    self.setLayout(grid) 
    self.layout().addWidget(self.main_frame) 


def UpdatePlot_DataSelection_withArg(self,TheEvent): 
    #SLOT 
    print("WITH ARG : Get connected here process the data in the subplot XX...",TheEvent) 


def on_draw_G(self,tab): 
    #Juts one subplot for test purpose 
    tab.fig.clear() 
    tab.plots = [] 
    subPlot = tab.fig.add_subplot(111) 
    subPlot.hold(False) 
    tab.plots.append(subPlot) 
    self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
    subPlot = tab.fig.add_subplot(122) 
    subPlot.hold(False) 
    tab.plots.append(subPlot) 
    self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
    tab.canvas.draw()  

def create_tab(self,tab):  
    #Create the tab widget, associated with Matplotlib plot 

    Conn=TheConnector() 
    #MATPLOTLIB 
    tab.fig = ChartFigure(Conn) 
    tab.canvas = FigureCanvas(tab.fig) 
    tab.canvas.setParent(tab) 
    tab.canvas.setFocusPolicy(Qt.StrongFocus) 
    tab.canvas.setFocus() 

    #connect signal to slot 
    Conn.selecteddataregionARG.connect(lambda who="Three": self.UpdatePlot_DataSelection_withArg(who)) 

    tab.mpl_toolbar = NavigationToolbar(tab.canvas, tab) 

    vbox = QVBoxLayout() 
    vbox.addWidget(tab.canvas) 
    vbox.addWidget(tab.mpl_toolbar) 
    tab.setLayout(vbox) 

    tab.canvas.mpl_connect('button_press_event', tab.fig.onclick) 

    return tab  

def on_key_press(self, event): 
    #Keyboard input: standard mpl key press 
    key_press_handler(event, self.canvas, self.mpl_toolbar) 

def PlotData_G(self, plot, G_array, hdom_array): 
    # Plot G 
    plot.hold(False) 
    plot.scatter(x=hdom_array, y=G_array, marker='+',linewidths=1.5) 
    plot.set_autoscaley_on(True) 

def main(): 
app = QApplication(sys.argv) 
form = InventoryChartsWidget(xlimlow=0,xlimhigh=60,ylimlow=0,ylimhigh=80) 
form.show() 
app.exec_() 

if __name__ == "__main__": 
main() 

私の考えていました3つのクラスが理にかなっていると主張するが、これは別のトピックである。ここで

0

は、メインクラスにイベントを転送することができる方法である:

from __future__ import print_function 
from __future__ import division 

import sys 

from PyQt4 import QtGui 
from PyQt4 import QtCore 

from matplotlib.figure import Figure 
from matplotlib.backend_bases import key_press_handler 
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg as FigureCanvas, 
NavigationToolbar2QT as NavigationToolbar) 

#Connect InventoryChartsWidget to ChartFigure: QT 
class TheConnector(QtCore.QObject): 

    selecteddataregion=QtCore.pyqtSignal(object, name='selecteddataregion') 

    def emitsignal(self,xmin,xmax,ymin,ymax, event): 
     self.selecteddataregion.emit((xmin,xmax,ymin,ymax, event)) 

#Chart including events: MATPLOTLIB 
class ChartFigure(Figure): 

    def onclick(self,event): 
     #MAIN ISSUE 
     #HOW TO RETURN THE subplot axes to class InventoryChartsWidget?  

     if event.button==1 : 
      print('OK: Axes is ... ', event.inaxes) 
      self.ConnSbPlt.emitsignal(1.0,1.0,2.0,2.0, event) 


    def __init__(self,Conn): 
     #Init the Matplotlib  
     Figure.__init__(self) #initialize the orginal class, see also super() 
     super(ChartFigure, self).__init__() 
     self.canvas=FigureCanvas(self) 
     self.ConnSbPlt=Conn 

#Chart including events: QT 
class InventoryChartsWidget(QtGui.QDialog): 

    def __init__(self, parent=None,xlimlow=0,xlimhigh=100,ylimlow=0,ylimhigh=100, G_array=[], N_array=[], ddom_array=[], hdom_array=[], speciesDict={}): 

     QtGui.QMainWindow.__init__(self, parent) 

     #Fake stupid data 
     self.mG_array = [2] * 10 
     self.mHdom_array = [0.5] * 10 

     #jte to make sur I have it 
     self.xdata_start=-1.0 

     #fake plot to get a member of type subplot: UGLY! 
     #Attempt to create a member object "axes" 
     self.tabFake = QtGui.QWidget() 
     self.tabFake = self.create_tab(self.tabFake) 
     self.tabFake.plots = [] 
     self.subPlotFake = self.tabFake.fig.add_subplot(111) 

     print("here is OK; it exists ...", self.subPlotFake) 

     self.create_main_frame() 

     self.setModal(False) 
     self.setVisible(True) 
     self.show() 


    def create_main_frame(self): 
     #Associate a Qwidget with the InventoryChartsWidget widget 

     print("OK here too; it exists ... ",self.subPlotFake) 

     self.main_frame = QtGui.QWidget() 
     LesTabs = QtGui.QTabWidget() 
     self.tabG = QtGui.QWidget() 

     #Fill the tab with Matplotlib object and draw the charts 
     self.tabG=self.create_tab(self.tabG) 
     self.on_draw_G(self.tabG) 
     self.tabG.fig.subplots_adjust(left=0.02,bottom=0.05,right=1,top=0.95,wspace=0.2,hspace=0.2) 

     LesTabs.addTab(self.tabG,"Chart") 

     grid = QtGui.QGridLayout() 
     grid.addWidget(LesTabs, 0, 0) 
     self.main_frame.setLayout(grid) 
     self.setLayout(grid) 
     self.layout().addWidget(self.main_frame) 


    def UpdatePlot_DataSelection(self, transfer_object): 
     #SLOT 
     xmin,xmax,ymin,ymax, event = transfer_object 
     print ("Axes are now in the InventoryChartsWidget: ", event.inaxes) 


    def on_draw_G(self,tab): 
     #Juts one subplot for test purpose 
     tab.fig.clear() 
     tab.plots = [] 
     subPlot = tab.fig.add_subplot(111) 
     #subPlot.hold(False) 
     tab.plots.append(subPlot) 
     self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
     subPlot = tab.fig.add_subplot(122) 
     #subPlot.hold(False) 
     tab.plots.append(subPlot) 
     self.PlotData_G(subPlot,self.mG_array,self.mHdom_array) 
     tab.canvas.draw()  

    def create_tab(self,tab):  
     #Create the tab widget, associated with Matplotlib plot 

     print("OK member exists ... ", self.xdata_start) 
     print("OK member exists ",self.tabFake) 

     #ISSUE HERE: don't understand 
     #print("NOT OK !!! member does not exist Why ? ",self.subPlotFake) 
     # reason: self.subPlotFake does not yet exist 

     Conn=TheConnector() 
     #MATPLOTLIB 
     tab.fig = ChartFigure(Conn) 
     tab.canvas = FigureCanvas(tab.fig) 
     tab.canvas.setParent(tab) 
     tab.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) 
     tab.canvas.setFocus() 

     #connect signal to slot 
     Conn.selecteddataregion.connect(self.UpdatePlot_DataSelection) 

     tab.mpl_toolbar = NavigationToolbar(tab.canvas, tab) 

     vbox = QtGui.QVBoxLayout() 
     vbox.addWidget(tab.canvas) 
     vbox.addWidget(tab.mpl_toolbar) 
     tab.setLayout(vbox) 

     tab.canvas.mpl_connect('button_press_event', tab.fig.onclick) 

     return tab  

    def on_key_press(self, event): 
     #Keyboard input: standard mpl key press 
     key_press_handler(event, self.canvas, self.mpl_toolbar) 

    def PlotData_G(self, plot, G_array, hdom_array): 
     # Plot G 
     #plot.hold(False) #axes.hold is deprecated. 
     plot.scatter(x=hdom_array, y=G_array, marker='+',linewidths=1.5) 
     plot.set_autoscaley_on(True) 
     plot.tick_params(labelsize=8) 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    form = InventoryChartsWidget(xlimlow=0,xlimhigh=60,ylimlow=0,ylimhigh=80) 
    form.show() 
    app.exec_() 

if __name__ == "__main__": 
    main() 
関連する問題