傀儡師の館.Python

傀儡師の館.Python

[Python] カテゴリの記事

全214件 (214件中 1-50件目)

1 2 3 4 5 >

2011.03.21

コメント(0)

  • Open JTalk を Python から使ってみる

    音声読み上げTwitterクライアントできたしかし、NVDAに付属している Open JTalk をベースとした日本語音声合成エンジンはなかなかのものである。NVDAのソースをちょっと見てみると、どうやら簡単に日本語音声合成エンジンを利用できそうだ。というわけで、早速 ymotongpooのTwCmdというコマンドライン版Twitterクライアントに組み込んでみた。あまり実用的ではないが、ちゃんとTLを日本語で読み上げてくれる。とあったので、久々、音声に興味が行く。以前、しばらくの間 VoiceText の Misaki を使うのに、電子かたりべプレイヤー の「高品質サービス」の契約結んで使っていたのだけれど、定期的に料金を払う必要があるのでやめてしまった(なんとなく音声合成を試す (2008.12.28) を書いた時期に使っていた)。ちなみに、アクト・ツー様のRSSニュース、Twitter読上げアプリに採用されました。 らしい。一太郎2011 の 詠太を含むパッケージを買うという手もあるか。でも、もう一太郎離れしちゃったのだよなぁ。VOICEROID+ 民安ともえ とか、VOICEROID+ 鷹の爪 吉田くん あたりもありだろうが、ちょっと癖が強すぎて...。【送料無料】VOICEROID+ 民安ともえ価格:7,839円(税込、送料別)とりあえず試してみるかと、まずは Open JTalk が使われている NonVisual Desktop Access (NVDA) をダウンロード。使ってみたら、思ったよりもよい。次に、上記の TwCmd も動かしてみた。一定時間ごとに自動的に読み上げさせるようにするとかしてもよいかな。ソースを見ると、なるほど簡単に Open JTalk が呼び出せるようになっている。必要なところだけ抜き出すと、下のような感じ。# -*- coding: utf-8 -*-import timefrom synthDrivers import _nvdajp_jtalk_nvdajp_jtalk.initialize()WAIT = 0.05texts = ["とてもおなかがすきました。", "何を食べようかなぁ。"]try: for text in texts: _nvdajp_jtalk.speak(unicode(text)) time.sleep(len(text)*WAIT) _nvdajp_jtalk.stop()except Exception, e: print eいいかもしれない。目が疲れているときは、音声で聞きたくなるのだな。でも、音声合成の声は長時間聴くと疲れるのが常。長時間しゃべらせて自分の疲労度をみる人体実験してみるかな。Python からパラメータとか調整するのはどうするのかな。それもちゃんとソース見て調べてみるか。何はともあれ、これはけっこう嬉しい。

    2011.02.06

    コメント(0)

  • Editra Gui Designer いいなぁと思ったけど、まだ実現は先なのね

    wxPython: Eguid ? Editra Gui Designer で マルチプラットフォーム対応のテキストエディタ「Editra」 の作者 Cody Precord さんが、Editra Gui Designer なるものを開発し始めたことを知る。ちなみに、Cody Precord さんは、"wxPython 2.8 Application Development Cookbook" の著者でもある。Eguid - Editra Gui DesignerwxPython-dev: Interface Builder Tool を見ると、アイデアを練っている段階なので、すぐに使えるところにはいかないだろうけど、どんなやりとりがされて、どんなものに仕上がっていくかというのをウォッチすると楽しいかもね。というか、日本人も参加して、日本語で問題がでないようなものになってくれると嬉しかったりしてと他力本願モード。こんな風にちゃっちゃと GUI プログラミングができるようになると嬉しいのにね。Python の場合、現状はこのあたりだろうけど、開発が止まってしまっていたり、いまいちなのだよね。Boa constructorPythonCardXRCedちなみに、Editraはけっこうよいなぁと思ったのだけれど、インラインで日本語入力できないのね。高機能なテキストエディタEditraと日本語入力について、wxStyledTextCtrlでの日本語入力に難がある件について など参照。で、Editra 日本語入力 その2、wx.stc.StyledTextCtrlで変換候補を正しく表示。Windows 上ではなんとかなるのか。でも、ちょっと手間がかかるな。PyShell なんかも、手を入れないと編集中の Pythonのプログラムを実行したときに日本語の入出力で問題あるのだよなぁ。関係ないけど、Android 端末を何か持つかなぁと思う今日このごろ。android-scripting 使えば、Python でもアプリが作れるのね。SL4A Video Help を見る。こんな動画もあった。ところで、Android も、IPA、Androidを標的とするボット型ウイルス「Geinimi」への注意を呼びかけ とかいう時代になってるのね。ついで。まったく関係ない話だが、The Evolution of a Python Programmer おもしろい。

    2011.01.23

    コメント(0)

  • Yahoo日本語係り受け解析 API の Python ラッパーを使ってみた

    wxPython 入門の続きは、ちょっとおやすみ。日本語係り受け解析システムといえば、奈良先端大松本研究室で開発された CaboCha があるが、何かと面倒なので、もっと簡単に係り受け解析ができないかということで、Yahoo! JAPAN のテキスト解析 日本語係り受け解析 を使うという手がある。「24時間以内で1つのアプリケーションIDにつき50000件のリクエストが上限」、「1リクエストの最大サイズを4KBに制限」という制限があるので大量に使う場合は困るだろうが、そこに収まる範囲であれば、便利だろう。これを Python から簡単に使えるようにするために、 Yahoo日本語係り受け解析APIのPythonラッパー を公開されている方がいらっしゃったので、ちょっと試してみた。使うためには、Yahoo! JAPAN デベロッパーネットワーク で、アプリケーションID を予め登録しておく必要がある。daservice.py をダウンロードして、site-packages に置いておくか、カレントディレクトリに置いておく。# -*- coding: utf-8 -*-from daservice import DAServiceappid = 'アプリケーションID をここに入れる'da = DAService(appid)for chunk in da.getChunkList('尖閣諸島は日本の領土です。'): print chunk, "->", chunk.dependenceChunkこれを実行すると、尖閣諸島は -> 領土です。日本の -> 領土です。領土です。 -> Noneのように、出力される。Windows のプロンプト上で実行するなら、print unicode(chunk), "->", unicode(chunk.dependenceChunk)とかして文字化けしないようにしてもよし( UTF-8 でそのまま出力すると文字化けして表示されるので )。ついでなので、wxPython で簡単な GUI を付けてみる。# -*- coding: utf-8 -*-import wxfrom daservice import DAServiceappid = 'Yahoo API のアプリケーションID をここに入れる'class KakariukePanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) # text control self.textField = wx.TextCtrl(self, pos=(10,10), size=(400, 50)) self.logger = wx.TextCtrl(self, pos=(10,70), size=(400,300), style=wx.TE_MULTILINE|wx.TE_READONLY) # ボタン self.post_button =wx.Button(self, label="解析する", pos=(410, 10)) self.clear_button =wx.Button(self, label="クリア", pos=(410, 70)) # イベント self.Bind(wx.EVT_BUTTON, self.OnClear,self.clear_button) self.Bind(wx.EVT_BUTTON, self.OnPost, self.post_button) # 係り受け self.da = DAService(appid) def OnClear(self,event): self.logger.Clear() self.textField.Clear() def OnPost(self,event): text = self.textField.GetValue() self.logger.AppendText("【原文】 %s\n\n" % text) for chunk in self.da.getChunkList(text): result = "%s -> %s\n" % (chunk,chunk.dependenceChunk) self.logger.AppendText(result) self.logger.AppendText("\n") self.textField.Clear()app = wx.App(False)frame = wx.Frame(None,title="係り受け解析", size=(520,440))panel = KakariukePanel(frame)frame.Show()app.MainLoop()ちなみに、今、 MASHUP AWARDS 6 が応募中みたいね。私は応募していないし、応募予定もなしだけど。締切り 11月8日。応募作品を見る と、143個応募されている。

    2010.10.24

    コメント(0)

  • wxPython 入門 (12)

    wPython.org の Getting Started をサカナに第十二弾。Getting started with wxPython でいうと、1 と 2 が終わって、3.Woking with Windows の 3.2 Sizer あたりの話題を引き続き。Getting Started のソースコードの例を見てみる。Sizer を使った箇所だけを抜き出してみる。(Frame.__init__ の中の記述から)self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)self.buttons = []for i in range(0, 6): self.buttons.append(wx.Button(self, -1, "Button &"+str(i))) self.sizer2.Add(self.buttons[i], 1, wx.EXPAND)# Use some sizers to see layout optionsself.sizer = wx.BoxSizer(wx.VERTICAL)self.sizer.Add(self.control, 1, wx.EXPAND)self.sizer.Add(self.sizer2, 0, wx.EXPAND)#Layout sizersself.SetSizer(self.sizer)self.SetAutoLayout(1)self.sizer.Fit(self)ここでは、sizer2 として、水平方向に部品を並べるボタン配置用の BoxSize を作り、そこに Button1 から Button6 6つのボタンを追加。さらに、垂直方向に部品を並べる BoxSizer を作って、control と sizer2 を追加している。これを実行すると、次のようになる。ウィンドウの大きさをいろいろ変えてみて実感してみる。self.sizer.Add(self.sizer2, 0,..) なので、縦方向のサイズは起動時と変わらないが、control の方は 1 なので、縦に伸ばせば、それに応じて広がる。ボタンは、size2 の中でリサイズするように指定されているので、横に広げたときに、横幅いっぱいに広がってくれる。パネルにラベルを付けてみる"Getting Started" には、入力フォームの値を wx.Validator でチェックして云々の話が若干書かれていているのだが、実例まで踏み込んでないのでここでは飛ばしておく。実際のアプリケーションを作ったら、入力フィールドで整数値の 0~99 を指定したときには処理をするけれど、それ以外であればエラーを出して云々とかいう処理が必要になって、そういう場合に、wx.Validator を使えるねというところで終わって、次に進む(そのうち、実例で扱う)。参考にしているのは、A Working Example: Our first label within a panel のあたりから。ここでは Panel と StaticText が出てくる。まずは StaticText で、指定した位置にユーザーが書き換えできない固定の文字列を表示する。Getting Started では Frame に StaticText を配置するようなコードになっているのだが、パネル (Panel)を作って、そこに配置してみた。# -*- coding: utf-8 -*-import wxclass ExamplePanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.SetBackgroundColour("silver") wx.StaticText(self, label="ラベル1 :", pos=(10, 10)) wx.StaticText(self, label="ラベル2 :", pos=(100, 10)) wx.StaticText(self, label="ラベル3 :", pos=(200, 10)) wx.StaticText(self, label="ラベル4 :", pos=(10, 30)) wx.StaticText(self, label="ラベル5 :", pos=(100, 30), size=(20, -1)) wx.StaticText(self, label="ラベル6 :", pos=(200, 30), size=(-1, 10)) wx.StaticText(self, label="ラベル7 :", pos=(10, 60), size=(200,-1)) wx.StaticText(self, label="ラベル8 :", pos=(30, 60)) wx.StaticText(self, label="ラベル9 :", pos=(200, 60)) app = wx.App(False)frame = wx.Frame(None)panel = ExamplePanel(frame)frame.Show()app.MainLoop()pos で x, y 座標を指定している。サイズは横幅だけ指定して、縦は、-1 で自動になっているので、フォントサイズに応じて、それが表示できるだけの高さが確保される。size は指定しなくても動く。ラベル5は、必要な横幅を文字幅より少ないポイント数で指定してみた。右側が表示しきれず途切れる。ラベル6 は縦幅を指定し、必要な文字丈より少なくしてみた。下の方が途切れる。size は (-1, -1) で自動計算にしておけば、無指定と同じで途切れることはない。ラベル7と 若干重なる位置にラベル8は置いてみた。あとから置いたラベル8が強い。ラベル7は sizeで必要幅以上を指定しているが関係なく上書きされる。ちなみに、wxPython のドキュメントによると、パネル(panel) は、さまざまなコントロールを配置するために使われるウィンドウで、通常フレーム上に配置される。親クラスの wxWindow クラスに最小限の機能を追加したもので、見た目も機能も Dialog に似ているが、parent はどのような window クラスも親とすることができるところが違い、柔軟性があるとのこと。

    2010.10.14

    コメント(0)

  • wxPython 入門 (11)

    wPython.org の Getting Started をサカナに第十一弾。Getting started with wxPython でいうと、1 と 2 が終わって、3.Woking with Windows の 3.2 Sizer あたりの話題から。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルを開くダイアログwxPython (9) (8) のソースコードwxPython (10) ウィンドウ配置の概要Sizer を使ったレイアウトを配置Frameの中に、wx.BoxSizer を使ってボタンを3つ、水平方向に並べてみる。# -*- coding: utf-8 -*-import wxclass MainWindow(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(200,-1)) # ボタンを作成 self.button_cupnudle = wx.Button(self, wx.ID_ANY, "カップヌードル") self.button_bigmac = wx.Button(self, wx.ID_ANY, "ビッグマック") self.button_gyudon = wx.Button(self, wx.ID_ANY, "牛丼") # 水平方向に並べる BoxSizer を作成 self.sizer = wx.BoxSizer(wx.HORIZONTAL) # ボタンを BoxSizer に追加 self.sizer.Add(self.button_cupnudle) self.sizer.Add(self.button_bigmac) self.sizer.Add(self.button_gyudon) # レイアウトを行う self.SetSizer(self.sizer) self.SetAutoLayout(True) self.sizer.Fit(self) # Frame を表示する。 self.Show() app = wx.App(False)frame = MainWindow(None, "Sizer サンプル")app.MainLoop()ウィンドウサイズを広げると次のようになる。self.sizer.Add(self.button_xxxx) でボタンをサイザーに追加に追加していき、SetSizer()でサイザーをセットし、SetAutoLayout()でレイアウトの自動化の指定を行い、Fit()でサイザーを Frame サイズにフィットさせる計算をする。そして Show() でフレーム表示。sizer.Add するときには、オプションを指定することができる。self.sizer.Add(self.button_xxx, 0) のように指定した場合、 0は、リサイズをするかどうか。0 にするとリサイズせず、 0 より大きい値を設定するとリサイズする(指定がないときは 0 を指定したのと同じ)。上記の例に変更して、1 を指定すると、サイズを広げたときに、次のようになる。試しに、牛丼だけ 0、それ以外は 1 にして広げてみると次のようになる。ウィンドウを広げても、牛丼だけサイズが変わらない。カップヌードルとビッグマックはウィンドウの幅に合わせて広がる。Size にさらにオプションを付けてみる。self.sizer.Add(self.button_xxx, 1, wx.EPAND)としたものが次の画像。ウィンドウのサイズにあわせて、縦横ともにボタンが広がるようになる。フレームを広げると、それに応じてボタンのサイズも大きくなる。BoxSizer が Frame にフィットするようにしているので、ボタンはフレームの中で隙間なく均等に広がる。ここでまた、牛丼だけ、self.sizer.Add(self.button_xxx, 0, wx.EPAND) とすると次のようになる。ボタンサイズ自体は、フレームにフィットしているものの、牛丼の横幅は、最初のままでリサイズされない。ちなみに、self.sizer = wx.BoxSizer(wx.HORIZONTAL) のところを、self.sizer = wx.BoxSizer(wx.VERTICAL) とすれば、縦方向に並ぶようになる。wx.EPAND が指定されているところは、いろいろな値をとることができる。割り当てられた横幅に対して、アイテムのをどちらの縁に合わせるかを指定する。ALLは HORIZONTAL または、VERTICAL の指定方向だけで、wx.EXAND の場合は、指定方向に関係なく全方位。wx.TOPwx.BOTTOMwx.LEFTwx.RIGHTwx.ALLアイテムをすべての方向に対してフィットさせる。wx.EXPAND縦横の比率を維持したまま、できるだけ大きいサイズでフィットさせる。wx.SHAPED自動的に最適値として計算された最小の大きさのまま固定。wx.FIXED_MINSIZE割り当てられたスペースの中での配置方法の指定。wx.ALIGN_CENTERwx.ALIGN_LEFTwx.ALIGN_RIGHTwx.ALIGN_TOPwx.ALIGN_BOTTOMwx.ALIGN_CENTER_VERTICALwx.ALIGN_CENTER_HORIZONTAL複数のフラグを指定する場合は、wx.FIXED_MINSIZE|wx.ALIGN_CENTER のように「 | 」でフラグをつないでいく。ちょっと極端な例だが、もし、次のように指定すれば、self.sizer.Add(self.button_cupnudle, 1, wx.SHAPED|wx.ALIGN_TOP)self.sizer.Add(self.button_bigmac, 0, wx.FIXED_MINSIZE|wx.ALIGN_CENTER_VERTICAL)self.sizer.Add(self.button_gyudon, 0, wx.FIXED_MINSIZE|wx.ALIGN_BOTTOM)こうなる。BoxSizer をうまく使えば、ウィンドウサイズを変えたときでも柔軟に対応できそうな感じ。

    2010.10.13

    コメント(0)

  • wxPython 入門 (10)

    wPython.org の Getting Started をサカナに第十弾。Getting started with wxPython でいうと、1 と 2 が終わって、3 Woking with Windows のあたりから。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルを開くダイアログwxPython (9) (8) のソースコードウィンドウ配置の概要ここから、ウィンドウをどのように扱い、配置するかなどの話が始まる。これまでは、Frame 、TextCtrl 、MenuBar、Menu, StatusBar, MessageDialog, FileDialog 程度の部品しかつかっていなかったが、実際にアプリケーションを作るとなると、もっとたくさんの部品を使う必要があるのは言うまでもない。さまざまな部品は、wxWindow のサブクラスになっていて、実にたくさんのものがある。たとえば、フレームにツールバーを追加するための、wx.ToolBar や、wx.Control オブジェクトを部品として、複数のオブジェクトを配置するための入れ物となるパネル (wx.Panel)、ユーザが直接変更できない文字列を表示するための wx.StaticText、ドロップダウンリストから選択もできるし直接文字列の入力も可能な wx.ComboBox をはじめとして、いろいろなものがあるので、じっくり覚えていかなければならない。それと同時に、どのようにしたら部品をウィンドウ上に配置していくことができるのかも覚えなければならない。たとえば、図のようにアプリケーションのウィンドウとして wx.Frame、そこに wx.MenuBar と wx.Panel を配置し、さらに wx.Panel の中に wx.StaticText や wxTextCtrl などの部品を配置していくというイメージ図になる。図は、Getting started with wxPython より拝借。実際には、どのように部品を視覚的に配置するのか。次のような方法が考えられる。がんばってピクセル単位で、どの位置にどの部品を置くかを決める。wx.LayoutConstraints を使う。Delphai-like な LayoutAnchors を使う。wxSizer のサブクラスを使う1. は、あまりに面倒だし、プラットフォーム(OS)が変わったときにどう対応するか、フォントサイズが異なるときにどうするか等々、融通が利かないのでお勧めできないとされる。2. は複雑で使うのが難しい。3. wx.LayoutConstraints を使いやすくしてくれるので候補には入る。4. Getting Started で取り扱うのはこれ。Started Guide を書いた人が慣れ親しんでいるということで、記事は wx.Sizer がメインになる。ここで Window Layoutを見てみると、wxLayoutConstraints の例なども載っている。b = wxButton(self.panelA, 100, ' Panel A ')lc = wxLayoutConstraints()lc.centreX.SameAs (self.panelA, wxCentreX)lc.centreY.SameAs (self.panelA, wxCentreY)lc.height.AsIs ()lc.width.PercentOf (self.panelA, wxWidth, 50)b.SetConstraints(lc) その名のとおり、部品の制約条件を指定して配置するのだな。ボタンはパネルの真ん中に位置し、パネルは親ウィンドウに対して、幅50% にする等、部品の位置関係を中心に記述していくようなもののようだ。確かに大変そう。"Window Layout" の "4. Resources " は、XRCed のようなリソースエディタを使う話だと思うが、wxPython GUI リソースエディタ XRCedや XRCedの使い方 XRCedは一癖あります など参照。こういうものを使うと、GUI で部品の配置ができるから楽かもしれないですねと言いつつ、まずは、Size を学習するのでありました。XRCed や wxGlade、Boa Constructor, PythonCard などビジュアル系はそのうち扱うが、とりあえず無視してゴリゴリコードを書く系のみ見ていく。"Getting Stated"の Sizer の話に戻る。Sizer で部品を配置するSizer は、wx.Sizer のサブクラスで、フレームの中で部品をどのように配置するかを自動的に計算して配置してくれる。Tkinter とか使っていた人には、pack していくイメージを思い浮かべるとよいのかな。視覚的な部品のサイズが適切になるように自動的に計算してくれる。ルールに従って、部品の位置を決めてくれる。フレームのサイズが変更されたときに、動的に部品のサイズを変更したり、再配置してくれる。Sizer には、いくつかの種類がある。wx.BoxSizer: 水平方向(HORIZONTAL)か、垂直方向(VERTICAL) の直線状に部品を配置する。wx.GridSizer: 視覚的な部品をグリッドライクな構造で配置する。wx.FlexGridSize: wx.GridSIzer に似ているが、より柔軟なレイアウトを取ることができる。Sizer を使うときには、配置の対象となる wx.Window オブジェクトを sizer.Add(window, options...) のように配置対象のリストに追加し、その後、それらの部品を配置する。 sizer.AddMany(...).もある。イメージ的にいうと、箱の中に、縦方向に部品を詰め込んで並べていくか、横方向に詰め込んでいくかという感じ。Sizer は入れ子にできるので、たとえば、水平方向に3つのボタンを並べる wx.BoxSizer を作って、さらに同じものを作って、2つの BoxSizer を別の BoxSizer に垂直方向に並べるといったことができる。図は、Getting started with wxPython より拝借。上記は、都合 6つのボタンがあるが、もし、これを1つの Sizer の中で配置しようとするならば、wx.GridSizer を使ってねということになる(6つのマス目に部品を置いていく)。もう少補足として、XRCedの使い方 XRCedは一癖あります の 【3.4】 サイザーに関するルール を参照してみる。【3.4.1】 wxSizer全般に通じるルールwxFrame/wxDialog/wxPanelには唯一の子wxSizerを持つことができる。wxFrame/wxDialog/wxPanelのサイズは子wxSizerにフィットしようとする。wxSizerは複数の子を持つことができる。wxSizerの子になれるのはwxSizerおよびwxPanelとその他のコントロール。wxSizerは親からのサイズ指示がない限りすべての子が収まる最小のサイズになる。wxSizerの子になったものは、wxSizerItemとしての機能が追加される。wxSizerは横方向か縦方向かというレイアウトの方向を持っている。FrameやPanel に、いきなり BoxSizer を 2つ置くとかいうことはできず、まず、Frame や Panel にフィットする BoxSizer を作って、その中に 2つの BoxSizer をつくらなければならないということになるのね。Sizer のドキュメントを次にまとめておく。Type Sizerwx.BoxSizerwx.StaticBoxSizerwx.BoxSizerwx.GridSizerwx.FlexGridSizerwx.GridBagSizer今日はここまでで、実例は次のエントリーで。

    2010.10.13

    コメント(0)

  • wxPython 入門 (9)

    wPython.org の Getting Started をサカナに第九弾。Getting started with wxPython でいうと、2.4 まで終わらせて、とりあえず、ここまで書けるようになったというソースコード。メニューは、__init__ の中に詰め込まないで別のメソッドにまとめた方がいいかもねとか、そういうことまではしていないので __init__ がやけに長いので、SetupMenu メソッドを作ってまとめておくことにした。ということで、ここまでのソースコードのまとめ。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルダイアログとファイルの読み込み# -*- coding: utf-8 -*-import wximport osclass MyFrame(wx.Frame): """ 簡易エディタ """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # メニューバーを作成する self.SetupMenu() # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) def SetupMenu(self): # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー menuNew = file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") menuOpen = file_menu.Append(wx.ID_OPEN, "開く (&F)", "ファイルを開きます") menuSave = file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") menuSaveas = file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー menuUndo = edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") menuCut = edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") menuCopy = edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") menuPaste = edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー menuHelp = help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") menuAbout = help_menu.Append(wx.ID_ABOUT, "バージョン情報 (&A)", "プログラムのヘルプを表示します") # メニューバーを作成し、個々のメニューをメニューバーに追加していく menuBar = wx.MenuBar() menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(help_menu, "ヘルプ (&H)") # 個々のメニューアイテムを、イベントハンドラーにバインドする self.Bind(wx.EVT_MENU, self.OnNew, menuNew) self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen) self.Bind(wx.EVT_MENU, self.OnSave, menuSave) self.Bind(wx.EVT_MENU, self.OnSaveas, menuSaveas) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Bind(wx.EVT_MENU, self.OnUndo, menuUndo) self.Bind(wx.EVT_MENU, self.OnCut, menuCut) self.Bind(wx.EVT_MENU, self.OnCopy, menuCopy) self.Bind(wx.EVT_MENU, self.OnPaste, menuPaste) self.Bind(wx.EVT_MENU, self.OnHelp, menuHelp) self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) # メニューバーを Frame にセットする self.SetMenuBar(menuBar) def OnNew(self, event): print "Select New" def OnOpen(self,e): """ ファイルを開く """ # ホームディレクトリを開くようにする self.dirname = os.getenv("HOME") or os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") # フィルタ文字列のセット filters = 'Python files (*.py;*.pyw) | *.py;*.pyw | txt files (*.txt)|*.txt| All files (*.*)|*.*' dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "デフォルトのファイル名", filters, wx.OPEN) if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetFilename() self.dirname = dlg.GetDirectory() f = open(os.path.join(self.dirname, self.filename), 'r') self.control.SetValue(f.read()) f.close() dlg.Destroy() def OnSave(self, event): print "Select Save" def OnSaveas(self, event): print "Select Save As" def OnUndo(self, event): print "Select Undo" def OnCut(self, event): print "Select Cut" def OnCopy(self, event): print "Select Copy" def OnPaste(self, event): print "Select Paste" def OnHelp(self, event): print "Select Help" def OnAbout(self, event): # OK ボタンがついたメッセージダイアログを表示する。 # dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ") dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ", wx.OK|wx.STAY_ON_TOP) # ダイアログの表示 dlg.ShowModal() # ダイアログの終了時にダイアログオブジェクトを破棄する #dlg.Destroy() self.dlg = dlg def OnExit(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "簡易エディタを終了してもよいですか", "簡易エディタ", wx.YES_NO|wx.ICON_QUESTION) # ダイアログの表示 response = dlg.ShowModal() # 「はい」なら終了 if response == wx.ID_YES: dlg.Destroy() self.Close(True) # 「いいえ」なら、ダイアログを閉じるだけ elif response == wx.ID_NO: dlg.Destroy()app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()

    2010.10.09

    コメント(0)

  • wxPython 入門 (8)

    wPython.org の Getting Started をサカナに第八弾。Getting started with wxPython でいうと、2.3 から 2.4 のあたりの続き。今回は、ファイルを開くダイアログを作ってみる。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython 入門 (5) イベントとバインドwxPython 入門 (6) (5) のソースコードwxPython 入門 (7) プログラムの終了とダイアログの表示ファイルを開くダイアログを作ってみるファイルを開くには、OS 標準のファイルを開くダイアログを呼び出してくれる FileDialog がある。独自のダイアログではなくて、OS 標準のものなので、見た目や使い勝手で浮いてしまうことがない。選択したあとに、「開く」ボタンで 終了したかどうか(キャンセルボタンが押されたのではない)を if dlg.ShowModal() == wx.ID_OK: で確認して、その上で、GetFilename() と、GetDirectory() でファイル名とディレクトリ名を取り出す。そして、os.path.join でパス名を完成させる。そして、ファイルをオープンし(open)、read() で中身を読み込み、control.SetValue() でテキストコントロールにセットしている。読み終わったらファイルを閉じ(close)、ダイアログ終了時には、ダイアログを Destroy() で破棄している。 def OnOpen(self,e): """ ファイルを開く """ self.dirname = '' dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN) if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetFilename() self.dirname = dlg.GetDirectory() f = open(os.path.join(self.dirname, self.filename), 'r') self.control.SetValue(f.read()) f.close() dlg.Destroy()そうすると、こうなる。FileDialog の引数は、(self, parent, message=FileSelectorPromptStr, defaultDir=EmptyString, defaultFile=EmptyString, wildcard=FileSelectorDefaultWildcardStr, style=FD_DEFAULT_STYLE, pos=DefaultPosition) wx.OPEN となっているところは、お作法的には wx.FD_OPEN が正しいような気もするが、>>>wx.FD_OPEN1>>>wx.OPEN1定義されている値が共に 1 で同じだから、動く。他の wx.FD_SAVE、wx.FD_OVERWRITE_PROMPT、wx.FD_MULTIPLE、wx.FD_CHANGE_DIR なども、FD_ がなくても、すべて同じ値になっているので問題ないけど。どうなんだろうな。けっこう短縮形を使っていることが多い。Style Guide for wxPython code とか見ても、書いてないし、"Simple is better than complex." で短縮形でよいということかな。デフォルトで開くディレクトリ(DefaultDir) に関しては、self.dirname = os.getcwd() として、プログラムを起動したカレントディレクトリや、self.dirname = os.getenv("HOME") or os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH")等として、ユーザーのホームディレクトリをファイルを開くときの基準にするということもできる。デフォルトファイル(defaultFile) を "" ではなく、"sample.txt" とか入れておくと、ファイル名のところに "sample.txt" が入った上で、ダイアログが開く。ファイルを開くダイアログで選択ファイルの拡張子を指定するここで、指定したファイルの拡張子を指定したいとかいうことになったらどうなるか。たとえば、python のファイルにフィルタをかけたくて、 "*.*" の箇所を変更する。Python のファイルには、*.py と *.pyw にフィルタをかけて表示したい。この場合、次のようになる。dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN)をfilters = 'Python files (*.py;*.pyw) | *.py;*.pyw'dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN)とすれば、Python のファイルだけを表示することができる。でも、プルダウンでいろいろな種類を選択したいよねということであれば、 filters = 'Python files (*.py;*.pyw) | *.py;*.pyw | txt files (*.txt)|*.txt| All files (*.*)|*.*' のように "表示1|拡張子1|表示2|拡張子2|表示3|拡張子4" のように複数並べていれてやればよい。これで Python files、txt files, All files がフィルタとして選択できるようになる。 エラー処理がないから、存在しないファイル名を指定されると困る。なので、os.path.isfile でファイルがあるかどうかを確認した上で open しようとか、開けなければエラーメッセージ出しましょうとか、日本語の文字コードがいろいろあるファイルを読み込んだときのことを考えて、コードを変換した上で読み込むとかしたいところかもしれないのだが、ここではやらないで、後の機会に残しておく。文字コードを判定して、codecs.open で開けばよいだけなのだが。 ここまでで、Getting started with wxPython の 2.4 あたりまでをカバーした。2.5 Possible extensions で、いろいろな拡張があるよという存在だけが示されている。Drag and DropMDITab view/multiple filesFind/Replace dialogPrint dialog (Printing)Macro-commands in python ( using the eval function)etc ...このブログでも、これに合わせて、詳細にとりあえず立ち入らず、いったんここで話題を変えることにする(別ネタで扱う予定)。

    2010.10.09

    コメント(0)

  • wxPython 入門 (7)

    wxPython.org の Getting Started をサカナに第七弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更してみた。そして、メニューやステータスバーを付け、さらにメニューイベントに対応した処理をバインドしてというところまでやった。今回は、イベントハンドラーのメソッドの中に少し処理を入れてみる。ひとつは、プログラムを終了するという単純なところと、もうひとつはダイアログを出すところ。Getting started with wxPython でいうと、2.3 から 2.4 のあたり。全部で 12項目あるのでまだまだこのネタは続くのであった。さらに次のネタもみつけてあるので、当面 wxPython 入門は続きそう。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython 入門 (5) イベントとバインドwxPython 入門 (6) (5) のソースコードwxPython のプログラムを終了するwxPython で書かれたプログラムを終了するには、コマンドラインから起動した場合には、コマンドライン上で Ctrl-C を入力して強制的に終了させるかw、ウィンドウの右上の × をクリックして終了させることもできる。でも、ちゃんとプログラム独自に終了させることもできるようにしましょうということで、[ファイル]メニュー - [終了] を選択するとプログラムが終了できるようにする。これはいたって簡単。メニューを選択したときに、イベントハンドラーの中で、ウィンドウ(Frame) を Close(True) してやればよい。それだけ。次のものは、単純にするために必要な箇所だけのコード。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューから終了する """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) file_menu= wx.Menu() # Exitメニューアイテムのオブジェクト (バインドするときのソース) menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # メニューバーオブジェクトを作って、そこにファイルメニューオブジェクトを追加 menuBar = wx.MenuBar() self.SetMenuBar(menuBar) menuBar.Append(file_menu,"ファイル (&F)") # イベントに対して、ハンドラとソースをバインドする self.Bind(wx.EVT_MENU, self.OnExit, menuExit) # 表示 self.Show(True) # 終了のためのメソッド def OnExit(self,e): self.Close(True)app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()終了を選択するとあっさりと、プログラムは終了する。ダイアログを表示する[ヘルプ]メニュー -[バージョン情報] を選択すると、About ダイアログが表示されるようにしてみる。これも同じようにメニューイベントのハンドラを書いてあげる。前回のwxPython (6) (5) のソースコードをベースに追加修正する。ダイアログを表示するのは、wx.MessageDialog。引数は、messageDialog(parent=None, message='', caption='Message', style = wx.OK | wx.CANCEL | wx.CENTRE, pos=wx.DefaultPosition) 。def OnAbout(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ", wx.OK) # ダイアログの表示 dlg.ShowModal() # ダイアログの終了時にダイアログオブジェクトを破棄する dlg.Destroy()ダイアログのスタイルで、style= wx.YES_NO とすれば、「はい」と「いいえ」のボタンが表示される。何も指定しなければ、style=wx.OK|wx.CANCEL|wx.CENTRE が指定されたのと同じことになるので、「OK」 と 「キャンセル」ボタンが表示される。スタイル (style) は、wx.OK、wx.CANCEL、wx.YES_NO と wx.YES_DEFAULT、wx.NO_DEFAULT、さらに、wx.ICON_EXCLAMATION、wx.ICON_INFORMATION、wx.ICON_HAND, wx.ICON_ERROR, wx.ICON_QUESTION, wx.ICON_INFORMATION, wx.STAY_ON_TOP を組み合わせて指定可能。アイコンの種類を変更したいときは、たとえば、wx.OK| wx.ICON_ERROR と | でつないで指定してやればよい。デフォルトは、ICON_INFORMATION。wx.STAY_ON_TOP を付けてやると、ダイアログが常に一番上のウィンドウとして表示されるので、他のプログラムのウィンドウの下に隠れてしまうということがなくなる。MessageDialog では、Frame やメニューを作るときと違って引数に ID が指定されていないが、これは内部で自動的に id = wx.ID_ANY(実際は -1 だったりもする)で、自動的に ID が割り当てられているから。一番単純には、wx.MessageDialog(self, "メッセージ") だけでも動くが、タイトルキャプションも付けると、wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ")で、この場合、こうなる。wx.ICON_QUESTION の場合、アイコンが次のようになる。ダイアログを表示するときに showModal() とする。フレームのときは、フレームのときは Show() だったのでちょっと違う。モーダル(Modal) は、このダイアログが表示されている間、ダイアログにフォーカスがあたり、OK か Cancel が押されるまで、他に何もできないように作られているタイプのもの。つまり、この手のダイアログの類を作ったときには、ShowModal() を使う。また、Show() にしても何も表示されない。最後に Destroy() をしないと、OK をクリックすればダイアログは消えるものの、オブジェクトがきちんと破棄されず、MessageDialog が呼び出されるたびに新しいオブジェクトが作られ続ける。つまり、ダイアログのオブジェクトは明示的に破棄しないと、プログラム終了までメモリ内に残ってしまうので注意が必要。OK, Cancel ダイアログを追加してみるダイアログで複数のボタンがあるようなものを表示し、どちらのボタンが押されたかを処理に使いたい場合はどうしたらよいか。ということで、そのサンプルを載せておく。前のダイアログでは OK だけしか表示せず、その返答も捨てていたが、ここでは何のボタンが押されたかを確認したうえで処理する。ShowModal() を呼ぶと、その結果を取れるので、 if dlg.ShowModal() == wx.ID_OK: のような処理を書けばよいことになる(ShowModal() は、wx.ID_YES、wx.ID_NO、wx.ID_CANCEL、wx.ID_OKのいずれかを返す)。終了メニューが選択されたときに、ほんとうに終了してもよいですかと表示して、OK なら終了。Cancel ならダイアログだけを閉じて、メインのフレームに戻るようにしてみる。def OnExit(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "簡易エディタを終了してもよいですか", "簡易エディタ", wx.YES_NO|wx.ICON_EXCLAMATION) # ダイアログの表示と返答の取り出し response = dlg.ShowModal() # 「はい」なら終了 if response == wx.ID_YES: dlg.Destroy() self.Close(True) # 「いいえ」なら、ダイアログを閉じるだけ elif response == wx.ID_NO: dlg.Destroy()

    2010.10.09

    コメント(0)

  • 時報を Beep 音で鳴らそうとしたら、意外な厳しさがあった

    35.4. winsound ? Windows 用の音声再生インタフェース を使っている Python Tuner (電気羊の羊小屋 )を見て、ふと思った。winsound.Beep(周波数:Hz, 鳴らす時間:ミリ秒) で、PCのスピーカーを鳴らすことができる。440Hz といえば A(ラ) の音。基準の周波数。ギターをやっていたころは、よく聴いた音。音叉を咥えてもだえていたなぁ。チューナーの基礎知識 みたいな機械的なチューナーを使ったりもしたが、直接耳で聴くほうが気持ちがいい。440Hz に洗脳されてしまっている。import winsoundwinsound.Beep(440,500)440Hz の倍音は 880Hz。この音のつながりは、時報だ。NHK の時報みたいにしてみようと調べてみる。NHKの時報について を見ると、57秒、58秒、59秒に 440Hz の音を 100ミリ秒ならし、0秒で 880Hz を鳴らすとある。PCで実際にやってみると、100ms だと気持ちよくないので少し伸ばして 150ms にしてみた。import winsoundimport timedef time_signal(): for i in range(3): winsound.Beep(440,150) time.sleep(0.85) winsound.Beep(880,1400)if __name__ == '__main__': times_signal()時報っぽい音に聞こえるかな。でも、880Hz の音を減衰させていくことができないから不自然。だんだんと小さくなって消えて欲しいのだが。。。動作確認できたら、これを 適当なファイル名.pyw で保存して、Windows だったらタスクマネージャに登録して。毎時間時報がなるようにしてみた。拡張子 pyw にしておけば、黒いコマンドプロンプトの画面が表示されずに音が鳴る。ところが、性能が低い PC で動かそうとすると、負荷が高いときに、ちゃんとブツブツになってちゃんとした音にならないときがある。なので、優先順位を上げてやったらどうだろうと調べる。import win32apiimport win32processimport win32con pid = win32api.GetCurrentProcessId()handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid)win32process.SetPriorityClass(handle, win32process.HIGH_PRIORITY_CLASS) のようにすれば、起動したプロセスの優先順位を高くできる。これを使って、音を鳴らす前に、優先順位を上げておけば、多少はよくなるかなと。Windows の優先順位は次のようになっている。 リアルタイム win32process.IDLE_PRIORITY_CLASS 高      win32process.BELOW_NORMAL_PRIORITY_CLASS 通常以上   win32process.NORMAL_PRIORITY_CLASS 通常     win32process.ABOVE_NORMAL_PRIORITY_CLASS 通常以下   win32process.HIGH_PRIORITY_CLASS 低い     win32process.REALTIME_PRIORITY_CLASS優先順位の定数の名前を覚えるのも大変なので、下のようにして 0 ~ 5 の値を指定すると、優先順位が上下できるというようにするとよいかな。起動したあとに、優先順位を高に上げて、一呼吸待ってから音を鳴らし始める。毎時 59分55秒にタスクをしかける。 # -*- coding: utf-8 -*-import winsoundimport time## http://code.activestate.com/recipes/496767/ (r1)def setpriority(pid=None,priority=1): """ Set The Priority of a Windows Process. Priority is a value between 0-5 where 2 is normal priority. Default sets the priority of the current python process but can take any valid process ID. """ import win32api,win32process,win32con priorityclasses = [win32process.IDLE_PRIORITY_CLASS, win32process.BELOW_NORMAL_PRIORITY_CLASS, win32process.NORMAL_PRIORITY_CLASS, win32process.ABOVE_NORMAL_PRIORITY_CLASS, win32process.HIGH_PRIORITY_CLASS, win32process.REALTIME_PRIORITY_CLASS] if pid == None: pid = win32api.GetCurrentProcessId() handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) win32process.SetPriorityClass(handle, priorityclasses[priority])## end of http://code.activestate.com/recipes/496767/ def time_signal(): """" 時報を鳴らす """ for i in range(3): winsound.Beep(440,150) time.sleep(0.85) winsound.Beep(880,1400)if __name__ == '__main__': # 優先度を 4 : win32process.HIGH_PRIORITY_CLASS にセット setpriority(None, 4) # 1.5秒待って time.sleep(1.5) # 時報を鳴らす time_signal()ところが実際にやってみると、キーボードで入力していたり、Youtube を見ていたりしても、きれいに音がなってくれない。やっぱり性能が低い PC だと厳しい。Beep のハードウェア割り込みとタイマー割り込みで、そこに他の負荷がかかってダメなのかな。winsound.PlaySound(sound, flags) であらかじめ用意しておいた wave ファイルを鳴らした方が、気持ち悪くならないかな。NHKの時報音(もどき)をダウンロードして使ってみる(C で書かれた音を作るためのソースコードも入っている )。この音を、winsound.PlaySound("nhk.wav", winsound.SND_FILENAME)で鳴らすようにした。こっちの方がいいな。ちなみに、できるだけ正確な時間になにかをしようとしたら、sleep で何秒待って、何かをするというのは厳しいかもね。自前で時間を拾って、一定時刻を過ぎていたら何かするというようにしないと、同じ間隔で何かするというのが、負荷状況によっては、あまり正確にできない可能性がある。

    2010.10.08

    コメント(0)

  • wxPython 入門 (6)

    wPython.org の Getting Started をサカナに第五弾 wxPython 入門(5)  の続き。説明は前のエントリ。ここではソースコードと実行画面のみ。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューを作る """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー menuNew = file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") menuOpen = file_menu.Append(wx.ID_OPEN, "ファイル (&F)", "ファイルを開きます") menuSave = file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") menuSaveas = file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー menuUndo = edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") menuCut = edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") menuCopy = edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") menuPaste = edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー menuHelp = help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") menuAbout = help_menu.Append(wx.ID_ABOUT, "バージョン情報 (&A)", "プログラムのヘルプを表示します") # メニューバーを作成し、個々のメニューをメニューバーに追加していく menuBar = wx.MenuBar() menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(help_menu, "ヘルプ (&H)") # 個々のメニューアイテムを、イベントハンドラーにバインドする self.Bind(wx.EVT_MENU, self.OnNew, menuNew) self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen) self.Bind(wx.EVT_MENU, self.OnSave, menuSave) self.Bind(wx.EVT_MENU, self.OnSaveas, menuSaveas) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Bind(wx.EVT_MENU, self.OnUndo, menuUndo) self.Bind(wx.EVT_MENU, self.OnCut, menuCut) self.Bind(wx.EVT_MENU, self.OnCopy, menuCopy) self.Bind(wx.EVT_MENU, self.OnPaste, menuPaste) self.Bind(wx.EVT_MENU, self.OnHelp, menuHelp) self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) # メニューバーを Frame にセットする self.SetMenuBar(menuBar) # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) # メニューが選択されたら、選択されたことを標準出力に表示する def OnNew(self, event): print "Select New" def OnOpen(self, event): print "Select Open" def OnSave(self, event): print "Select Save" def OnSaveas(self, event): print "Select Save As" def OnUndo(self, event): print "Select Undo" def OnCut(self, event): print "Select Cut" def OnCopy(self, event): print "Select Copy" def OnPaste(self, event): print "Select Paste" def OnHelp(self, event): print "Select Help" def OnAbout(self, event): print "Select About" def OnExit(self, event): print "Select Exit" app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()

    2010.10.06

    コメント(0)

  • wxPython 入門 (5)

    wPython.org の Getting Started をサカナに第五弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更してみた。そして、メニューやステータスバーを付けるところまでやった。今度は、メニューを選択したときに何かの処理が行われるようなところを作ってみる。つまり、話題としては、イベントハンドリング(Event handling) の箇所。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーそういえば、前回、Standard event identifiersで、wx.ID_xxx のドキュメントがあるのを気づかずに通り越していた。wxID_LOWEST = 4999、 wxID_HIGHEST = 5999 なので、この範囲はユーザーが直接使うのは避けましょうということも書いてあった。さらにメニューを作るときには、Stock items を見るとよさそう。メニューとイベントとイベントハンドラーを結びつけるまずは、下記を確認。メインループ(Main loop)とは、イベント駆動型GUIなどの機能を持つアプリケーションで典型的な設計手法。イベントループ(Event loop)とも呼ばれる。常に実行されているループを持ち、ユーザーイベントの有無をループする度に確認し、それイベントを処理する。何らかの方法でイベントを処理すると、制御は前述のループに戻り、次にイベントが発生するまでループを回り続ける。このようなプログラムではループが最上位の制御構造となっており、そのため「メイン」と名づけられている。メインループ (Wikipedia より)ということで、wxwxPython で作ったプログラムを実行するとき、一番最後に app.MainLoop() としているのは、プログラムがイベントループの状態にさせるため。そうすると、プログラムは、マウスやキーボード、あるいはタイマーなどのイベントを捕まえて、それによって何かのアクションが引き起こされるようになる。wxPython のイベントには、wxPython のイベントの一覧 のようなものがある。これは、import wxfor x in dir(wx): if x.startswith('EVT_'): print x のようにして参照することもできる。 たとえば、メニューを選択したときには、wx.EVT_MENUが発生する。これを拾って、何かの処理を起動してやるという処理を書く必要がある。このイベントと、そのイベントに対応する処理(イベントハンドラー) を結び付けてあげるのに Bind メソッドを使う。Bind の構文は、def Bind(self, event, handler, source=None, id=wxID_ANY, id2=wxID_ANY):例:self.Bind(wx.EVT_SIZE, self.OnSize)self.Bind(wx.EVT_BUTTON, self.OnButtonClick, theButton)self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)たとえば、次のようになる。 menuItem = filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報") self.Bind(wx.EVT_MENU, self.OnAbout, menuItem) Bind の第一引数は、イベントの種類。メニュー操作を扱うためのイベントなので wx.EVT_MENU が指定されている。次に指定されているのが、イベントハンドラー。このメソッドでメニューが選択されたときの処理メソッドを指定する(これは別途作成する)。3つめの引数がソースで、ここではメニューアイテムオブジェクト。ここで指定されたメニューアイテムが選択されると EVT_MENU のイベント発生し、イベントハンドラーの self.OnAbout に渡され、そこでなんらかの処理をする。なので、イベントハンドラーのメソッドには、このイベントを引数として受け取れるようにする必要があるので def foo(self, event) のようになる。前回のコードでは、filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報")としていたが、各メニューアイテムオブジェクト(ソース)を格納する変数を用意しなければならないので、menuItem = filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報")のようにするところに注意。そうしたうえで、バインドする。self.Bind(wx.EVT_MENU, self.OnAbout, menuItem)さらに、MyFlame クラスの中で、def OnAbout(self, event): # イベントを受け取って、何かを処理する print "Select About”のようになる。ちなみに、wx.EVT_MENU や wx.EVT_BUTTON などのイベントは、すべて wx.Event のサブクラス。また、あるメソッドがイベントを受け取ったときに処理をせずに、イベントループに戻すには、event.Skip() を呼び出せばよい。たとえば、def OnButtonClick(self, event): if (some_condition): do_something() else: event.Skip()のように使う。もし、ボタンがクリックされても、some_condition が False であれば、このメソッドでは処理を行わないことになる。もし、このスキップを行わない場合、メソッド終了とともに、このイベントの扱いは完了してしまう。けれども、event_skip() としておくと、他のメソッドでこのイベントを扱うように設定されてれば、引き続き、そのメソッドで処理ができる。ということで、とりあえず、各メニューが選択されたら、コンソール上に "Select 選択されたメニュー" を表示するようにしてみた。コードが少し長くなるので、次のエントリに続く。

    2010.10.06

    コメント(0)

  • wxPython 入門 (4)

    wPython.org の Getting Started をサカナに第四弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更することをやってみた。wxPython 入門 (1) wxPython 入門 (2) wxPython 入門 (3)今日は、メニューをつけてみることにする。メニューバーを作るWindows のメモ帳と同じようなメニューを作ってみることにする。ただし、全部作ると面倒なので適宜省略する。メニューを作るには、まず、各々のメニューオブジェクト(wx.Menu) を作る。次に、各メニュー(ファイル、編集、書式...) を選択すると表示されるメニューアイテムを追加(Append)していく。各メニューの中で区切り線を入れたければ、Separator オブジェクトを挿入したい箇所に AppendSeparator で追加する。各メニューオブジェクトの設定が終わったら、メニューバー(wx.MenuBar) を作って、そこに各メニューを追加(Append)する。最後にメニューオブジェクトを、フレームにセットする(wx.SetMenuBar)。各メニューオブジェクト(ファイル,編集...) にメニューアイテムを追加するときには、メニューオブジェクト.Append( ID, メニュー表示, ステータスバーのメッセージ) の順に、たとえば、file_menu.Append(wx.ID_ANY, "新規作成 (&N)", "ファイルを新しく作ります") と指定する。Getting Started を見ると、ID に対して wx.ID_EXIT や wx.ID_ABOUT など、標準で用意されている ID を使っているが、標準以外の ID を使おうとすれば定義が必要になる(値は整数)。実際には、このIDはメニューアイテムのどれかを識別するためにユニークな整数が割り当てられていればよい。手作業で一つ一つ、ID_XXX = 1, ID_XXY = 2, ... と定義を入れていってもよいのだろうが、数が多くなると大変だし間違いが起こりやすくなる。Style Guide for wxPython code を読むと、"3. Don't use IDs. There is very rarely a good reason to use them." 特別な場合以外は、ID を独自に設定する意味はなさそうだし、むしろ下手につけない方がよいようなので、wx.ID_ANY を指定することにしようと思ったが、EXCEPTION: (there's always an exception!) Use standard IDs for standard menus, buttons, etc. It is useful to use the standard IDs because they may turn on standard functionality, such as menu item remapping for wxMac, automatic Dialog completion or cancellation, using stock button labels and images, etc. A list of these standard IDs can be found in the "Constants -- Stock items" section of the wxWidgets Reference manual. Example:item = FileMenu.Append(wx.ID_EXIT, "&Quit") This will put the Quit menu where it should be on OS-X, for instance.と、標準的な ID については、標準のものを使った方がよいかなぁ。ということで、標準の ID を使った。Mac OSX 以外でそういうメリットがあるか分からないけど。メニューアイテムの文字列については、&X のようにアンパサンドの後にある文字が、自動的にアクセラレーターキーになる。以下、コードが長くなると見づらくなるので、メニューに関連するところだけにしておく。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューを作る """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() format_menu = wx.Menu() view_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") file_menu.Append(wx.ID_OPEN, "ファイル (&F)", "ファイルを開きます") file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") # メニューバーを作成する menuBar = wx.MenuBar() # 個々のメニューをメニューバーに追加していく menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(format_menu, "書式 (&O)") menuBar.Append(view_menu, "表示 (&V)") menuBar.Append(help_menu, "ヘルプ (&H)") # メニューバーを Frame にセットする self.SetMenuBar(menuBar) # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()今回はメニューを作るところまでだが、メニューを作り終わったら、そのメニューが選択されたときに (メニュー選択のイベントが発生したときに、どのようなアクションをとるかということを結びつける(バインドする, BIND)。ここは次の回にやる予定。以下、標準で用意されている wx.ID_??? と、そこで定義されている値を見てみたもの。自分で ID を定義するときには、これとぶつからないように 10以下と 5000台の数は使わないようにすることにした。> import wx> for name in dir(wx):... if name.startswith("ID_"):... print name, eval("wx."+name)...ID_ABORT 5115ID_ABOUT 5014ID_ADD 5118ID_ANY -1ID_APPLY 5102ID_BACKWARD 5107ID_BOLD 5126ID_CANCEL 5101ID_CLEAR 5034ID_CLOSE 5001ID_CLOSE_ALL 5021ID_CONTEXT_HELP 5112ID_COPY 5032ID_CUT 5031ID_DEFAULT 5108ID_DELETE 5038ID_DOWN 5121ID_DUPLICATE 5036ID_EDIT 5030ID_EXIT 5006ID_FILE 5050ID_FILE1 5051ID_FILE2 5052ID_FILE3 5053ID_FILE4 5054ID_FILE5 5055ID_FILE6 5056ID_FILE7 5057ID_FILE8 5058ID_FILE9 5059ID_FIND 5035ID_FORWARD 5106ID_HELP 5009ID_HELP_COMMANDS 5018ID_HELP_CONTENTS 5015ID_HELP_CONTEXT 5020ID_HELP_INDEX 5016ID_HELP_PROCEDURES 5019ID_HELP_SEARCH 5017ID_HIGHEST 5999ID_HOME 5122ID_IGNORE 5117ID_INDENT 5133ID_INDEX 5125ID_ITALIC 5127ID_JUSTIFY_CENTER 5128ID_JUSTIFY_FILL 5129ID_JUSTIFY_LEFT 5131ID_JUSTIFY_RIGHT 5130ID_LOWEST 4999ID_MORE 5109ID_NEW 5002ID_NO 5104ID_NONE -3ID_NOTOALL 5114ID_OK 5100ID_OPEN 5000ID_PAGE_SETUP 5012ID_PASTE 5033ID_PREFERENCES 5022ID_PREVIEW 5013ID_PREVIEW_CLOSE 1ID_PREVIEW_FIRST 6ID_PREVIEW_GOTO 8ID_PREVIEW_LAST 7ID_PREVIEW_NEXT 2ID_PREVIEW_PREVIOUS 3ID_PREVIEW_PRINT 4ID_PREVIEW_ZOOM 5ID_PRINT 5010ID_PRINT_SETUP 5011ID_PROPERTIES 5041ID_REDO 5008ID_REFRESH 5123ID_REMOVE 5119ID_REPLACE 5039ID_REPLACE_ALL 5040ID_RESET 5111ID_RETRY 5116ID_REVERT 5005ID_REVERT_TO_SAVED 5140ID_SAVE 5003ID_SAVEAS 5004ID_SELECTALL 5037ID_SEPARATOR -2ID_SETUP 5110ID_STATIC 5105ID_STOP 5124ID_UNDELETE 5139ID_UNDERLINE 5132ID_UNDO 5007ID_UNINDENT 5134ID_UP 5120ID_VIEW_DETAILS 5042ID_VIEW_LARGEICONS 5043ID_VIEW_LIST 5045ID_VIEW_SMALLICONS 5044ID_VIEW_SORTDATE 5046ID_VIEW_SORTNAME 5047ID_VIEW_SORTSIZE 5048ID_VIEW_SORTTYPE 5049ID_YES 5103ID_YESTOALL 5113ID_ZOOM_100 5135ID_ZOOM_FIT 5136ID_ZOOM_IN 5137ID_ZOOM_OUT 5138

    2010.10.02

    コメント(2)

  • wxPython 入門 (3)

    wxPython 入門 (1) 、wxPython 入門 (2) に引き続き、wPython.org の Getting Started をサカナに第三弾。"Building a simple text editor" のあたりを見ていく。シンプルなテキストエディタを作ってみましょうというところ。TextCtrl の style を指定すれば、スクロールやワードラップ、右寄せ、左寄せ、センタリング等々の設定ができるところまで wxPython 入門 (2) で確認したが、文字の色をつけたり、フォントを指定したりするにはどうしたらよいかということを見ていく。要するに、TextCtrl をもう少し見ていきましょうということ。TextCtrl の文字色と背景色を変えるテキストコントロールの SetForgroundColour メソッドで文字色、SetBackgroundColour メソッドで背景色を変更することができる。文字色は、英語名でも、16進形式でも、10進形式(RGB を 0-255で指定) でも可能だが、英語名の場合は、すべての名前が使えるわけではなく、red, blue, yellow, black, white, gray... といった基本色以外は使えない。名前は何が使えるか、未調査。たとえば、wheet みたいなものは使えない。wx.WHITE、wx.GREEN、wx.BLACK、wx.CYAN, wx.RED, wx.LIGHT_GREY のようなものも使える。無効な色が指定された場合は、デフォルトの色になる。10進形式の場合は、wxColour(R, G, B) で指定する(それぞれ 0~255)。ちなみに、"colour" であって、"color" でないので注意(英国式の綴り)、と思ったら、実は、wx.Color(R,G,B) でも大丈夫だった。どちらかに統一しておいたほうがよいだろう。wx.LIGHT_GREY はあるが、wx.LIGHT_GRAY はないなど、基本的には英国式綴りをベースにした方が問題ないように思える(最初は英国綴りだけしかなくて、みな間違えるので米国式綴りも定義されたんじゃなかろうか。それゆえ、すべてのクラスで両方あるわけではないと。歴史的経緯については調べていないけど)# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色を変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 # 次の4つはどれでも同じ結果になる。 # self.control.SetForegroundColour("red") # self.control.SetForegroundColour(wx.RED) # self.control.SetForegroundColour(wx.Colour(255, 0, 0)) self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()wx.色 で定義されているのは、次の色。wx.BLACKwx.WHITEwx.REDwx.BLUEwx.GREENwx.CYANwx.LIGHT_GREYTextCtrl のフォントを変える今度は、フォントの種類を変えたり、文字の大きさを変えたり、イタリックにしたり、太字にしたりしてみる。指定は、SetFont メソッドを使う。ただし、直接値を渡すのではなく、wx.Font() でフォント指定のオブジェクトを作ってから渡す。その際には、フォントのサイズ、ファミリー、スタイル、ウェイトを指定しなければならない。下線を文字の下につけたいときは、引数の最後に True を追加する (1でもよい)。False なら下線なし。フォントファミリーは、wx.FONTFAMILY_DEFAULT デフォルトwx.FONTFAMILY_DECORATIVE デコラティブwx.FONTFAMILY_ROMAN ローマン(serif) wx.FONTFAMILY_SCRIPT ハンドライティング(手書き風)wx.FONTFAMILY_SWISS スイス(sans-serif) フォントwx.FONTFAMILY_MODERN 固定ピッチフォントwx.FONTFAMILY_TELETYPE テレタイプフォントフォントスタイル (FONTSTYLE_) は、wx.FONTSTYLE_NORMAL ノーマルwx.FONTSTYLE_SLANT  スラントwx.FONTWEIGHT_BOLD ボールドwx.FONTWEIGHT_LIGHT ライトフォントウェイトは、wx.FONTWEIGHT_NORMAL ノーマルwx.FONTWEIGHT_LIGHT ライトwx.FONTWEIGHT_BOLD ボールドただし、wx.DEFAULT, wx.NORMAL, wx.SWISS, wx.BOLD のように、前半の FONTFAMILY_ や FONTSTYLE_ をつけなくても、実際の定数の INT の数値が同じなので問題ないようだ。同じ定数が定義されている。検索してみると、両方見つかるが、デモなど見ても、wx.DEFAULT のように短縮した形式になっているので、短い形式で指定することにした。次の例では、24ポイントのノーマルフォントで太字でイタリックで表示している。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色とフォントを変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # フォントの指定 font = wx.Font(24, wx.NORMAL, # wx.FONTFAMILY_DEFAULT wx.ITALIC, # wx.FONTSTYLE_ITALIC wx.BOLD) # wx.FONTWEIGHT_BOLD self.control.SetFont(font) # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()TextCtrl のフォント名を指定する使用するフォントを名前で指定することもできる。その場合、wx.Font(ポイント, ファミリー, スタイル, ウェイト , アンダーライン(T|F), フォント名) のような指定になる。アンダーラインのところで True を指定すれば、文字に下線が引かれる。False なら通常の表示。次の例は、フォントにメイリオを使って、下線を表示している例。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色、フォントなどを変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # フォントの指定 font = wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, "メイリオ") self.control.SetFont(font) # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()ちなみに、TexCtrl を駆使すれば、それなりのリッチテキストエディタが作れるはずだが、リッチテキストエディタがほんとうに作りたければ、むしろ、wx.RichTextCtrl を使った方がいいだろう。デモを見ると、こういうものがある。ただし、ちゃんとしたアプリケーションとしては仕上げられてはいないから、表示するところまでで、保存はテキスト形式になっちゃうけど。TextCtrl 自体、まだまだネタはあるのだが、おいおい取り込むことにして、とりあえず、先に進むことにする。

    2010.10.01

    コメント(0)

  • 全214件 (214件中 1-50件目)

    1 2 3 4 5 >



    © Rakuten Group, Inc.
    X
    Mobilize your Site
    スマートフォン版を閲覧 | PC版を閲覧
    Share by: