トップ > 書籍サポート >

モンキーPython: 第2回 お絵かきプログラムを作ってみる

この文書は、Linux magazine 2005年1月号〜3月号に掲載された連載の草稿を、(株)アスキーLinux magazine編集部の許可を得て公開するものです。校正前の原稿なので読みづらいところもあるかと思います。不明な点などありましたらコメントをお送りください。


いろいろなオブジェクトを操れるようになると、作れるプログラムの幅が拡がります。今回は、いろいろなオブジェクトの使い方と、前回に説明していなかった基本的な文法について解説します。

今回の目次

  1. 前回のおさらい
  2. 基本的なオブジェクト
  3. 関数を定義する
  4. 名前空間とスコープ
  5. Tkinter
  6. クラスを定義する
  7. サンプル:お絵かきプログラム
  8. 色を変更する(オプションメニュー)
  9. 線の太さを変更する(スケール)
  10. 今回のまとめ

@ 前回のおさらい

簡単に前回のおさらいをしておきましょう。

  1. プログラムは、コンピュータに何かをさせるための命令を書き連ねたテキストファイルである。
  2. プログラムの命令は、文を単位として実行される。
  3. 命令には、関数呼び出し、オブジェクトのメソッド呼び出し、print文、変数への代入などがある。
  4. オブジェクトは、内部に構造(内部状態)を持ち、その操作のためのメソッドを持つ。
  5. オブジェクトのメソッドはクラスで定義される。オブジェクトを生成するには、クラス名を関数のようにして呼び出すか、スクリプトに値を直接書く。

特に、どのような関数があってどう呼び出すのか、どのようなクラスがあり、そのクラスでどのようなメソッドが定義されているのか、を覚えていくことが重要です。今回は、まずは、いろいろなオブジェクトの使い方を見ていきましょう。

@ 基本的なオブジェクト

最も基本的で、多用するオブジェクトは、数値と文字列です。また、データを格納するためのオブジェクトでよく使うものに、タプル、リストがあります。

■数値

Pythonでは、数値は(短い)整数、長整数、実数、複素数に分けられます。それぞれクラス名は次の表のとおりです。

区分クラス名
(短い)整数int
長整数long
実数 float
複素数complect

-(231-1)〜(231-1) の整数はint、それより大きい整数はlong、小数点以下のある数値はfloatとなります。intとlongはコンピュータ内部での都合で分けられていて、通常は使い分けを意識する必要はありません。floatは(これもコンピュータ内部の都合ですが)計算誤差が発生する場合があるので、小数点以下が不要なときは整数を使います。

次のスクリプトは、数値の四則演算を行います。

print 2 + 3 * 4   #=> 14
print (2 + 3) * 4 #=> 20
print 7 / 3       #=> 2
print 7.0 / 3     #=> 2.33333333333
print 2 ** 3      #=> 8

普通の計算順序どおりに、掛け算・割り算は足し算・引き算より先に行われます。括弧で囲めば括弧の内側のほうが先に計算されます。「x ** y」は、xのy乗を表します。

割り算は、実数の場合は小数点以下まで計算されますが、整数同士だと切り捨てられます。(正確には答がマイナス無限大の方向へ丸められます。)

■文字列

文字の連なりを文字列といいます。Pythonでは、文字列は「"」(ダブルクォーテーション)または「'」(シングルクォーテーション)で囲んで表します。文字列のクラスはstrです。

文字列同士は「+」で連結することができます(書き方は x + y)。数値であってもstr() 関数で文字列に変換すれば連結できます。

例えば、リスト1のようにして文字列を操作できます。

リスト1 文字列の操作
# -*- coding:utf-8 -*-
print "a" + "b"            #=> ab
print "a" + str(10)        #=> a10
s = "テキストABCabcテキスト"
print s.count("テキスト")  #=> 2
print s.lower()            #=> テキストabcabcテキスト
print s.find("abc")        #=> 15
print s[9:15]              #=> トABC
Note.

メソッドはオブジェクトのクラスごとに同じ名前を付けられる(たとえ違う内容であっても)ので、以下では必要に応じて、

クラス名#メソッド名
と書いて、どのクラスのメソッドなのかを明確にします。スクリプト上では、
対象オブジェクト.メソッド名(引数, ...)
と書くことに注意してください。

リスト1のそれぞれのメソッド(いずれもstrクラスのメソッド)の働きは次のとおりです。

