私の目標は、ユーザーがクリックしたサブプロットを特定することです。より正確には、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が必要です)
ご協力いただければ幸いです。ありがとうございました。
「厄介な」おそらく正しい単語です。私はそのような構造が意味をなさないケースを想像することはできません。このコードで問題を解決するには、slotが処理できるようにmatplotlibイベントを含むシグナルを出力するのが最もよいでしょう。もっと一般的に言えば、私はこれらの3つのクラスを持っていて、そのうちの1つでイベントをキャッチして、後でそれを他のクラスに移すという意味はありません。 – ImportanceOfBeingErnest
イラストレーションコードを新鮮で独立して見ていただき、ありがとうございます。これはもちろん、質問の本質を説明する元のコードの非常に単純化された非常に短いバージョンです。 3つのクラスは意味があります(少なくとも要件が変更されるまで...)。イベントをキャッチして転送することについては、クラスのエンタングルメントではなく階層を維持することです( - >構造体)。 – vava