これまでばらばらに実装してきた機能をまとめて"mylib.py"ファイルを作成しようと思います。


これまではスクリプトの本体は部品となるFormやButtonの作成と配置だけを行なってきましたが、今回はイベントハンドラも実装しているため、本体全体で一つのクラスを作成しています。 実質的な本体処理は最後の2行で行なわれています。
本体スクリプトだけで以前作成したスクリプトと同程度の分量がありますが、これは動的に配置する"No. X"ボタンをクリックした時に図のようなボタン名入りのMessageBoxを表示するようにしているためです。
オリジナル:03_04_form_flowlayout.ipy
# 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)
a07_lib\__init__.py
__all__ = ["MyForm", "MyButton", "MyFlowLayoutPanel"] from a07_lib.mylib import *
スクリプト本体:a07_flowlayout.ipy
# 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()ライブラリ: a07_lib\mylib.py
# 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.