count(文字列)
対象となる文字列オブジェクトの中に、引数の文字列がいくつあるか数えます。
lower()
対象文字列中の英大文字を小文字にした新しい文字列オブジェクトを生成します(対象オブジェクトは変更しない)。
find(文字列)
対象文字列から引数の文字列を検索し、最初に発見した位置(Note参照)を返します。

文字列オブジェクト[s:t]と書くと、先頭から数えて位置sから位置 (t - 1) までの文字で新しい文字列オブジェクトを作ります。

文字列には、通常モード(ASCIIモード)とUnicodeモードがあり、文字単位で扱いたいときは、文字列をUnicodeモードにします。

ASCIIモードでの文字位置と文字コード

Pythonでは、文字列操作での文字位置は0から始まる数値で、コンピュータ内部での文字の位置です。これはASCIIモードのときは文字単位ではないことに注意してください。

コンピュータ内部では、文字列はバラバラにされて数値の連なりとして格納されます。ある文字がどのような数値にするかは、そのときの文字コードによります。別の言い方をすると、文字コードは、ある文字をどのような数値列と対応づけるかの規則です。

文字コードは、歴史的な事情により、シフトJIS、EUC-JP、UTF-8などいくつもあります。第1回で、プログラムの文字コードはUTF-8にするように書きました。UTF-8では、半角の英数記号文字は1文字1バイトですが、全角ひらがな・カタカナ・記号・漢字は、1文字3バイト(一部2バイト)になります。

textβ
e6 97 a5e6 9c ace8 aa 9e74657874e2 98 86ce b2

同じ文字列をEUC-JPで保存すると、次のようになります。EUC-JPでは、全角文字は1文字2バイトになります。

textβ
c6 fccb dcb8 ec74657874a1 f9a6 c2

文字列をUnicodeモードにするには、スクリプト中で文字列を書くときに「"」あるいは「'」の前に「u」を付けます。Unicode文字列のクラスは、unicodeです。メソッドは、strクラスの文字列オブジェクトと同じものが使えます。

リスト2で、通常モード(ASCIIモード)とUnicodeモードで文字列の扱いがどう変わるか見てみます。

リスト2 モードによる文字列の扱い
s = "テキストABCABC"
print s.count("ト")       #=> 1
print s.find("A")         #=> 12
print s.lower()           #=> テキストabcABC

s = u"テキストABCABC"
print s.count(u"ト")      #=> 1
print s.find("A")         #=> 4
print s.lower()           #=> テキストabcabc

Unicodeモードでは、find() の結果(戻り値)が文字単位になっていることが分かります。lower()で全角文字も小文字になるようになります。

■タプルとリスト

数値や文字列だけでは複雑なデータを表すことはできません。そこで、複数のデータを束ねるための、データを格納できるオブジェクトを導入しましょう。

Pythonでは、タプル (tuple)リスト (list)などを用います。

タプルとリストはいずれも要素を一列にして格納します。タプルはいったん生成すると、要素の追加、削除はできません。リストは後から追加も削除もできます。この違い以外は、タプルとリストは同じように使えます。

リスト3は、タプルとリストを生成し、list#append() メソッドでリストに後ろ(右)から要素を追加します。文字列と同様に、[n]あるいは[lower:upper]で、要素を参照したり、一部分からなる新しいタプル、リストを作ることができます。

リスト3 タプルとリストの例
# タプル
t = (1, 2, "foo")
print t           #=> (1, 2, 'foo')
print t[1]        #=> 2
print t[0:2]      #=> (1, 2)

# リスト
list = [1, "hoge"]
list.append("foo")
print list        #=> [1, 'hoge', 'foo']

list = [1]
s = ["a", "b"]
list.append(s)
s.append("c")     
print list        #=> [1, ['a', 'b', 'c']]

格納すると言っても、オブジェクトの内部に要素が埋め込まれる訳ではありません。外から見ると格納されているように見えますが、内部ではオブジェクトへのリンクが張られています。リスト3で、変数sが指すリストに要素を追加すると、変数listのリストが変更されたように見えます。

図2 オブジェクトとオブジェクト空間

オブジェクトは、図2のようにオブジェクト空間に浮かんでいます。listの2番目の要素と変数sは同じオブジェクトを指しています。

@ 関数を定義する

前回掲載したサンプルプログラムでは、ウィンドウとボタンを表示しただけで、押しても何も起こりませんでした。今回は、ボタンを押すと文字列を出力するようにしてみます。自分で関数を定義します。

自分で関数を定義するには、次のようにします。

