wxPythonでMatplotlibを使う
wxFormBuilderでデスクトップアプリ作成の基礎 - メグタンの何でもブログの続き
起動用mainファイル
main.py
# -*- coding: utf-8 -*- import wx import win32gui import ctypes import o3dMain class MyApp(wx.App): def OnInit(self): frame = o3dMain.o3dMain(None) self.SetTopWindow(frame) frame.Show(True) return True try: ctypes.windll.shcore.SetProcessDpiAwareness(True) except: pass if __name__ == '__main__': if win32gui.FindWindow(None,"Open3Dtest") == 0: app = MyApp(False) app.MainLoop()
wxFormBuilder で作成された画面ファイル
このファイルは手修正してはいけない。
o3dtest.py
# -*- coding: utf-8 -*- ########################################################################### ## Python code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) ## http://www.wxformbuilder.org/ ## ## PLEASE DO *NOT* EDIT THIS FILE! ########################################################################### import wx import wx.xrc ########################################################################### ## Class Main ########################################################################### class Main ( wx.Frame ): def __init__( self, parent ): wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Open3Dtest", pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) self.SetSizeHints( wx.Size( 600,400 ), wx.DefaultSize ) self.SetFont( wx.Font( 10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, "メイリオ" ) ) self.m_menubar1 = wx.MenuBar( 0 ) self.m_menu1 = wx.Menu() self.m_menuOpen = wx.MenuItem( self.m_menu1, wx.ID_ANY, u"Open", wx.EmptyString, wx.ITEM_NORMAL ) self.m_menu1.Append( self.m_menuOpen ) self.m_menuClose = wx.MenuItem( self.m_menu1, wx.ID_ANY, u"Close", wx.EmptyString, wx.ITEM_NORMAL ) self.m_menu1.Append( self.m_menuClose ) self.m_menubar1.Append( self.m_menu1, u"File" ) self.SetMenuBar( self.m_menubar1 ) self.m_statusBar1 = self.CreateStatusBar( 1, wx.STB_SIZEGRIP, wx.ID_ANY ) bSizer1 = wx.BoxSizer( wx.HORIZONTAL ) self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) self.m_panel2.SetBackgroundColour( wx.Colour( 200, 255, 200 ) ) bSizer6 = wx.BoxSizer( wx.VERTICAL ) self.m_button1 = wx.Button( self.m_panel2, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0 ) bSizer6.Add( self.m_button1, 0, wx.ALL, 5 ) self.m_panel2.SetSizer( bSizer6 ) self.m_panel2.Layout() bSizer6.Fit( self.m_panel2 ) bSizer1.Add( self.m_panel2, 0, wx.EXPAND |wx.ALL, 5 ) self.m_panel4 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) self.m_panel4.SetBackgroundColour( wx.Colour( 255, 255, 225 ) ) bSizer1.Add( self.m_panel4, 1, wx.EXPAND |wx.ALL, 5 ) self.SetSizer( bSizer1 ) self.Layout() self.Centre( wx.BOTH ) # Connect Events self.Bind( wx.EVT_CLOSE, self.MainOnClose ) self.Bind( wx.EVT_MENU, self.m_menuOpenOnMenuSelection, id = self.m_menuOpen.GetId() ) self.Bind( wx.EVT_MENU, self.m_menuCloseOnMenuSelection, id = self.m_menuClose.GetId() ) self.m_button1.Bind( wx.EVT_BUTTON, self.m_button1OnButtonClick ) def __del__( self ): pass # Virtual event handlers, override them in your derived class def MainOnClose( self, event ): event.Skip() def m_menuOpenOnMenuSelection( self, event ): event.Skip() def m_menuCloseOnMenuSelection( self, event ): event.Skip() def m_button1OnButtonClick( self, event ): event.Skip()
自動生成された画面クラスを継承したクラスファイル
このファイルを自動生成するのは1度のみ。
このファイルを修正してプログラムを作るので、途中で自動生成すると上書きされて修正箇所が消えてしまう。
event.skipはそのイベントを下位の層に伝える事を意味する。
passは何もしない。
下記のようにmatplotlibを組み込むことで、wxpythonでmatplotlibが表示できる
o3dmain.py
"""Subclass of Main, which is generated by wxFormBuilder.""" import wx import o3dtest import numpy as np from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar import matplotlib.pyplot as plt # Implementing Main class o3dMain( o3dtest.Main ): def __init__( self, parent ): o3dtest.Main.__init__( self, parent ) # BoxSizerにmatplotlibのFigureCanvasを配置しm_panel4にセットする self.fig, self.ax = plt.subplots() self.figcan = FigureCanvas(self.m_panel4, -1, self.fig) self.CSizer = wx.BoxSizer( wx.VERTICAL ) self.CSizer.Add(self.figcan, 1, wx.EXPAND |wx.ALL, 0) self.m_panel4.SetSizer( self.CSizer ) self.m_panel4.Layout() # fig内のaxの位置を調整したい時 # self.fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9) # 背景に色を付ける時 # self.ax.set_facecolor([0.6,0.6,0.8]) # self.fig.set_facecolor([0.6,0.6,0.8]) # 縦横比を1にする(円が円として表示される)時 # self.ax.set_aspect('equal') # FigureCanvasのNavigationToolbarを有効化して # マウス操作で拡大縮小移動が出来るようにする # ツールバー自体は邪魔なので隠す # pキーでマウスドラッグで拡大縮小移動モード(トグル) # 左ボタンドラッグで移動 # 右ボタンドラッグで拡大縮小 # sキーで保存 # oキーでマウスドラッグエリアで拡大縮小モード(トグル) # 左ボタンエリア選択 拡大 # 右ボタンエリア選択 縮小 # rキーで初期表示状態 self.ntoolbar = NavigationToolbar(self.figcan) self.ntoolbar.Realize() self.ntoolbar.Hide() # FigureCanvas上のマウスイベントで独自の機能を持たせたい時には # 下記のようにイベント処理を追加すればいい # self.fig.canvas.mpl_connect('button_release_event', self.on_button_release) # self.fig.canvas.mpl_connect('button_press_event', self.on_button_press) # self.fig.canvas.mpl_connect('pick_event', self.on_pick) # self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion) # self.fig.canvas.mpl_connect('key_press_event', self.on_key_press) # サンプルデータ作成 self.SampleData() # 描画 self.fig.canvas.draw() # Handlers for Main events. def MainOnClose( self, event ): print("close process") #通常のクローズ処理へ event.Skip() def m_menuOpenOnMenuSelection( self, event ): pass def m_menuCloseOnMenuSelection( self, event ): print("Close menu selected") self.Close() def m_button1OnButtonClick( self, event ): print("button pushed") # SampleData 作成 def SampleData(self): x = np.linspace(0,10,100) y = np.random.randn(100) self.ax.plot(x,y,color ="red", linewidth=2, linestyle = "dashed")