これまでばらばらに実装してきた機能をまとめて"mylib.py"ファイルを作成しようと思います。
これまではスクリプトの本体は部品となるFormやButtonの作成と配置だけを行なってきましたが、今回はイベントハンドラも実装しているため、本体全体で一つのクラスを作成しています。 実質的な本体処理は最後の2行で行なわれています。
本体スクリプトだけで以前作成したスクリプトと同程度の分量がありますが、これは動的に配置する"No. X"ボタンをクリックした時に図のようなボタン名入りのMessageBoxを表示するようにしているためです。
# coding=Shift_JIS # @author: YasuhiroABE <yasu@yasundial.org> # import clr clr.AddReferenceByPartialName("System.Windows.Forms") clr.AddReferenceByPartialName("System.Drawing") import System from System.Windows.Forms import Form from System.Windows.Forms import FlowLayoutPanel from System.Windows.Forms import Button from System.Windows.Forms import MessageBox from System.Windows.Forms import DockStyle from System.Drawing import Size ## init Form object form = Form() form.Text = "Hello World!" form.Size = Size(300,200) ## init FlowLayoutPanel object flowLayout = FlowLayoutPanel() flowLayout.Size = form.Size flowLayout.Dock = DockStyle.Fill #flowLayout.AutoScroll = True ## 生成したButtonオブジェクトを記憶するリストです buttonList = [] ## setup add button addButton = Button() addButton.Text = "Add" def addButton_click(sender, arge): b = Button() b.Text = "No. " + str(len(buttonList)) flowLayout.Controls.Add(b) pass addButton.Click += addButton_click flowLayout.Controls.Add(addButton) ## setup del button delButton = Button() delButton.Text = "Delete" def delButton_click(sender, arge): if(len(buttonList) == 0): return b = buttonList.pop() flowLayout.Controls.Remove(b) pass delButton.Click += delButton_click flowLayout.Controls.Add(delButton) form.Controls.Add(flowLayout) System.Windows.Forms.Application.Run(form)
__all__ = ["MyForm", "MyButton", "MyFlowLayoutPanel"] from a07_lib.mylib import *
# coding=Shift_JIS # @author: YasuhiroABE <yasu@yasundial.org> # import System from a07_lib import * class Main: def __init__(self): self.form = MyForm("Hello World!") self.layout = MyFlowLayoutPanel() self.callback_buttonList = [] self.putButtons() pass def putButtons(self): addButton = MyButton("Add", "add new button") addButton.Click += self.callback_addButton self.layout.Controls.Add(addButton) delButton = MyButton("Del", "delete the last button") delButton.Click += self.callback_delButton self.layout.Controls.Add(delButton) pass def callback_addButton(self, sender, arge): b = MyButton("No. " + str(len(self.callback_buttonList)), "") b.Click += self.callback_button self.callback_buttonList.append(b) self.layout.Controls.Add(b) pass def callback_delButton(self, sender, arge): if(len(self.callback_buttonList) == 0): return b = self.callback_buttonList.pop() self.layout.Controls.Remove(b) pass def callback_button(self, sender, arge): msg = "Button: " + sender.Text + " clicked" System.Windows.Forms.MessageBox.Show(msg, "Notice") pass def run(self): self.form.Controls.Add(self.layout) self.form.run() ## main ## main = Main() main.run()
# encoding=Shift_JIS # @author: YasuhiroABE <yasu@yasundial.org> # import clr clr.AddReferenceByPartialName("System.Windows.Forms") clr.AddReferenceByPartialName("System.Drawing") import System from System.Windows.Forms import Form from System.Windows.Forms import Button from System.Windows.Forms import ToolTip from System.Windows.Forms import FlowLayoutPanel from System.Windows.Forms import DockStyle from System.Windows.Forms import ToolStripMenuItem from System.Windows.Forms import MenuStrip from System.Windows.Forms import MessageBox from System.Drawing import Size from System.Drawing import Point __all__ = ['MyForm','MyButton','MyFlowLayoutPanel'] size = Size(300,200) class MyForm(Form): def __init__(self, title): self.Size = size self.Text = title self.IsMdiContainer = True pass def setupMenu(self): self.ms = MenuStrip() self.windowNewMenu = ToolStripMenuItem("New", None) self.windowNewMenu.Click += self.windowNewMenu_onclick self.windowMenu = ToolStripMenuItem("Window") self.windowMenu.DropDownItems.Add(self.windowNewMenu) self.ms.MdiWindowListItem = self.windowMenu self.ms.Items.Add(self.windowMenu) self.ms.Dock = DockStyle.Top self.MainMenuStrip = self.ms self.Controls.Add(self.ms) pass def windowNewMenu_onclick(self, sender, arge): MessageBox.Show("Thank you for clicking on me!", "windowNewMenu_onclick") pass def run(self): self.setupMenu() System.Windows.Forms.Application.Run(self) pass class MyButton(Button): def __init__(self, name, tooltip): self.Text = name self.toolTip = MyToolTip() self.toolTip.SetToolTip(self, tooltip) pass def setLocation(self, x , y): self.Location = Point(x,y) pass class MyToolTip(ToolTip): def __init__(self): self.AutoPopDelay = 5000 self.InitialDelay = 1000 self.ReshowDelay = 500 self.ShowAlways = True pass pass class MyFlowLayoutPanel(FlowLayoutPanel): def __init__(self): self.Size = size self.Dock = DockStyle.Fill self.AutoScroll = True pass pass ## end ##
今回はスクリプト本体にイベントハンドラ用の(call_back_*)メソッドを作成しました。 メニューのようにMyFlowLayoutPanel側にメソッドを作成することもできましたが、柔軟性を確保するためにイベントハンドラは基本的にライブラリ側には置かないのが良いのだろうと思います。
Pythonはインデントに依存するため、if文やメソッド定義をくくるためにブレースなどの特別な記号は使いません。
その代りにスクリプトではpass
文を使っています。
これ自体に機能はありませんが、インデントが崩れたり、インデントレベルの違うコードをコピーしてきた時でもpass
を目印にインデントを調整する事ができるようになります。
エディタが狂ってしまい行頭の空白が全て潰れてしまった様子を想像してみてください。
pass
文は非常にコストの低い予防策になるでしょう。
全てのインデントが下がる手前に挿入しなければいけないので、少し難しいですけどね。
勝手に追加したコードのせいもありますが、以前作成したスクリプトとの行数での比較でみると2倍前後の差があります。 これで効率が高まったといえるのかどうか微妙な数字ですが、個人的には余計な機能を追加するぐらいの余裕はでてきたのかなと感じています。
ライブラリを作成する意義に迫るためにも、次回はテストについて考えていきます。
Created: 2010-03-13, Last modified: 2010-03-19
www.yasundial.org by Yasuhiro ABE is licensed under a Creative Commons Attribution 2.1 Japan License. Permissions beyond the scope of this license may be available at http://www.yasundial.org/info/license.html.