def 定義する関数名 ( 引数名, ... ) :
    文
    文
    ...

defの行の最後に「:」(コロン)を書き、次の行から行を字下げ(左側に空白を入れる)して、実行する文を書いていきます。字下げするのを止めたところがその関数の終わりになります。

例で見たほうが感じがつかめます。リスト4は、on_clicked()関数を定義して、ボタンが押されたときにターミナル画面に「ボタンが押された!」と表示します。

リスト4 on_clicked関数を定義した
import Tkinter

def on_clicked():
    print "ボタンが押された!"

window = Tkinter.Tk()
button = Tkinter.Button(window, text = "押してください。",
                        command = on_clicked)
button.pack()
window.mainloop()

Tkinter.Button()のキーワード引数commandで指定し、on_clicked()を登録します。ボタンが押された時には、Tk#mainloop()の中から登録された関数が呼び出されます。

@ 名前空間とスコープ

変数がオブジェクトを指すラベル(付箋)だということは、前回も解説しました。変数は、文脈によっては、同じ名前であっても別のオブジェクトを指すことがあります。ある変数が有効な範囲をスコープ(scope)といいます。

変数は名前空間の中にありますが、ある関数が呼び出されてその中の文が実行される時、新しい名前空間が導入されます。関数の引数、それから関数の中で代入した変数は、関数の外側の変数とは別の名前空間に属します。関数の中の文の実行が終わるときに、その関数の名前空間は消滅します。

次のプログラムは、関数fooの外側と内側で同じ名前の変数yを使っています。

y = 100
def foo(x):
    y = x * 2
    print "in foo(): y = ", y
foo(1)
foo(2)
print y

foo() の中で変数yに代入していますが、外側の変数yには影響しません(外側のyが指すオブジェクトは変わりません。)(図3)。このプログラムの実行結果は、次のようになります。

in foo(): y =  2
in foo(): y =  4
100

関数内でのみ有効な変数をローカル変数といいます。言い換えると、ローカル変数のスコープは関数です。なお、すべての関数のなかから参照できる変数をグローバル変数といいます。

図3 名前空間は入れ子

ただし、関数呼び出しでは、名前(変数)が新しく取られるだけで、オブジェクトがコピーされるわけではありません。引数として与えられた変数を介してオブジェクトを操作すると、その影響は呼び出した側にまで及びます。

次のプログラムは、リストを関数の中で変更します。メソッドの外側で生成したオブジェクトが変更されます。

def hoge(ary):
    ary.append(10)

ary = [1, 2, 3]
hoge(ary)
print ary  #=> [1, 2, 3, 10]

@ Tkinter

これまでのサンプルでは、ラベル、ボタンをウィンドウに貼り付けてきました。Tkinterには、それ以外にも、いろいろなものがあります。

■ウィジェット

ウィンドウに貼れるものをウィジェット (widget) といいます。

Note.

ウィジェットは、「コントロール」あるいは「コンポーネント」と呼ぶこともあります。

いくつかのウィジェットをウィンドウに並べてみます(リスト5)。実行すると、画面1のように表示されます。

リスト5 いろいろなウィジェット
# -*- coding:utf-8 -*-
import Tkinter

window = Tkinter.Tk()

Tkinter.Button(window, text = "ボタン").pack()
Tkinter.Checkbutton(window, text = "チェックボタン").pack()

entry = Tkinter.Entry(window)
entry.insert(Tkinter.END, "エントリ")
entry.pack()

frame = Tkinter.LabelFrame(window, text = "ラベル付きフレーム")
frame.pack()
Tkinter.Label(frame, text = "ラベル").pack()

listbox = Tkinter.Listbox(window, height = 3)
listbox.insert(Tkinter.END, "リストボックス")
listbox.insert(Tkinter.END, "項目2")
listbox.pack()

Tkinter.Scale(window, orient = Tkinter.HORIZONTAL).pack()
Tkinter.Spinbox(window).pack()

window.mainloop()
画面1 主なウィジェット

ウィジェットのクラスとその内容は表1のとおりです。それぞれのクラスの使い方は、紙面もないので、An Introduction to Tkinter などを参照してください。

表1 Tkinterのクラス
Tkinterクラス名内容
Widget
 Button 押しボタン
 Canvas キャンバス
 Checkbutton チェックボタン
 Entry エントリ(1行テキスト入力)
 Frame フレーム
 Label ラベル
 LabelFrame ラベル付きフレーム
 Listbox リストボックス
 Menu メニューバー
 Menubutton (推奨されない。MenuかOptionMenuを使う。)
  OptionMenu オプションメニュー
 Message (推奨されない。Labelを使う。)
 PanedWindow ペイン区切り
 Radiobutton ラジオボタン
 Scale スケール(スライダ)
 Scrollbar スクロールバー
 Spinbox スピンボックス
 Text 複数行テキスト入力

ウィジェットの機能のうち、共通の部分はWidgetクラスで定義されています。リファレンスマニュアルなどでは、調べたいウィジェットのクラスだけではなく、Widgetクラスも調べる必要があります。オプションメニューについても、OptionMenuクラス、Menubuttonクラス、Widgetクラスを遡って調べる必要があります。

■イベントの束縛

Tkinterでは、マウスのボタンが押された、ドラッグされた、キーボードのキーが打たれた、など、ユーザーがウィンドウ上で何らかのことをしたりすると、イベントとしてプログラムに伝えられます。

イベントは、マウスのボタンを押したときの座標、どのボタンを押したのか、どのキーを打ったのか、などの情報をまとめたものです。イベントを受け取るためには、あらかじめ関数を登録しておく必要があります。関数を登録しておくと、これらユーザーの操作などがあったときに、Tk#mainloop()の中からその関数が呼び出されます。

すでに見たように、押しボタン(Buttonクラス)では、commandキーワード引数で関数を登録しておけば、クリックしたときにその関数が呼び出されました。ウィジェット特有のイベントはこのように特別な指定方法がありますが、一般的なイベントは、bindメソッドでイベントと関数を結び付け(束縛)ます。

bindメソッドは次のように書きます。

    widgetオブジェクト . bind ( イベントを表す文字列, 関数・メソッド名 )

例えば、リスト7のようにします。「<Button-1>」は、マウスの左ボタンを押す、というイベントです。実際にイベントが発生したときには、イベントの情報を格納したオブジェクトを引数として、登録しておいた関数が呼び出されます。

リスト7 bind()メソッドで左ボタンを登録
# -*- coding:utf-8 -*
import Tkinter
import sys

def on_pressed(event):
  sys.exit()  # プログラムを終了

window = Tkinter.Tk()
label = Tkinter.Label(window, text = "ここでマウスボタンを押してください。")
label.bind("<Button-1>", on_pressed)
label.pack()
window.mainloop()

表2に、イベントの一部を掲げます。

表2 イベント(一部)
イベント内容
<Button-x>マウスのボタンが押された。xはボタン番号で、1=左ボタン、2=中ボタン、3=右ボタン
<Bx-Motion>マウスがドラッグされた。xはボタン番号。
<ButtonRelease-x>マウスのボタンが離された。xはボタン番号
<Double-Button-x>マウスがダブルクリックされた。xはボタン番号
<Enter>マウスポインタがウィジェットに重なった(入ってきた)。キーボードのEnterキーが押されたにあらず。
<Leave>マウスポインタがウィジェットから離れた

@ クラスを定義する

関数は、引数として与えられたオブジェクトと、関数内で生成したオブジェクト、グローバル変数しか参照できません。大きな仕事をするには、多くの関数が協力・分担して、いろいろなことができなければなりません。

図4 オブジェクトとメソッド

すでに見てきたように、それぞれのオブジェクトは多くのメソッドを持ち、これらがオブジェクトの内部情報を共有しています。外側から見ると、メソッドに対して指図することで(メソッド呼び出し)、オブジェクトを操作します(図4)。

我々もこのようなオブジェクトを作っていい頃合いです。オブジェクトの振る舞い(メソッド)は、クラスで定義します。

クラスを定義する文法は、次のようになります。

class 定義するクラス名 :
    メソッド定義など...

■メソッドを定義する

メソッドを定義する文法は、関数とほとんど同じで、次のようになります。

def 定義するメソッド名 ( 自オブジェクト変数名, 引数, ... ) :
    文...

関数定義と違うのは、最初の引数として操作対象となるオブジェクトを指す変数を用意することだけです。この変数の名前は何でもいいのですが、慣例的にselfとします。

字下げして文を書いたり、呼び出されるたびに新しい名前空間が導入されるのも同じです(ローカル変数のスコープも同じ)。

実際の書き方をリスト8に示します。__init__メソッドは、特別なメソッドで、オブジェクトが生成されるときに呼び出されます。

リスト8 クラスとメソッドを作る
# -*- coding:utf-8 -*-
class my_class:
    def __init__(self):
        self.value = 1000

    # 加算
    def add(self, v):
        self.value += v

    # 減算
    def sub(self, v):
        self.value -= v

    def get_value(self):
        return self.value

obj1 = my_class()
obj2 = my_class()
obj1.add(10)
obj2.sub(30)
print obj1.get_value(), obj2.get_value()  #=> 1010 970

■インスタンス変数

オブジェクトの内部状態を保持する変数をインスタンス変数といいます。インスタンス変数は、次のように書きます。

    オブジェクト . 変数名        # 文法

上記のリスト8では、self.value がインスタンス変数です。インスタンス変数は、オブジェクトが生成されるたびに作られ、オブジェクトのメソッドで共有できます。オブジェクトが消滅するまで生き続けます。

@ サンプル:お絵かきプログラム

それでは、これまでに見てきたことを踏まえて、ごく短いお絵かきプログラムを書いてみます(リスト9)。実行結果は、画面2のようになります。

どのようなことをしているか、順に見ていきましょう。

リスト9 お絵かきプログラム
# -*- coding:utf-8 -*-
import Tkinter
class Scribble:
def on_pressed(self, event): self.sx = event.x self.sy = event.y self.canvas.create_oval(self.sx, self.sy, event.x, event.y, outline = "red", width = 5)
def on_dragged(self, event): self.canvas.create_line(self.sx, self.sy, event.x, event.y, fill = "red", width = 5) self.sx = event.x self.sy = event.y
def __init__(self): window = Tkinter.Tk() self.canvas = Tkinter.Canvas(window, bg = "white", width = 300, height = 300) self.canvas.pack() quit_button = Tkinter.Button(window, text = "終了", command = window.quit) quit_button.pack(side = Tkinter.RIGHT) self.canvas.bind("<ButtonPress-1>", self.on_pressed) self.canvas.bind("<B1-Motion>", self.on_dragged) window.mainloop()
Scribble()
画面2 お絵かきプログラムの実行結果

(1) Scribble#__init__() (リスト9囲み3)

お絵かきのためのキャンバスオブジェクトと、プログラムを終了するためのボタンオブジェクトを作ります。キャンバスオブジェクトは、bg引数で背景を白に、widthとheightで大きさを指定します。

ボタンオブジェクトには、Tkinter.Tk#quitメソッドを登録しておきます。クリックされたら、このメソッドが呼び出され、プログラムが終了します。

キャンバスにはbind()でイベントを結び付けます。ユーザーがマウスの左ボタンを押したとき、マウスをドラッグしたときに、それぞれon_pressedメソッド、on_draggedメソッドが呼び出されるようにします。

(2) Scribble#on_pressed() (リスト9囲み1)

ボタンが押されたら点を描きます。Tkinter.Canvas#create_oval()は楕円を描くメソッドです。この上下左右の座標を1点にすることで、点を描きます。

インスタンス変数sx、syに現在位置を入れておきます。on_dragged()でこれを使います。

(3) Scribble#on_dragged() (リスト9囲み2)

マウスがドラッグされたときは、直前の座標との間に線を描けばうまくいきます。on_pressed()で保存した座標との間に、Tkinter.Canvas#create_line()で線を描きます。

その後、最後の座標(sx, sy)を更新しておきます。こうすることで、さらにマウスを動かしたときに、今度はここから次の座標まで線を引けます。

@ 色を変更する(オプションメニュー)

前節リスト9では、線の色と太さが一定でした。オプションメニューとスケールを使って、これらを変更できるようにしてみましょう。

Scribbleクラスに新しいメソッドを追加します(リスト10)。

リスト10 色を変更できるようにする
    def color_chooser(self, window):
        COLORS = ["red", "green", "blue", "#FF00FF", "black"] # ①
        self.color = Tkinter.StringVar()                      # ②
        self.color.set(COLORS[1])                             # ③
        b = Tkinter.OptionMenu(window, self.color, *COLORS)   # ④
        b.pack(side = Tkinter.LEFT)                           # ⑤

このメソッドは、オプションメニュー(OptionMenuクラス)オブジェクトを生成し、それをウィンドウに配置します。

このメソッドの動作を順に説明すると、

  1. オプションメニューに表示する色の選択肢のリストを生成します。色は、"red", "green"など色の名前を指定することも、"#FF00FF"のように赤、緑、青それぞれ00〜255(16進数で00〜FF)の範囲で指定することもできます。
  2. StringVarオブジェクトを生成します。このオブジェクトに、オプションメニューで選択された項目の文字列が格納されます。StringVarオブジェクトは、setメソッドで値を設定でき、getメソッドで値を読み取ることができます。
  3. オプションメニューで最初に表示する値をStringVar#set()で設定します。COLORS[n]で (n + 1) 番目の値が得られるので、ここでは2番目の"green"を設定することになります。
  4. OptionMenuオブジェクトを生成します。最初の引数として貼り付けるウィンドウのオブジェクトを、2番目の引数としてオプションメニューで選択された項目の値を格納するオブジェクトを指定します。3番目以降の引数で選択肢を指定します。COLORSの前の「*」は、リストの要素を展開する記号で、次のように書いたかのように動きます。
    Tkinter.OptionMenu(window, self.color, "red", "green", "blue", "#FF00FF", "black")
    
  5. OptionMenuオブジェクトのpackメソッドで、左詰めにします。

メソッドを作ったら、Scribble#__init__メソッドに、このメソッドを呼び出す文を追加します(リスト11)。

リスト11 color_chooserメソッドの呼び出しを追加
    def __init__(self):
        window = Tkinter.Tk()
        self.canvas = Tkinter.Canvas(window, bg = "white", 
                                     width = 300, height = 300)
        self.canvas.pack()
        self.color_chooser(window)
        quit_button = Tkinter.Button(window, text = "終了",
                                     command = window.quit)
        quit_button.pack(side = Tkinter.RIGHT)

さらに、点を打つところ、線を引くところを修正しておきます(リスト12)。

リスト12 点と線の描画部分の修正
    def on_pressed(self, event):
        self.sx = event.x
        self.sy = event.y
        self.canvas.create_oval(self.sx, self.sy, event.x, event.y,     
                                outline = self.color.get(), width = 5)

    def on_dragged(self, event):
        self.canvas.create_line(self.sx, self.sy, event.x, event.y,    
                                fill = self.color.get(), width = 5)
        self.sx = event.x
        self.sy = event.y

これで色を選べるようになりました(画面3)。

画面3 色の変更を追加

@ 線の太さを変更する(スケール)

今度は線の太さをスケールを使って変えられるようにしてみましょう。また新しいメソッドを作ります(リスト13)。

リスト13 線の太さを変更できるようにする
    def width_chooser(self, window):
        self.width = Tkinter.Scale(window, from_ = 1, to = 15,
                                   orient = Tkinter.HORIZONTAL)   # ①
        self.width.set(5)                                         # ②
        self.width.pack(side = Tkinter.LEFT)                      # ③

このメソッドは、スケールオブジェクトを生成し、ウィンドウに貼り付けます。

  1. Tkinter.Scale()でスケールオブジェクトを生成します。最初の引数にウィンドウのオブジェクトを指定します。キーワード引数from_とtoで、スケールの範囲を指定します。また、orientで方向を指定します。Tkinter.HORIZONTALだと水平方向のスケールになります。
  2. 最初の値(初期値)をScaleオブジェクトのsetメソッドで指定します。
  3. Scaleオブジェクトのpackメソッドで、左詰めで詰めます。

新しいメソッドを作成したら、Scribble#__init__()で、width_chooser()を呼び出す文を追加します。color_chooser()を呼び出す行の次がいいでしょう(リスト14)。

リスト14 width_chooserの呼び出し
        self.canvas = Tkinter.Canvas(window, bg = "white", width = 300, height = 300)
        self.canvas.pack()

        self.color_chooser(window)
        self.width_chooser(window)

        quit_button = Tkinter.Button(window, text = "終了",
                                     command = window.quit)
        quit_button.pack(side = Tkinter.RIGHT)

加えて、on_pressed(), on_dragged()も修正します。self.width.get()で現在のスケールの値を得ます。これでペンの太さと色を変えられるようになりました(画面4)。

画面4 線の太さの変更を追加

@ 今回のまとめ


トップ > 書籍サポート > モンキーPython: 第2回 お絵かきプログラムを作ってみる
このページについてのご感想・ご提案などをお寄せください。なお、コメントに「http:」、HTML aタグが含まれると送信されません。
評価: ◎ ← → ×
コメント:
お名前:
メールアドレス:
[Profile]  [Privacy Policy]  [Legal & Link]  [Site Map]  

banner Netsphere Laboratories http://www.nslabs.jp/

Copyright (c) HORIKAWA Hisashi. All rights reserved.

[PR]

はてなブックマークに追加  

サイト内検索:

[PR]