つかさのほえほえ日記跡地 tukasa1919 Hatena::Blog hatenablog://blog/10257846132616278198 グッバイはてなダイアリー hatenablog://entry/10257846132626153237 2012-08-02T10:04:09+09:00 2018-09-10T16:08:06+09:00 あいさつ つかさです。 ブログを移転します。移転先はつかさのほえほえ日記です。 http://hoehoetukasa.blogspot.jp ここで書いた記事は消さずに残す予定です。記事の移行も少しずつ行うつもり。 r 、 r 、_ .⊆ヽ`二ミヽ、 (`_ー-=r‐ァ゙=,三ミ、`、 } _ ,⊆三彡' / ,r===゙゙'---‐¨=丶 ,ゞ=,.= ‐' / .:i し¬_r=彳、 .:::i }c`'ー--- ───---:::'{ ,. ¬、_O ___O__...::::::_2!、 いこう ここもじき腐海に沈む / .. ̄.. ....::::: ̄:: .:::::ヽ / ,.… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> ブログを移転します。移転先は<a href="http://hoehoetukasa.blogspot.jp/">&#x3064;&#x304B;&#x3055;&#x306E;&#x307B;&#x3048;&#x307B;&#x3048;&#x65E5;&#x8A18;</a>です。<br /> <a href="http://hoehoetukasa.blogspot.jp">http://hoehoetukasa.blogspot.jp</a><br /> ここで書いた記事は消さずに残す予定です。記事の移行も少しずつ行うつもり。<br /> <br /> </p> <pre class="code" data-lang="" data-unlink>            r 、         r 、_ .⊆ヽ`二ミヽ、       (`_ー-=r‐ァ゙=,三ミ、`、 } _         ,⊆三彡&#39; / ,r===゙゙&#39;---‐¨=丶        ,ゞ=,.= ‐&#39; /              .:i         し¬_r=彳、            .:::i             }c`&#39;ー--- ───---:::&#39;{           ,. ¬、_O   ___O__...::::::_2!、   いこう ここもじき腐海に沈む         /      .. ̄..  ....::::: ̄:: .:::::ヽ         /         ,.-t_r‐テ=:.‐ャrテ‐x`.::::::::ヽ      /      ,. イ `こニ ´゙  Fニ´「[`ヽ、:::::ヽ、     , &#39;&#34;    ,.r‐&#39;i&#34;「:..._゙ゝ‐-ー- 、r  レ;z亠ッ`&#39;ー゙=ミ- &#39;   ,f=‐:-,,-<. i::. l:. l:_,≦-`    ` -&#39;&#34; ´_=ミー&#34;_,.:ヽ  /.:.    `:.  ゙ヾ. l:..ヽ、彡,´        、ミミ゙ー&#34;⌒:ヽ _/.:._     :.   `&#39;ー-、〃;&#34;   ,,  ,、 、ヾツ   ...;;ヘ ⌒゙ー:...._   `;,,_   &#39;&#39;≠彡ッ彡;,ソ,,リ、,ミ㍉゙ 丶-‐....::::;;〉</pre> </div> tukasa1919 Pythonでプログラムを作るときのTips hatenablog://entry/10257846132626153257 2012-06-16T20:27:18+09:00 2018-09-10T16:08:08+09:00 あいさつ つかさです。 プログラム本体とは関係ないが、詰まったりしたことのメモ py2exeの使い方 実行ファイル形式にするので定番が、py2exeらしい。 ここからダウンロード。Pythonのバージョンによって、違うのをインストールしないとだめのようだ。僕は2.7を使ってるのでpy2exe-0.6.9.win32-py2.7.exeをダウンロードした。そしてこれをインストール。では、これで実行ファイルを作る方法。setup.pyを作ります。 setup.py import sys import os from distutils.core import setup import py2exe… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> プログラム本体とは関係ないが、詰まったりしたことのメモ</p> </div> <div class="section"> <h4>py2exeの使い方</h4> <p>実行ファイル形式にするので定番が、py2exeらしい。<br /> <a href="http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/">&#x3053;&#x3053;</a>からダウンロード。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>のバージョンによって、違うのをインストールしないとだめのようだ。僕は2.7を使ってるのでpy2exe-0.6.9.win32-py2.7.exeをダウンロードした。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120616201859" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120616/20120616201859.jpg" alt="f:id:tukasa1919:20120616201859j:image" title="f:id:tukasa1919:20120616201859j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>そしてこれをインストール。</p><p>では、これで実行ファイルを作る方法。</p><p>setup.pyを作ります。</p> <div class="section"> <h5>setup.py</h5> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> sys <span class="synPreProc">import</span> os <span class="synPreProc">from</span> distutils.core <span class="synPreProc">import</span> setup <span class="synPreProc">import</span> py2exe py2exe_options = { <span class="synConstant">&quot;compressed&quot;</span>: <span class="synConstant">1</span>, <span class="synConstant">&quot;optimize&quot;</span>: <span class="synConstant">2</span>, <span class="synConstant">&quot;bundle_files&quot;</span>: <span class="synConstant">3</span>} setup( options = {<span class="synConstant">&quot;py2exe&quot;</span>: py2exe_options}, windows = [{ <span class="synConstant">&quot;script&quot;</span> : <span class="synConstant">&quot;SETZER.py&quot;</span>, <span class="synConstant">&quot;icon_resources&quot;</span>: [(<span class="synConstant">1</span>,<span class="synConstant">&quot;py.ico&quot;</span>)], <span class="synConstant">&quot;name&quot;</span> : <span class="synConstant">&quot;SETZER&quot;</span>, <span class="synConstant">&quot;version&quot;</span> : <span class="synConstant">&quot;0.01&quot;</span>, <span class="synConstant">&quot;description&quot;</span> : <span class="synConstant">&quot;&quot;</span>, <span class="synConstant">&quot;company_name&quot;</span> : <span class="synConstant">&quot;hoehoeSoft&quot;</span>, <span class="synConstant">&quot;url&quot;</span> : <span class="synConstant">&quot;http://d.hatena.ne.jp/tukasa1919/&quot;</span>, }], zipfile = <span class="synConstant">&quot;lib/library.zip&quot;</span>) </pre><p>そしてこれを、実行ファイルがあるフォルダに入れ、PPxであれば次のようなコマンドを打つ。</p> <pre class="code" data-lang="" data-unlink>CD %1 %: C:\Python27\python.exe setup.py py2exe</pre> </div> <div class="section"> <h5>ポイント</h5> <p>ポイントは二カ所。bundle_filesと、zipfileです。</p><p>bundle_filesで、実行ファイルの大きさを変えることができます。3になると小さくなります。<br /> ただ、これだと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リに、関連するファイルがたくさんできてうっとうしい。そこで、サブフォルダにそれらをまとめて入れたいと思うことになると思います。</p><p>そのときに設定するのが、zipfileです。ここで</p> <pre class="code" data-lang="" data-unlink>zipfile = &#34;lib/library.zip&#34;</pre><p>とすることで、libフォルダを作りそのなかに.pydとか.dllとかの雑多なファイルをまとめられるようにできます。</p> </div> </div> <div class="section"> <h4>sitecustomize.py</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C9">エンコード</a>の設定のため、デフォルトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C7%A5%A3%A5%F3%A5%B0">エンコーディング</a>を変えたほうがいいらしいので、変える。</p> <ul> <li>sitecustomize.py</li> </ul><pre class="code" data-lang="" data-unlink>import sys sys.setdefaultencoding(&#34;mbcs&#34;)</pre><p>このファイルを</p><p>C:\Python27\Lib\site-packages</p><p>に入れます。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>への変換方法</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>をいじっていて一番躓いたのが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C9">エンコード</a>のエラー。何かにつけて</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a> DECODE ERROR</p><p>みたいな文字が出てしまう。<br /> とりあえず、外部から何か文字列を取り出し、内部で作業したいなら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>に変換するというのが無難らしい。<br /> そして、再び外部に出力するときには、Shift-jisなり<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTF-8">UTF-8</a>なりにする、と。</p><p>というわけで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>に変換する方法です。</p> <pre class="code lang-python" data-lang="python" data-unlink> lookup = (<span class="synConstant">'utf_8'</span>, <span class="synConstant">'euc_jp'</span>, <span class="synConstant">'euc_jis_2004'</span>, <span class="synConstant">'euc_jisx0213'</span>, <span class="synConstant">'shift_jis'</span>, <span class="synConstant">'shift_jis_2004'</span>,<span class="synConstant">'shift_jisx0213'</span>, <span class="synConstant">'iso2022jp'</span>, <span class="synConstant">'iso2022_jp_1'</span>, <span class="synConstant">'iso2022_jp_2'</span>, <span class="synConstant">'iso2022_jp_3'</span>, <span class="synConstant">'iso2022_jp_ext'</span>,<span class="synConstant">'latin_1'</span>, <span class="synConstant">'ascii'</span>) <span class="synStatement">for</span> encoding <span class="synStatement">in</span> lookup: <span class="synStatement">try</span>: hoge = hoge.decode(encoding) <span class="synStatement">break</span> <span class="synStatement">except</span>: <span class="synStatement">pass</span> </pre><p>ファイルから読み取るなり<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>から入力された文字を読み取るなりする場合には、とりあえずこれを挟んで<a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>にデコードするといいみたいです。</p><p>で、出力するときには<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C9">エンコード</a>をする。</p><p>.encode("<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTF-8">UTF-8</a>")</p><p>だとか</p><p>.encode("Shift-jis")</p><p>をくっつければいいみたいです。<a href="http://speirs.blog17.fc2.com/blog-entry-4.html">&#x6280;&#x8853;&#x5FD7;&#x5411; | Python &#x6587;&#x5B57;&#x30B3;&#x30FC;&#x30C9;&#x306E;&#x5224;&#x5B9A;&#x3068;&#x5909;&#x63DB;</a>を参考にしました。</p> </div> <div class="section"> <h4>作業フォルダを実行ファイルのあるフォルダに</h4> <p>ファイルのはじめの方に、以下を追加すると、作業フォルダを実行ファイルのある場所に固定できる。もちろんosはインポートしておきましょう。</p> <pre class="code" data-lang="" data-unlink>os.chdir(os.path.dirname(sys.argv[0]) or &#39;.&#39;)</pre> </div> <div class="section"> <h4>アイコンの作成</h4> <p><a href="http://takabosoft.com/edge">EDGE</a>を使う。僕は横幅32縦幅32で作った。</p> </div> <div class="section"> <h4>Editor</h4> <p><a href="https://sites.google.com/site/craftware/lredit">LREdit</a>と<a href="http://www.jsdlab.co.jp/~kamei/">Xyzzy</a>+<a href="http://www.geocities.co.jp/Milano-Cat/2067/xyzzy.html">py-mode</a>というのが選択肢としてあるみたいだ。<br /> 僕はずっとLREditを使ってた。</p><p>Ctrl + E Ctrl + Oで、アウトラインが出るのが便利。</p> </div> tukasa1919 ソフトウェア配布用のHP作りました hatenablog://entry/10257846132626153279 2012-06-13T12:39:40+09:00 2018-09-10T16:08:10+09:00 あいさつ つかさです。 ここでSETZERの更新をするたびに記事を書くというのもあれなので、配布用のHPを作りました。hoehoeSoftバグとか要望とかありましたらtwitterなりメールなり何なりで知らせてください。 <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> ここでSETZERの更新をするたびに記事を書くというのもあれなので、配布用のHPを作りました。</p><p><a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a></p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120613123905" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120613/20120613123905.jpg" alt="f:id:tukasa1919:20120613123905j:image" title="f:id:tukasa1919:20120613123905j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>バグとか要望とかありましたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>なりメールなり何なりで知らせてください。</p> </div> tukasa1919 Python用メニューとTree hatenablog://entry/10257846132626153300 2012-06-12T09:28:49+09:00 2018-09-10T16:08:12+09:00 Pythonのスクリプトを実行するためのPPxメニュー。 「Pythonの実行」は、アプリケーションを終了しても窓を閉じないように 「py2exe」は実行ファイルの作成用 「Tree」はPythonには関係ないが、たまにフォルダ構造のコピーをとりたいときのため。今まではフリーソフトでやってたがこっちのほうが楽だと気づいた。 M_cmdMenu = { Pythonの実行 = CD %1 %: C:\Python27\python.exe %FCD py2exe = CD %1 %: C:\Python27\python.exe setup.py py2exe Tree = CD %1 %: T… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を実行するためのPPxメニュー。</p> <ul> <li>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の実行」は、アプリケーションを終了しても窓を閉じないように</li> <li>「py2exe」は実行ファイルの作成用</li> <li>「Tree」は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>には関係ないが、たまにフォルダ構造のコピーをとりたいときのため。今までは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EA%A1%BC%A5%BD%A5%D5%A5%C8">フリーソフト</a>でやってたがこっちのほうが楽だと気づいた。</li> </ul><pre class="code" data-lang="" data-unlink>M_cmdMenu = { Pythonの実行 = CD %1 %: C:\Python27\python.exe %FCD py2exe = CD %1 %: C:\Python27\python.exe setup.py py2exe Tree = CD %1 %: Tree }</pre> tukasa1919 wxPythonでAA管理ツールを作ろう!閑話休題 AAの登録 hatenablog://entry/10257846132626153315 2012-06-11T12:29:57+09:00 2018-09-10T16:08:13+09:00 あいさつ つかさです。 今回からは応用編です。基礎的なやり方を学んでいく、というのからはずれます。 問題点 AAを管理する方法で問題になるのは、「一々AAの登録をするのが面倒」ということに尽きると思います。 AAに一意的に名前を付けられるか。たとえばつかさAAは複数あるが、それぞれをどう名付けるのか 名前をつけるのが難しい場合はどうするのか 名前を付けたとして、分かりやすいものならいいが、それ以外ならあとで検索して、たどれることが無理になるのではないか データベースみたいなのを作って、一々タグを付けて管理していくというのもありえますが、個人でやる以上、手間がかかりすぎて破綻すると思います。また… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回からは応用編です。基礎的なやり方を学んでいく、というのからはずれます。</p> </div> <div class="section"> <h4>問題点</h4> <p>AAを管理する方法で問題になるのは、「一々AAの登録をするのが面倒」ということに尽きると思います。</p> <ul> <li>AAに一意的に名前を付けられるか。たとえばつかさAAは複数あるが、それぞれをどう名付けるのか</li> <li>名前をつけるのが難しい場合はどうするのか</li> <li>名前を付けたとして、分かりやすいものならいいが、それ以外ならあとで検索して、たどれることが無理になるのではないか</li> </ul><p>データベースみたいなのを作って、一々タグを付けて管理していくというのもありえますが、個人でやる以上、手間がかかりすぎて破綻すると思います。また一意的にタグをどのようにしてつけるかも難しそうです。用途に合わせてというのも、AAの場合では無理でしょう。<br /> またデータベースを集団で作るというのも、それで有用なのができるのかどうか。誰でもたどれるキーなんてあり得るのか。</p> </div> <div class="section"> <h4>画像管理の方法の応用</h4> <p>そこで思いついたのが、画像管理の方法の応用です。<br /> 画像というのは、ネットで落としてきた場合でも、名前というのは適当なわけです。一意的に名付けなんてしようがない。ならばどう管理するかというと、フォルダ分けを使うわけです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%AD%BC%AA">猫耳</a>でもケ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A1%BC">モナー</a>でもテリシアでも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>でもめがねっこでも、とりあえずフォルダを作って名前で判別するようにしておく。そしてそのなかに、ファイル名は適当で画像を放り込んでいく。そして、あとで画像を探す場合には、そのフォルダ名からありそうなフォルダへまずいって、そのあと内容を表示して、その画像をめくっていって目的のを見つける。こういうことをするわけですね。</p> <ul> <li>ファイル名は適当</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120611121558" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120611/20120611121558.jpg" alt="f:id:tukasa1919:20120611121558j:image" title="f:id:tukasa1919:20120611121558j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>画像表示をして管理</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120611121557" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120611/20120611121557.jpg" alt="f:id:tukasa1919:20120611121557j:image" title="f:id:tukasa1919:20120611121557j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <div class="section"> <h5>AA管理への応用</h5> <p>これを応用するとどうなるか。AAにあわせて、フォルダを用意するわけです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>、中指、お断りします、みたいにAAにあわせてカテゴリ分けをする。そして、そのなかにファイル名は適当に、AAを放り込んでいく。あとは、検索するときにはそのフォルダ名をキーにして、目的のフォルダへまずいって、そのあとでそれをひとつひとつ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示で閲覧しながら目的のAAを探す。</p> <pre class="code" data-lang="" data-unlink>D:\bin\SETZER\AAList └─AAList ├─お断りします ├─ねじれ ├─ほむら ├─まどかマギカ ├─ゆのっち腹パン ├─ゆるしてにゃん ├─ティッシュ ├─テリシア ├─ビンタ ├─中指 ├─化物語 ├─柊つかさ ├─矢印 └─長門有希</pre><p>フォルダ名をキーとすることで、その中のファイル名は適当でもよくなるのですね</p> </div> </div> <div class="section"> <h4>実装へ</h4> <p>で、このような構造を作ったとしてどうやってそれをプログラムで実装するか、です。</p><p>まずはじめに考えたのが、fenrirの方法をまねること。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リとファイルというように分離し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リモード、ファイル検索モードと分離する。<br /> そして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにヒットしたら、カーソルキーを横に押せばそこにあるファイルが一覧表示。それにカーソルをあわせると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示がなされる。</p><p>fenrirに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示がついたのを考えてくれるといいと思います。まあこのように、モード分けをしたランチャを作ってしまえば可能なわけですね。</p><p>問題点は、ランチャを作る手間がいるということ。今まで作ってきたのよりははるかに複雑なわけです。さらに、ListBoxではなくListCtrlを使う必要が出るでしょう。さっすがにAA管理ツール程度で、そこまでやるのはなあという気がします。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C8%AF%C1%DB%A4%CE%C5%BE%B4%B9">発想の転換</a></h4> <p>そうして思いついたのが、「キーを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ+連番にする」です。<br /> どうせフォルダに放り込んだのなら、名前なんて見ないんだからどうでもいい。それなら、そのフォルダにあるファイルをすべて、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リの名前+連番」にして、ListBoxに他のと一緒に並べたらそれでいいのではないか。それと、対応するパスを辞書で結びつければそれでいい。そうすれば、その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リの名前を検索すれば、その中にあるのがヒットし、表示される。あとは、そこから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示で選択すればいい。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リに入れたテキストファイルは、そのファイル名にかかわらず次のように表示され、それぞれがキーとして、そのパスと結びつけられることになる。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>-1</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>-2</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>-3</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>-4</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>-5</li> </ul><p>このようにすれば、一々<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ構造を実現する必要もないし、また名前とか適当なままフォルダに放り込んだとしても何の支障もない。またルートフォルダにおいた、ファイル名をつけてそれで判別したいファイルとも矛盾しない。ただ、ルートフォルダには名前-数字.txtというのをおかないようにすればいいだけだし、おいたとしたってAAが一つ表示されなくなるだけでたいしたことではない。</p> </div> <div class="section"> <h4>工夫</h4> <p>工夫として、名前-1のファイルをリストの上の方に並べれば、検索キーにもなるだろう。</p><p>ここではフォルダ構造は一階層のみだが、複数にすることもやろうとすればできるはず。</p> </div> <div class="section"> <h4>まとめ</h4> <p>ということで、ではこれを実際にどうやって実装するかという話を次回行います。<br /> このあたりにくるともう、最初の趣旨の、基本的な作り方を知ってみるとかいうのとはかけはなれてきてるような。応用編というか、参考にしたいひとだけ見るという感じでしょうね。僕はこう進んだ、という一つのサンプルとしてご覧下さい。</p> </div> tukasa1919 SETZER ver0.1 公開 hatenablog://entry/10257846132626153340 2012-06-10T20:10:11+09:00 2018-09-10T16:08:15+09:00 あいさつ つかさです。 今までのAA管理ツールから大きく変更しました。クリップボード管理を中心にしてます。 Download SETZER ver.0.1.zip ※最新版はhoehoeSoftに 常駐してホットキー(デフォルトだとCapsLock)でOnOffトグル クリップボードを監視して履歴を再利用 Tabによる切り替えで、クリップボード履歴モード、AA貼り付けモード、ブックマークモードが使える SnapTextの機能(クリップボードを監視してテキスト形式で保存)の組み込み UNICODE対応 Migemo対応 要はeClipだとかClip.netみたいな、クリップボード履歴を取得、蓄積… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今までのAA管理ツールから大きく変更しました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>管理を中心にしてます。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610162459" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610162459.jpg" alt="f:id:tukasa1919:20120610162459j:image" title="f:id:tukasa1919:20120610162459j:image" class="hatena-fotolife" itemprop="image"></a></span></p><br /> <br /> <p><del datetime="2012-08-04T01:42:20+09:00">Download SETZER ver.0.1.zip</del><br /> ※最新版は<a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a>に<br /> <br /> <br /> </p> <ul> <li>常駐してホットキー(デフォルトだとCapsLock)でOnOffトグル</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>を監視して履歴を再利用</li> <li>Tabによる切り替えで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴モード、AA貼り付けモード、ブックマークモードが使える</li> <li>SnapTextの機能(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>を監視してテキスト形式で保存)の組み込み</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>対応</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>対応</li> </ul><p>要はeClipだとかClip.netみたいな、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴を取得、蓄積して再利用するツールです。<br /> 操作はeClipだとかとほとんど同じです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>かカーソルで目的のアイテムを選択し、Enterを押すことで、直前までアクティブだったウィンドウに貼り付けることができます。</p> <ul> <li>ウィンドウを閉じる→ESC</li> <li>アイテム選択→カーソルキー</li> <li>選択アイテム貼り付け→Enter</li> <li>モードの切り替え→Tab</li> </ul><p>Tabキーを押すことで、モードが切り替わります。リストボックスに表示されるリストが</p> <ol> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴</li> <li>AAリスト</li> <li>ブックマーク</li> <li>また最初へ</li> </ol><p>と切り替わり、Enterを押したときの挙動も変化します。</p> </div> <div class="section"> <h4>できること</h4> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>モード</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610162241" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610162241.jpg" alt="f:id:tukasa1919:20120610162241j:image" title="f:id:tukasa1919:20120610162241j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>にコピーされたテキスト一覧が表示されます。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>かカーソル移動でアイテムを選択し、Enterを押せば、直前までアクティブだったウィンドウにその文字列を貼り付けることができます。</p> </div> <div class="section"> <h5>AA(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%AD%A1%BC%A5%A2%A1%BC%A5%C8">アスキーアート</a>)モード</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610162257" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610162257.jpg" alt="f:id:tukasa1919:20120610162257j:image" title="f:id:tukasa1919:20120610162257j:image" class="hatena-fotolife" itemprop="image"></a></span></p><br /> <p>テキストファイル形式でAAListにためたAAを一覧表示します。</p><p>Enterを押すことで、直前までアクティブだったウィンドウに、そのAAを貼り付けられます。</p><p>AAを登録する場合は、AAListフォルダか、AAListのサブフォルダに、テキスト形式で保存してください。</p> </div> <div class="section"> <h5>ブックマークモード</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610162311" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610162311.jpg" alt="f:id:tukasa1919:20120610162311j:image" title="f:id:tukasa1919:20120610162311j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>ブックマーク一覧を表示します。</p><p>Enterを押せば、そのURLをデフォルトのブラウザで開きます。</p><p>ブックマークを登録したい場合は、book.iniをエディタで編集し、追加してください。</p> </div> </div> <div class="section"> <h4>使い方</h4> <p>とりあえず<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>を使えるようにしましょう。これを使わないと、このソフトの意義は半減します。</p> <div class="section"> <h5>辞書の取得</h5> <p>まず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>の辞書を手に入れます。</p><p><a href="http://www.kaoriya.net/software/cmigemo">KaoriYa</a>に行き、C/<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>をダウンロードします。僕が落としたのは、cmigemo-default-win32-20110227.zipでした。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610163015" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610163015.jpg" alt="f:id:tukasa1919:20120610163015j:image" title="f:id:tukasa1919:20120610163015j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>それを解凍した中に、</p> <ul> <li>han2zen.dat</li> <li>hira2kata.dat</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>-dict</li> <li>roma2hira.dat</li> <li>zen2han.dat</li> </ul><p>というファイルがあります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTF-8">UTF-8</a>フォルダ内にあるものとcp932フォルダ内にあるものの二種類がありますが、どちらでもよさそうです。これを、SETZERのDictフォルダにコピーします。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610163137" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610163137.jpg" alt="f:id:tukasa1919:20120610163137j:image" title="f:id:tukasa1919:20120610163137j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h5>SETZER.iniの変更</h5> <p>次に、SETZER.iniをエディタで開き、MAINセレクションのisearchtypeの値を1に変更し、保存します。</p> <pre class="code" data-lang="" data-unlink>isearchtype = 1</pre><p>これで、次回起動時に、ローマ字のままで日本語を検索することが可能になります。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>モードでも</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610163728" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610163728.jpg" alt="f:id:tukasa1919:20120610163728j:image" title="f:id:tukasa1919:20120610163728j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>AAモードでも</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610163758" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610163758.jpg" alt="f:id:tukasa1919:20120610163758j:image" title="f:id:tukasa1919:20120610163758j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>ブックマークモードでも</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120610163813" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120610/20120610163813.jpg" alt="f:id:tukasa1919:20120610163813j:image" title="f:id:tukasa1919:20120610163813j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>このように、ローマ字で日本語を検索し、絞り込むことができます。</p> </div> </div> tukasa1919 SnapText ver0.1 & SETZER ver0.03 公開 hatenablog://entry/10257846132626153363 2012-06-09T23:02:08+09:00 2018-09-10T16:08:17+09:00 あいさつ つかさです。 SnapTextとSETZERの新しいバージョンを公開します。 SnapText 常駐してクリップボードを監視し、テキストがクリップボードにコピーされればそれをテキストファイル形式で、指定したフォルダに自動保存するソフトです。ScreenShotをとればそれを自動でjpgとかにして保存してくれるソフトと、似たようなものと思ってくれていいです。 想定してるのはSetzerとの連携です。AAを大量にAAListのサブフォルダにためたいという場合にこれを用いるとはかどります。 SnapTextを起動し、AAList内の柊つかさなり暁美ほむらなりピングドラムなり好きなフォルダを… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> SnapTextとSETZERの新しいバージョンを公開します。</p> </div> <div class="section"> <h4>SnapText</h4> <p>常駐して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>を監視し、テキストが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>にコピーされればそれをテキストファイル形式で、指定したフォルダに自動保存するソフトです。ScreenShotをとればそれを自動でjpgとかにして保存してくれるソフトと、似たようなものと思ってくれていいです。<br /> 想定してるのはSetzerとの連携です。AAを大量にAAListのサブフォルダにためたいという場合にこれを用いるとはかどります。<br /> SnapTextを起動し、AAList内の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%A2%A4%C4%A4%AB%A4%B5">柊つかさ</a>なり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%C7%C8%FE%A4%DB%A4%E0%A4%E9">暁美ほむら</a>なり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%F3%A5%B0%A5%C9%A5%E9%A5%E0">ピングドラム</a>なり好きなフォルダを指定し、そのキャラのAAがおいてあるAA保管サイトに行けば、もうあとは欲しいAAを選択してコピーを繰り返すだけで、AAを登録できるわけです。</p><p><del datetime="2012-08-07T18:28:36+09:00">Download SnapText ver.0.1.zip</del><br /> ※最新版は<a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a>に</p> </div> <div class="section"> <h4>SETZERの更新</h4> <p>今までは、AAList内のファイルがShift-Jisで無い場合は読み込めませんでしたが、それに対応しました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTF-8">UTF-8</a>とかでも大丈夫です。</p><p><del datetime="2012-08-07T18:28:36+09:00">Download SETZER ver.0.03.zip</del><br /> ※最新版は<a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a>に</p> </div> <div class="section"> <h4>今後の予定</h4> <p>次回あたりのバージョンから、SETZERを常駐させ、eClipやClip.netみたいな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>管理ツールに変更しようと思ってます。AA管理は、その一つのモードという仕方で残すことになります。<br /> あと一々ブログの記事にして載せるのも何だし、GoogleSitesとかで新しいHPを作ってそこに置くようにしようかとも思ってます。</p> </div> tukasa1919 AA管理ツール SETZER ver0.02 公開 hatenablog://entry/10257846132626153375 2012-06-06T20:03:51+09:00 2018-09-10T16:08:19+09:00 Download SETZER ver.0.02.zip ※最新版はhoehoeSoftに 変更点 リストボックスの最大表示数を設定可に ツールチップ表示のウィンドウ最大値を調節可に タスクバーに表示するかどうかを設定可に 何文字入力された時点でMigemo検索を行うかを設定可に 文字を入力してもリストが変更しないときはちらつかせない アイコンを変えた ソースコードを入れた <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606195151" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606195151.jpg" alt="f:id:tukasa1919:20120606195151j:image" title="f:id:tukasa1919:20120606195151j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p><del datetime="2012-08-07T18:28:56+09:00">Download SETZER ver.0.02.zip</del><br /> ※最新版は<a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a>に</p> <div class="section"> <h4>変更点</h4> <ul> <li>リストボックスの最大表示数を設定可に</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示のウィンドウ最大値を調節可に</li> <li>タスクバーに表示するかどうかを設定可に</li> <li>何文字入力された時点で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>検索を行うかを設定可に</li> <li>文字を入力してもリストが変更しないときはちらつかせない</li> <li>アイコンを変えた</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を入れた</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606195549" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606195549.jpg" alt="f:id:tukasa1919:20120606195549j:image" title="f:id:tukasa1919:20120606195549j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606195545" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606195545.jpg" alt="f:id:tukasa1919:20120606195545j:image" title="f:id:tukasa1919:20120606195545j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919 wxPythonでブックマーク管理ツールを作ろう! hatenablog://entry/10257846132626153391 2012-06-06T09:32:24+09:00 2018-09-10T16:08:20+09:00 あいさつ つかさです。 今回は番外編です。ブックマーク管理ツールを作ってみます。AA管理ツールで学んだことを応用します。 準備 今回作るプログラムは、あらかじめブックマークを手動でテキストファイルに書き込んでおき、それを読み込む、という形式をとります。 まずそのブックマークを書き込んだファイルを作りましょう。 bookmark.ini つかさのほえほえ日記 |http://d.hatena.ne.jp/tukasa1919/ はてなブックマーク |http://b.hatena.ne.jp/tukasa1919/ 2ちゃんねる サーバ負荷監視所 |http://ch2.ath.cx/ Goog… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は番外編です。ブックマーク管理ツールを作ってみます。AA管理ツールで学んだことを応用します。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120603072703" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120603/20120603072703.jpg" alt="f:id:tukasa1919:20120603072703j:image" title="f:id:tukasa1919:20120603072703j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>準備</h4> <p>今回作るプログラムは、あらかじめブックマークを手動でテキストファイルに書き込んでおき、それを読み込む、という形式をとります。<br /> まずそのブックマークを書き込んだファイルを作りましょう。</p> <ul> <li>bookmark.ini</li> </ul><pre class="code" data-lang="" data-unlink>つかさのほえほえ日記 |http://d.hatena.ne.jp/tukasa1919/ はてなブックマーク |http://b.hatena.ne.jp/tukasa1919/ 2ちゃんねる サーバ負荷監視所 |http://ch2.ath.cx/ Google リーダー | http://www.google.com/reader/view/#overview-page PPx help | http://homepage1.nifty.com/toro/ppxhlp.html Twitter | http://twitter.com/ wxPythonリファレンス | http://wxwindowsjp.sourceforge.jp/docs/html/wx/wx26.htm#classref gmail | https://mail.google.com/mail 簡易AAエディタ | http://iranegi.s5.xrea.com:8080/2ch/aaedit/aaedit.php</pre><p>"|"で区切っています。サイト名とurlが対になってます。これを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>と同じフォルダにおくことで、ブックマークを読み込みます。<br /> また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>も使うので、それに関係するファイル(<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>.dll <a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>.pyd Dict)も、同じフォルダに用意しておいてください。<br /> では次に、このファイルを読み込むプログラムを作成します。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606085533" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606085533.jpg" alt="f:id:tukasa1919:20120606085533j:image" title="f:id:tukasa1919:20120606085533j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>を作る</h4> <p>まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>を作るところからはじめましょう。</p> <ul> <li>Bookmark01.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606085601" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606085601.jpg" alt="f:id:tukasa1919:20120606085601j:image" title="f:id:tukasa1919:20120606085601j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p><a href="http://d.hatena.ne.jp/tukasa1919/20120521/1337583727">wxPython&#x3067;AA&#x7BA1;&#x7406;&#x30C4;&#x30FC;&#x30EB;&#x3092;&#x3064;&#x304F;&#x308D;&#x3046;&#xFF01;&#x7B2C;&#x4E00;&#x56DE; GUI&#x3092;&#x4F5C;&#x308B;</a>と全く同じですので、詳しくはそこを参照してください。</p> </div> <div class="section"> <h4>リストを作る</h4> <p>次に、bookmark.iniを読み込み、サイト名とurlが対になった辞書を作り、サイト名のリストをセットします。</p> <ul> <li>Bookmark02.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>) bf = <span class="synIdentifier">open</span>(<span class="synConstant">&quot;bookmark.ini&quot;</span>) booklist = bf.readlines() booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.decode(<span class="synConstant">&quot;shift-jis&quot;</span>).strip()),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.rsplit(<span class="synConstant">&quot;|&quot;</span>)),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: <span class="synIdentifier">tuple</span>(x)),booklist) self.BookDict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> booklist: name = x[<span class="synConstant">0</span>].strip() url = x[<span class="synConstant">1</span>].strip() self.BookDict[name] = url self.site_list = self.BookDict.keys() self.LBox.Set(self.site_list) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606085628" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606085628.jpg" alt="f:id:tukasa1919:20120606085628j:image" title="f:id:tukasa1919:20120606085628j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <div class="section"> <h5>辞書の作成</h5> <pre class="code lang-python" data-lang="python" data-unlink> bf = <span class="synIdentifier">open</span>(<span class="synConstant">&quot;bookmark.ini&quot;</span>) booklist = bf.readlines() booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.decode(<span class="synConstant">&quot;shift-jis&quot;</span>).strip()),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.rsplit(<span class="synConstant">&quot;|&quot;</span>)),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: <span class="synIdentifier">tuple</span>(x)),booklist) self.BookDict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> booklist: name = x[<span class="synConstant">0</span>].strip() url = x[<span class="synConstant">1</span>].strip() self.BookDict[name] = url </pre><p>まずは辞書を作るところから。"|"を区切り文字にして、サイト名とurlの対を取り出します。<br /> 次いで空の辞書self.BookDictを作り、サイト名をキーに。urlを値にして一つずつ登録します。<br /> これで次のような辞書ができます。</p> <pre class="code" data-lang="" data-unlink>{&#39;つかさのほえほえ日記&#39; : &#39;http://d.hatena.ne.jp/tukasa1919/&#39;, &#39;はてなブックマーク&#39; : &#39;http://b.hatena.ne.jp/tukasa1919/&#39;, &#39;2ちゃんねる サーバ負荷監視所&#39; : &#39;http://ch2.ath.cx/&#39;, &#39;Google リーダー&#39; : &#39;http://www.google.com/reader/view/#overview-page&#39;, 以下略}</pre> </div> <div class="section"> <h5>リストボックスに登録</h5> <pre class="code lang-python" data-lang="python" data-unlink> self.site_list = self.BookDict.keys() self.LBox.Set(self.site_list) </pre><p>次に、この辞書からサイト名のリストを作ります。キーのリストをkeys()で作成して、それをListBoxにセットします。</p><p>これで見た目は完成です。<br /> 次に、カーソル移動と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>による<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>ができるようにします。</p> </div> </div> <div class="section"> <h4>カーソル移動と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>の追加(コピペ)</h4> <ul> <li>Bookmark03.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,migemo,re migemo_object = <span class="synIdentifier">None</span> <span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>) bf = <span class="synIdentifier">open</span>(<span class="synConstant">&quot;bookmark.ini&quot;</span>) booklist = bf.readlines() booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.decode(<span class="synConstant">&quot;shift-jis&quot;</span>).strip()),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.rsplit(<span class="synConstant">&quot;|&quot;</span>)),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: <span class="synIdentifier">tuple</span>(x)),booklist) self.BookDict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> booklist: name = x[<span class="synConstant">0</span>].strip() url = x[<span class="synConstant">1</span>].strip() self.BookDict[name] = url self.site_list = self.BookDict.keys() self.LBox.Set(self.site_list) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): fr = self.LBox.GetStringSelection() webbrowser.<span class="synIdentifier">open</span>(self.BookDict[fr]) wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.BookDict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">else</span>: event.Skip() event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606085705" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606085705.jpg" alt="f:id:tukasa1919:20120606085705j:image" title="f:id:tukasa1919:20120606085705j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>変更したのは以下の点です。</p> <ul> <li>reと<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>をインポート</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>をglobal変数として宣言</li> <li>IncrementalSearchクラスをコピペ</li> <li>OnKeyCharとOnTextの二つの関数をコピペ</li> </ul><p>そして、</p> <pre class="code lang-python" data-lang="python" data-unlink> self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) </pre><p>を__ini__に付け足してます。<br /> やってることはAA管理ツールのコードの流用です。<a href="http://d.hatena.ne.jp/tukasa1919/20120602/1338627563">wxPython&#x3067;AA&#x7BA1;&#x7406;&#x30C4;&#x30FC;&#x30EB;&#x3092;&#x4F5C;&#x308D;&#x3046;&#xFF01;&#x7B2C;&#x516D;&#x56DE; PyMigemo&#x3067;&#x30A4;&#x30F3;&#x30AF;&#x30EA;&#x30E1;&#x30F3;&#x30BF;&#x30EB;&#x30B5;&#x30FC;&#x30C1;</a>あたりのコードから該当箇所をコピペしてます。</p> </div> <div class="section"> <h4>URLをデフォルトのブラウザで開く</h4> <p>いよいよラストです。<br /> 実際にブックマークをブラウザで開けるようにしましょう。変更点は、</p> <ul> <li>urlをデフォルトのブラウザで開くためにwebbrowserをインポート</li> <li>OnKeyCharのEnterの箇所</li> </ul><p>です。</p> <ul> <li>Bookmark04.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,migemo,re,webbrowser migemo_object = <span class="synIdentifier">None</span> <span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>) bf = <span class="synIdentifier">open</span>(<span class="synConstant">&quot;bookmark.ini&quot;</span>) booklist = bf.readlines() booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.decode(<span class="synConstant">&quot;shift-jis&quot;</span>).strip()),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: x.rsplit(<span class="synConstant">&quot;|&quot;</span>)),booklist) booklist = <span class="synIdentifier">map</span>((<span class="synStatement">lambda</span> x: <span class="synIdentifier">tuple</span>(x)),booklist) self.BookDict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> booklist: name = x[<span class="synConstant">0</span>].strip() url = x[<span class="synConstant">1</span>].strip() self.BookDict[name] = url self.site_list = self.BookDict.keys() self.LBox.Set(self.site_list) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): fr = self.LBox.GetStringSelection() webbrowser.<span class="synIdentifier">open</span>(self.BookDict[fr]) wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.BookDict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">else</span>: event.Skip() event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120606085818" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120606/20120606085818.jpg" alt="f:id:tukasa1919:20120606085818j:image" title="f:id:tukasa1919:20120606085818j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): fr = self.LBox.GetStringSelection() webbrowser.<span class="synIdentifier">open</span>(self.BookDict[fr]) wx.Exit() </pre><p>Enterを押したときに、サイト名に対応したurlを開くようにします。</p> <ol> <li>選択しているサイト名をキーにして、urlを取り出し</li> <li>それをデフォルトのブラウザで開く</li> </ol><p>ということをしてるわけですね。</p> </div> <div class="section"> <h4>使い方</h4> <p>登録はbookmark.iniを直接編集することで行います。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120603072216" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120603/20120603072216.jpg" alt="f:id:tukasa1919:20120603072216j:image" title="f:id:tukasa1919:20120603072216j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>上下カーソルでの選択も、<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>での絞り込みもできます。Enterでブックマークを開きます。Escで終了します。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120603072208" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120603/20120603072208.jpg" alt="f:id:tukasa1919:20120603072208j:image" title="f:id:tukasa1919:20120603072208j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>まとめ</h4> <p>要は、AA管理ツールの枠組みを使えば、</p> <ul> <li>登録する辞書</li> <li>Enterを押した時の挙動</li> </ul><p>の二つをいじるだけで、いろんなことができるというわけです。<br /> 他に僕が思いついたのは、定型文の管理。あと、辞書をうまく作ることができれば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴を監視するeClipみたいなのも作れますね。</p> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第七回 直前のウィンドウに貼り付け hatenablog://entry/10257846132626153535 2012-06-02T18:19:19+09:00 2018-09-10T16:08:36+09:00 あいさつ つかさです。 今回は、直前までアクティブだったウィンドウにAAを貼り付けられるようにします。 モジュールの導入 pyautoモジュールを入手しましょう。これは、Windowsの操作をカスタマイズ/自動化するためのモジュールです。 解凍したものを、スクリプトと同じフォルダにおきます。 スクリプト 新たにpyautoをインポートし Enterを押したときの挙動に「直前のウィンドウをアクティブにして」「貼り付け」を付け足してます AAlist08.py import wx,os,migemo,re,pyauto migemo_object = None class MyPopupWindo… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は、直前までアクティブだったウィンドウにAAを貼り付けられるようにします。</p> </div> <div class="section"> <h4>モジュールの導入</h4> <p><a href="http://sites.google.com/site/craftware/pyauto">pyauto&#x30E2;&#x30B8;&#x30E5;&#x30FC;&#x30EB;</a>を入手しましょう。これは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>の操作をカスタマイズ/自動化するためのモジュールです。<br /> 解凍したものを、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>と同じフォルダにおきます。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602180529" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602180529.jpg" alt="f:id:tukasa1919:20120602180529j:image" title="f:id:tukasa1919:20120602180529j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></h4> <ol> <li>新たにpyautoをインポートし</li> <li>Enterを押したときの挙動に「直前のウィンドウをアクティブにして」「貼り付け」を付け足してます</li> </ol> <ul> <li>AAlist08.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os,migemo,re,pyauto migemo_object = <span class="synIdentifier">None</span> <span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) <span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() pyauto.Input.send([ pyauto.KeyDown(pyauto.VK_MENU ), pyauto.Key(pyauto.VK_ESCAPE ), pyauto.KeyUp(pyauto.VK_MENU), pyauto.KeyDown(pyauto.VK_CONTROL), pyauto.Key(<span class="synIdentifier">ord</span>(<span class="synConstant">'V'</span>)), pyauto.KeyUp(pyauto.VK_CONTROL) ]) wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.AA_Dict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) self.ShowToolTip() <span class="synStatement">else</span>: event.Skip() event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">ShowToolTip</span>(self): f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre> </div> <div class="section"> <h4>キー操作</h4> <p>OnKeyCharの下の方を見てください。</p> <pre class="code lang-python" data-lang="python" data-unlink> pyauto.Input.send([ pyauto.KeyDown(pyauto.VK_MENU ), pyauto.Key(pyauto.VK_ESCAPE ), pyauto.KeyUp(pyauto.VK_MENU), pyauto.KeyDown(pyauto.VK_CONTROL), pyauto.Key(<span class="synIdentifier">ord</span>(<span class="synConstant">'V'</span>)), pyauto.KeyUp(pyauto.VK_CONTROL) ]) wx.GetApp().OnClose() </pre><p>Enterを押したときの動作に、数行加えています。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>にAAテキストを入れた後、</p> <ol> <li>直前のウィンドウをアクティブにして</li> <li>貼り付け</li> </ol><p>という動作を追加してます。</p><p>まず、直前のウインドウをアクティブに。これは、Alt+Escで実現できますね。Alt+Tabしか知らなかったひとは試してみましょう^^<br /> 次の貼り付けは、Ctrl+Vでできます。</p><p>pyauto.Input.sendで、それに対応したキーを送ります。</p> <ol> <li>Altキーを押して→Escapeキーを一瞬押して離して→Altキーを離してから</li> <li>Ctrlキーを押して→Vキーを一瞬押して離して→Ctrlキーを離す</li> </ol><p>という感じですね。</p> </div> <div class="section"> <h4>まとめ</h4> <p>これで、</p> <ol> <li>直前にアクティブだったウィンドウをアクティブにし</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>に格納したものを貼り付け</li> <li>終了する</li> </ol><p>という一連の動作が可能になりました。メイン部分ですることはもう無いかな?</p> </div> <div class="section"> <h4>一連の流れ画像</h4> <ul> <li><span class="deco" style="font-style:italic;">AAを貼り付けたいウィンドウの上で</span></li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602201009" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602201009.jpg" alt="f:id:tukasa1919:20120602201009j:image" title="f:id:tukasa1919:20120602201009j:image" class="hatena-fotolife" itemprop="image"></a></span></p> <ul> <li><span class="deco" style="font-style:italic;">AAlist.py(今作っている<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>)を起動</span></li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602201010" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602201010.jpg" alt="f:id:tukasa1919:20120602201010j:image" title="f:id:tukasa1919:20120602201010j:image" class="hatena-fotolife" itemprop="image"></a></span></p> <ul> <li><span class="deco" style="font-style:italic;"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>とかカーソルとか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>で貼り付けたいAAを探し</span></li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602201011" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602201011.jpg" alt="f:id:tukasa1919:20120602201011j:image" title="f:id:tukasa1919:20120602201011j:image" class="hatena-fotolife" itemprop="image"></a></span></p> <ul> <li><span class="deco" style="font-style:italic;">Enterで貼り付け</span></li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602201012" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602201012.jpg" alt="f:id:tukasa1919:20120602201012j:image" title="f:id:tukasa1919:20120602201012j:image" class="hatena-fotolife" itemprop="image"></a></span></p> <ul> <li><span class="deco" style="font-style:italic;">よくできました</span></li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602201013" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602201013.jpg" alt="f:id:tukasa1919:20120602201013j:image" title="f:id:tukasa1919:20120602201013j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第六回 PyMigemoでインクリメンタルサーチ hatenablog://entry/10257846132626153575 2012-06-02T17:59:23+09:00 2018-09-10T16:08:40+09:00 あいさつ つかさです。 今回は、PyMigemoを使います。 正規表現について まずは、pythonの正規表現について。reモジュールを使うことで、正規表現が使えます。 パターンをコンパイルし、正規表現オブジェクトを作る そのオブジェクトから、match()あるいはsearch()で、検索したい語を入れ、返り値を得る という順序です。PyMigemoを使うと、この正規表現のためのパターンを得ることができます。 PyMigemoのインストール migemo.pydと、migemo.dllをスクリプトのあるフォルダにおけば、このモジュールを使えるようになります。 また、migemo用のDictもど… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は、PyMigemoを使います。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>について</h4> <p>まずは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>について。reモジュールを使うことで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>が使えます。</p> <ol> <li>パターンを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>オブジェクトを作る</li> <li>そのオブジェクトから、match()あるいはsearch()で、検索したい語を入れ、返り値を得る</li> </ol><p>という順序です。</p><p><a href="http://www.atzm.org/etc/pymigemo.html">PyMigemo</a>を使うと、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>のためのパターンを得ることができます。</p> </div> <div class="section"> <h4>PyMigemoのインストール</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>.pydと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>.dllを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>のあるフォルダにおけば、このモジュールを使えるようになります。<br /> また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>用のDictもどこかからダウンロードしましょう。これも同じフォルダにおきます。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120527211539" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120527/20120527211539.jpg" alt="f:id:tukasa1919:20120527211539j:image" title="f:id:tukasa1919:20120527211539j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>でパターンを得る</h4> <p>例えば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>オブジェクトを作った後、query()にtukaというのを与えると</p> <pre class="code lang-python" data-lang="python" data-unlink>([捕遺仕疲遣柄攫束塚使冢掴閊障把支捉司掌元曹搏]|tuka|tuka|つか|付かぬ事|ツカ) </pre><p>このようなパターンを得ることができます。<br /> このパターンを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>に利用すれば、ローマ字でも日本語を検索できるわけです。</p> </div> <div class="section"> <h4>プログラム</h4> <p>以前から変更したのは大きくは二点。</p> <ol> <li>IncrementalSearchクラスを付け加えた</li> <li>OnKeyTxtを付け加えた</li> </ol> <ul> <li>AAlist07.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os,migemo,re migemo_object = <span class="synIdentifier">None</span> <span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) <span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.AA_Dict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) self.ShowToolTip() <span class="synStatement">else</span>: event.Skip() event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">ShowToolTip</span>(self): f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120527211540" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120527/20120527211540.jpg" alt="f:id:tukasa1919:20120527211540j:image" title="f:id:tukasa1919:20120527211540j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>IncrementalSearchクラス</h4> <p>検索文字列と調べたいリストを受け取り、検索文字列に一致したもののみのリストを返すIncrementalSearchクラスを作製しましょう。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list </pre><p>__init__のところを見てください。引数として</p> <ul> <li>検索に用いたい文字列</li> <li>その文字列で検索したいリスト</li> </ul><p>を受け取ります。</p><p>GetBackListは、受け取ったリストを受け取った文字列で<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>検索し、それにヒットした要素のみを、新しいリストとして返す関数です。GetBackListについて説明します。</p> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>オブジェクトの作成</h5> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) </pre><p>まず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>オブジェクトがあるかどうかで分岐します。無い場合は、作製します。<br /> 一々オブジェクトを作ると、時間がかかるのでこのようにしています。</p> </div> <div class="section"> <h5>検索パターンの取得と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a></h5> <pre class="code lang-python" data-lang="python" data-unlink> re_pattern = migemo_object.query(self.pattern) <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> </pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>オブジェクトに、引数として受け取ったエディットボックスに入力された文字を入れ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>用のパターンを取得します。<br /> その後、それを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>します。</p> </div> <div class="section"> <h5>一致したリストを返す</h5> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list </pre><p>ついで、引数として取得したリストの一々の要素について、それがさきに作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>パターンに一致するかを調べていきます。もし一致したら、それを新しいリストに加えます。<br /> こうやって、古いリストから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>に一致したリストを新しく作り直すわけですね。<br /> このようにして出来た新しいリストを、returnで返します。</p> </div> </div> <div class="section"> <h4>本体と結びつける</h4> <div class="section"> <h5>OnText関数</h5> <p>エディットボックスで何か入力されるたびにこのクラスを呼び出し、リストを受け取り、ListBoxにセットすればいいわけですね。<br /> そのための関数OnTextを作製します。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.AA_Dict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) self.ShowToolTip() <span class="synStatement">else</span>: event.Skip() event.Skip() </pre><p>GetValue()でエディットボックスの文字列を受け取ります。<br /> 次に、先に作ったIncrementalSearchにその文字列と、ファイル名のリストを投げます。<br /> そして戻ってきた新しいリストをListBoxにセットし、ListBoxの一番上を選択した状態にし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>を表示します。</p> </div> <div class="section"> <h5>EVT_TEXTで結びつけ</h5> <p>ついで、これをエディットボックスと結びつけます。class MyTxtFrmの初期化メソッド__init__に、次の一文を付け加えます。</p> <pre class="code lang-python" data-lang="python" data-unlink> self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) </pre><p>これで、エディットボックスに文字が入力されるたびに、OnText関数が呼び出されることになります。</p> </div> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>の様子</h4> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602194928" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602194928.jpg" alt="f:id:tukasa1919:20120602194928j:image" title="f:id:tukasa1919:20120602194928j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602194931" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602194931.jpg" alt="f:id:tukasa1919:20120602194931j:image" title="f:id:tukasa1919:20120602194931j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602194929" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602194929.jpg" alt="f:id:tukasa1919:20120602194929j:image" title="f:id:tukasa1919:20120602194929j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120602194930" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120602/20120602194930.jpg" alt="f:id:tukasa1919:20120602194930j:image" title="f:id:tukasa1919:20120602194930j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第八回 設定ファイル hatenablog://entry/10257846132626153455 2012-06-02T05:04:25+09:00 2018-09-10T16:08:28+09:00 あいさつ つかさです。 今回は設定ファイルです。ConfigParserというモジュールを使います。 設定が必要なもの まずは設定ファイルを作成しましょう。 大きさ(幅と高さ) 位置(x,y) ツールチップの色 あたりが、必要なものでしょうか。 以下のファイルを、スクリプトのあるフォルダに保存してください。 aalist.ini [DEFAULT] backgroundcolour = #B0E0E6 width = 200 height = 250 x = 400 y = 300この設定ファイルを読み込み、反映するようにスクリプトを改造します。 オブジェクトを作製 iniファイルを読み込み … <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は設定ファイルです。ConfigParserというモジュールを使います。</p> </div> <div class="section"> <h4>設定が必要なもの</h4> <p>まずは設定ファイルを作成しましょう。</p> <ul> <li>大きさ(幅と高さ)</li> <li>位置(x,y)</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>の色</li> </ul><p>あたりが、必要なものでしょうか。<br /> 以下のファイルを、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>のあるフォルダに保存してください。</p> <ul> <li>aalist.ini</li> </ul><pre class="code" data-lang="" data-unlink>[DEFAULT] backgroundcolour = #B0E0E6 width = 200 height = 250 x = 400 y = 300</pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120603041009" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120603/20120603041009.jpg" alt="f:id:tukasa1919:20120603041009j:image" title="f:id:tukasa1919:20120603041009j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>この設定ファイルを読み込み、反映するように<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を改造します。</p> <ul> <li>オブジェクトを作製</li> <li>iniファイルを読み込み</li> <li>read(セクション,値)で、個々の要素を取り出す</li> </ul><p>が一連の流れです。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></h4> <p>ConfigParserというモジュールをインポートしてます。</p> <ul> <li>AAlist09.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os,migemo,re,pyauto,ConfigParser migemo_object = <span class="synIdentifier">None</span> <span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style, ini): wx.PopupWindow.__init__(self, parent, style) self.ini = ini b_color = self.ini.get( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;BackgroundColour&quot;</span> ) self.SetBackgroundColour(b_color) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) <span class="synStatement">class</span> <span class="synIdentifier">IncrementalSearch</span>: <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self,pattern,<span class="synIdentifier">list</span>): self.pattern = pattern self.new_list = [] self.old_list = <span class="synIdentifier">list</span> <span class="synStatement">def</span> <span class="synIdentifier">GetBackList</span>(self): <span class="synStatement">global</span> migemo_object <span class="synStatement">if</span> migemo_object==<span class="synIdentifier">None</span>: migemo_object = migemo.Migemo(<span class="synConstant">'Dict\migemo-dict'</span>) re_pattern = migemo_object.query(self.pattern) <span class="synIdentifier">print</span> re_pattern <span class="synStatement">try</span>: migemo_re_object = re.<span class="synIdentifier">compile</span>(re_pattern, re.IGNORECASE) <span class="synStatement">except</span> re.error: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">for</span> x <span class="synStatement">in</span> self.old_list: <span class="synStatement">if</span> migemo_re_object.search(x): self.new_list.append(x) <span class="synStatement">return</span> self.new_list <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>, ini): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER, ini) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() pyauto.Input.send([ pyauto.KeyDown(pyauto.VK_MENU ), pyauto.Key(pyauto.VK_ESCAPE ), pyauto.KeyUp(pyauto.VK_MENU), pyauto.KeyDown(pyauto.VK_CONTROL), pyauto.Key(<span class="synIdentifier">ord</span>(<span class="synConstant">'V'</span>)), pyauto.KeyUp(pyauto.VK_CONTROL) ]) wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">OnText</span>(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.AA_Dict.keys()) <span class="synStatement">try</span>: new_list = isearch.GetBackList() <span class="synStatement">except</span>: <span class="synStatement">return</span> <span class="synIdentifier">False</span> <span class="synStatement">if</span> new_list: self.LBox.Set(new_list) self.LBox.SetSelection(<span class="synConstant">0</span>) self.ShowToolTip() <span class="synStatement">else</span>: event.Skip() event.Skip() <span class="synStatement">def</span> <span class="synIdentifier">ShowToolTip</span>(self): f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.INI_FILE = <span class="synConstant">&quot;aalist.ini&quot;</span> self.INI = ConfigParser.SafeConfigParser() self.INI.read(self.INI_FILE) self.width = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;width&quot;</span> ) self.height = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;height&quot;</span> ) self.x = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;x&quot;</span> ) self.y = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;y&quot;</span> ) self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>, self.INI) self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120603045704" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120603/20120603045704.jpg" alt="f:id:tukasa1919:20120603045704j:image" title="f:id:tukasa1919:20120603045704j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>ウィンドウの位置と大きさ</h4> <pre class="code lang-python" data-lang="python" data-unlink><span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.INI_FILE = <span class="synConstant">&quot;aalist.ini&quot;</span> self.INI = ConfigParser.SafeConfigParser() self.INI.read(self.INI_FILE) self.width = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;width&quot;</span> ) self.height = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;height&quot;</span> ) self.x = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;x&quot;</span> ) self.y = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;y&quot;</span> ) self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>, self.INI) self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> </pre><p>MyAppの初期化の際に、</p> <ol> <li>設定ファイルオブジェクトを作り</li> <li>位置と大きさの値を取り出し</li> <li>TxtFrmに設定ファイルオブジェクトを引数として与える</li> </ol><p>ということをしてます。</p> <pre class="code lang-python" data-lang="python" data-unlink> self.INI_FILE = <span class="synConstant">&quot;aalist.ini&quot;</span> self.INI = ConfigParser.SafeConfigParser() self.INI.read(self.INI_FILE) </pre><p>最初の三行で、ConfigParser.SafeConfigParser()でオブジェクトを作り、iniファイルを読み込ませてます。</p> <pre class="code lang-python" data-lang="python" data-unlink> self.width = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;width&quot;</span> ) self.height = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;height&quot;</span> ) self.x = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;x&quot;</span> ) self.y = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;y&quot;</span> ) </pre><p>次に、getintでそのオブジェクトから必要な値を取り出してます。</p> <ul> <li>数字を取り出すならgetint</li> <li>文字列を取り出すならget</li> </ul><p>です。</p> <pre class="code lang-python" data-lang="python" data-unlink> self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>, self.INI) self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height) </pre><p>そしてSetDimensionsで、ウィンドウを取り出した位置と大きさにセットしてるわけですね。<br /> また、MyTxtFrmの引数としてself.INIを与えているのにも注意してください。</p> </div> <div class="section"> <h4>他のクラスでオブジェクトを利用</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示のためには、別のクラスでもINIファイルを読み込まなくてはいけません。ですが一々別のクラスでも、一々同じようにオブジェクトを作って、というのは面倒ですね。</p><p>そこで、一度作ったiniオブジェクトを、引数として各クラスに渡すようにしてます。</p> <ol> <li>MyFrmでオブジェクトを作り</li> <li>それをMyTxtFrmに引数として与え</li> <li>さらにMyTxtFrmからMyPopupWindowにオブジェクトを引数として与える</li> </ol><p>ということをしてます。</p> </div> <div class="section"> <h4>位置の記憶</h4> <p>終了時の大きさと位置を記憶し、起動時にはそこで表示したいという場合があると思います。それができるように、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を書き換えてみましょう。</p><p>その場合は、</p> <ol> <li>終了する直前にiniオブジェクトを呼び出し</li> <li>writeで書き込む</li> </ol><p>そして起動したときには</p> <ol> <li>iniでその箇所を読み込む</li> </ol><p>というようにします。まずは設定ファイルを書き換えてください</p> <ul> <li>aalist.ini</li> </ul><pre class="code" data-lang="" data-unlink>[DEFAULT] backgroundcolour = #B0E0E6 width = 200 height = 250 x = 400 y = 300 historymode = 1 [HISTORY] width = 188 height = 238 x = 254 y = 278</pre><p>DEFAULTセクションに、位置や大きさを記録するかどうかを決められるようhistorymodeを付け足してます。これが0なら記憶しない。1なら記憶するようにします。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></h4> <p>MyAppの初期化のところで、前回の位置や記録を読み込むかどうかで分岐させてます<br /> 終了時に位置を記録するため、WriteIniとOnExitの二つの関数を付け足してます</p> <ul> <li>AAlist10.py</li> </ul><pre class="code" data-lang="" data-unlink>import wx,os,migemo,re,pyauto,ConfigParser migemo_object = None class MyPopupWindow(wx.PopupWindow): def __init__(self, parent, style, ini): wx.PopupWindow.__init__(self, parent, style) self.ini = ini b_color = self.ini.get( &#34;DEFAULT&#34;, &#34;BackgroundColour&#34; ) self.SetBackgroundColour(b_color) self.st = wx.StaticText(self, -1,pos=(10,10)) def ChangeTxt(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20) self.Show(True) class IncrementalSearch: def __init__(self,pattern,list): self.pattern = pattern self.new_list = [] self.old_list = list def GetBackList(self): global migemo_object if migemo_object==None: migemo_object = migemo.Migemo(&#39;Dict\migemo-dict&#39;) re_pattern = migemo_object.query(self.pattern) print re_pattern try: migemo_re_object = re.compile(re_pattern, re.IGNORECASE) except re.error: return False for x in self.old_list: if migemo_re_object.search(x): self.new_list.append(x) return self.new_list class MyTxtFrm(wx.Frame): def __init__(self, parent, id, ini): wx.Frame.__init__(self, parent, id) aa_list = os.listdir(&#34;AAList&#34;) self.AA_Dict = {} for x in aa_list: key = os.path.splitext(x)[0].decode(&#34;shift-jis&#34;) path = os.path.join(&#34;AAlist&#34;,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER, ini) self.TxtCtr = wx.TextCtrl(self, -1) self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, 0, wx.EXPAND) self.sizer.Add(self.LBox, 1, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(1) self.sizer.Fit(self) def OnKeyChar(self,event): key = event.GetKeyCode() if key == wx.WXK_ESCAPE: wx.GetApp().OnExit() elif key == wx.WXK_UP: count = self.LBox.GetCount() next = self.LBox.GetSelection() - 1 if next &gt;= 0: self.LBox.SetSelection(next) else: self.LBox.SetSelection(count - 1) f = open(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + 45) self.win.ChangeTxt(fr,pos) elif key == wx.WXK_DOWN: count = self.LBox.GetCount() next = self.LBox.GetSelection() + 1 if next &lt; count: self.LBox.SetSelection(next) else: self.LBox.SetSelection(0) f = open(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + 45) self.win.ChangeTxt(fr,pos) elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = open(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() pyauto.Input.send([ pyauto.KeyDown(pyauto.VK_MENU ), pyauto.Key(pyauto.VK_ESCAPE ), pyauto.KeyUp(pyauto.VK_MENU), pyauto.KeyDown(pyauto.VK_CONTROL), pyauto.Key(ord(&#39;V&#39;)), pyauto.KeyUp(pyauto.VK_CONTROL) ]) wx.GetApp().OnExit() else: event.Skip() def OnText(self,event): word = self.TxtCtr.GetValue() isearch = IncrementalSearch(word,self.AA_Dict.keys()) try: new_list = isearch.GetBackList() except: return False if new_list: self.LBox.Set(new_list) self.LBox.SetSelection(0) self.ShowToolTip() else: event.Skip() event.Skip() def ShowToolTip(self): f = open(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + 45) self.win.ChangeTxt(fr,pos) class MyApp(wx.PySimpleApp): def OnInit(self): self.INI_FILE = &#34;aalist.ini&#34; self.INI = ConfigParser.SafeConfigParser() self.INI.read(self.INI_FILE) if self.INI.getint( &#34;DEFAULT&#34;, &#34;HistoryMode&#34; ) == 1: self.width = self.INI.getint( &#34;HISTORY&#34;, &#34;Width&#34; ) self.height = self.INI.getint( &#34;HISTORY&#34;, &#34;Height&#34; ) self.x = self.INI.getint( &#34;HISTORY&#34;, &#34;X&#34; ) self.y = self.INI.getint( &#34;HISTORY&#34;, &#34;Y&#34; ) else: self.width = self.INI.getint( &#34;DEFAULT&#34;, &#34;Width&#34; ) self.height = self.INI.getint( &#34;DEFAULT&#34;, &#34;Height&#34; ) self.x = self.INI.getint( &#34;DEFAULT&#34;, &#34;X&#34; ) self.y = self.INI.getint( &#34;DEFAULT&#34;, &#34;Y&#34; ) self.TxtFrm = MyTxtFrm(None, -1, self.INI) self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() return 1 def WriteINI(self): if self.INI.getint( &#34;DEFAULT&#34;, &#34;HistoryMode&#34; ) == 1: x = str(self.TxtFrm.GetPosition()[0]) y = str(self.TxtFrm.GetPosition()[1]) width = str(self.TxtFrm.GetSize()[0]) height = str(self.TxtFrm.GetSize()[1]) self.INI.set(&#39;HISTORY&#39;,&#39;Width&#39;,width) self.INI.set(&#39;HISTORY&#39;,&#39;Height&#39;,height) self.INI.set(&#39;HISTORY&#39;,&#39;X&#39;,x) self.INI.set(&#39;HISTORY&#39;,&#39;Y&#39;,y) f = open(self.INI_FILE, &#34;w&#34;) self.INI.write(f) f.close() else: return def OnExit(self): self.WriteINI() wx.Exit() app = MyApp() app.MainLoop()</pre> </div> <div class="section"> <h4>前回の位置の読み込み</h4> <p>MyAppの初期化のところを見てください。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">if</span> self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;HistoryMode&quot;</span> ) == <span class="synConstant">1</span>: self.width = self.INI.getint( <span class="synConstant">&quot;HISTORY&quot;</span>, <span class="synConstant">&quot;Width&quot;</span> ) self.height = self.INI.getint( <span class="synConstant">&quot;HISTORY&quot;</span>, <span class="synConstant">&quot;Height&quot;</span> ) self.x = self.INI.getint( <span class="synConstant">&quot;HISTORY&quot;</span>, <span class="synConstant">&quot;X&quot;</span> ) self.y = self.INI.getint( <span class="synConstant">&quot;HISTORY&quot;</span>, <span class="synConstant">&quot;Y&quot;</span> ) <span class="synStatement">else</span>: self.width = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;Width&quot;</span> ) self.height = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;Height&quot;</span> ) self.x = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;X&quot;</span> ) self.y = self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;Y&quot;</span> ) </pre><p>前回の位置と大きさを読み込む設定になっていれば、HISTORYTセクションから読み込むように。なっていなければDEFAULTセクションで設定した値を読み込むようにしてます。</p> </div> <div class="section"> <h4>位置と大きさの記録</h4> <p>AAlist終了時には、OnExitを利用するようにします。AAlistを終了する時、というのは</p> <ul> <li>Escapeキーを押したとき</li> <li>Enterで貼り付けたとき</li> </ul><p>の二通りですね。それぞれ、今まではwx.Exit()で終了してたのを、wx.GetApp().OnExit()で新しく付け足した関数で終了するようにかえてます。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">def</span> <span class="synIdentifier">WriteINI</span>(self): <span class="synStatement">if</span> self.INI.getint( <span class="synConstant">&quot;DEFAULT&quot;</span>, <span class="synConstant">&quot;HistoryMode&quot;</span> ) == <span class="synConstant">1</span>: x = <span class="synIdentifier">str</span>(self.TxtFrm.GetPosition()[<span class="synConstant">0</span>]) y = <span class="synIdentifier">str</span>(self.TxtFrm.GetPosition()[<span class="synConstant">1</span>]) width = <span class="synIdentifier">str</span>(self.TxtFrm.GetSize()[<span class="synConstant">0</span>]) height = <span class="synIdentifier">str</span>(self.TxtFrm.GetSize()[<span class="synConstant">1</span>]) self.INI.<span class="synIdentifier">set</span>(<span class="synConstant">'HISTORY'</span>,<span class="synConstant">'Width'</span>,width) self.INI.<span class="synIdentifier">set</span>(<span class="synConstant">'HISTORY'</span>,<span class="synConstant">'Height'</span>,height) self.INI.<span class="synIdentifier">set</span>(<span class="synConstant">'HISTORY'</span>,<span class="synConstant">'X'</span>,x) self.INI.<span class="synIdentifier">set</span>(<span class="synConstant">'HISTORY'</span>,<span class="synConstant">'Y'</span>,y) f = <span class="synIdentifier">open</span>(self.INI_FILE, <span class="synConstant">&quot;w&quot;</span>) self.INI.write(f) f.close() <span class="synStatement">else</span>: <span class="synStatement">return</span> <span class="synStatement">def</span> <span class="synIdentifier">OnExit</span>(self): self.WriteINI() wx.Exit() </pre><p>DEFAULTセクションのhistorymodeの値をチェックし、前回の位置や大きさを記憶する設定であれば</p> <ol> <li>現在のウィンドウの位置と大きさを取り出し</li> <li>それをINIオブジェクトにセットし</li> <li>INIファイルに書き込む</li> </ol><p>ということをします。</p> </div> tukasa1919 AA管理ツール SETZER ver0.01 公開 hatenablog://entry/10257846132626153631 2012-05-29T14:19:17+09:00 2018-09-10T16:08:46+09:00 あいさつ AA管理ツールが一応完成したので、公開します。 現在連載している「wxPythonでAA管理ツールを作ろう!」シリーズでは、九回目あたりで到達するであろうソースを使ってます。 直前までアクティブだったウィンドウに、選択したAAを貼り付けます。Download SETZER ver.0.01.zip ※最新版はhoehoeSoftに 特徴 ツールチップ表示 AAをテキスト形式で管理 非常駐 Migemoによるインクリメンタルサーチ 操作 ウィンドウを閉じる→ESC アイテム選択→カーソルキー 選択アイテム貼り付け→Enter Migemoを使いたいとき dictディレクトリにMigem… <div class="section"> <h4>あいさつ</h4> <p>AA管理ツールが一応完成したので、公開します。<br /> 現在連載している「<a class="keyword" href="http://d.hatena.ne.jp/keyword/wxPython">wxPython</a>でAA管理ツールを作ろう!」シリーズでは、九回目あたりで到達するであろうソースを使ってます。<br /> 直前までアクティブだったウィンドウに、選択したAAを貼り付けます。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120529133847" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120529/20120529133847.jpg" alt="f:id:tukasa1919:20120529133847j:image" title="f:id:tukasa1919:20120529133847j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p><del datetime="2012-08-07T18:29:14+09:00">Download SETZER ver.0.01.zip</del><br /> ※最新版は<a href="https://sites.google.com/site/hoehoesoft/">hoehoeSoft</a>に</p> <ul> <li>特徴 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示</li> <li>AAをテキスト形式で管理</li> <li>非常駐</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>による<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a></li> </ul></li> </ul> <ul> <li>操作 <ul> <li>ウィンドウを閉じる→ESC</li> <li>アイテム選択→カーソルキー</li> <li>選択アイテム貼り付け→Enter</li> </ul></li> </ul> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>を使いたいとき</h4> <p>dict<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>の辞書ファイルを配置してください。</p> <ul> <li>辞書ファイル</li> </ul> <ul> <li> <ul> <li>han2zen.dat</li> <li>hira2kata.dat</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>-dict</li> <li>roma2hira.dat</li> </ul></li> </ul><p>後は、SETZER.iniを編集しIsearchType = 1にすることで機能が有効になります。</p> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第五回 クリップボードに保存 hatenablog://entry/10257846132626153642 2012-05-25T21:35:03+09:00 2018-09-10T16:08:48+09:00 あいさつ つかさです。 今回は、クリップボードに選択したファイルの中身をコピーします。 クリップボード MyTxtFrmクラスのOnKeyCharに、Enter用の分岐を付け加えてます。 AAlist06.py import wx,os class MyPopupWindow(wx.PopupWindow): def __init__(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -1,pos=(10,10)) def ChangeTxt(self… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>に選択したファイルの中身をコピーします。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a></h4> <p>MyTxtFrmクラスのOnKeyCharに、Enter用の分岐を付け加えてます。</p> <ul> <li>AAlist06.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os <span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() wx.Exit() <span class="synStatement">else</span>: event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525183449" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525183449.jpg" alt="f:id:tukasa1919:20120525183449j:image" title="f:id:tukasa1919:20120525183449j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <div class="section"> <h5>Enterを押したときの分岐</h5> <p>Enterを押せば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>に選択したファイルの中身をコピーし、終了するようにします。<br /> Charの分岐にEnterを付け加えます。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">elif</span> key <span class="synStatement">in</span> (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): c_board = wx.Clipboard() f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() c_board.SetData(wx.TextDataObject(fr)) c_board.Flush() c_board.Close() wx.Exit() <span class="synStatement">else</span>: event.Skip() </pre><p>この箇所ですね。ListBoxで選択してるファイル名に対応したパスを、辞書を利用して取得し、その中身を取り出して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>にセットしてます。<br /> その後に、wx.Exit()でプログラムを終了しています。</p> </div> </div> <div class="section"> <h4>次回の予定</h4> <p>これで、とりあえずはAA管理ツールとして一応は完成した、といってもいいのではないでしょうか。<br /> 次回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>ができるようにする予定です</p> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第四回 ツールチップ表示 hatenablog://entry/10257846132626153679 2012-05-25T07:56:03+09:00 2018-09-10T16:08:51+09:00 あいさつ つかさです。 今回は、リストボックスで選択している箇所の内容をツールチップ表示できるようにします。 前回からの変更点 ツールチップ表示用に、新しくMyPopUpWindowクラスを作成してます。 ListBoxで選択カーソルが移動すれば、ツールチップの表示内容が変化するようにしてます。 AAlist05.py import wx,os class MyPopupWindow(wx.PopupWindow): def __init__(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st =… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は、リストボックスで選択している箇所の内容を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示できるようにします。</p> </div> <div class="section"> <h4>前回からの変更点</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示用に、新しくMyPopUpWindowクラスを作成してます。<br /> ListBoxで選択カーソルが移動すれば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>の表示内容が変化するようにしてます。</p> <ul> <li>AAlist05.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os <span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.win = MyPopupWindow(self, wx.SIMPLE_BORDER) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) <span class="synStatement">else</span>: event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525071053" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525071053.jpg" alt="f:id:tukasa1919:20120525071053j:image" title="f:id:tukasa1919:20120525071053j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>MyPopUpWindowクラスの作成</h4> <p>MyPopupWindowが、今回新しく付け加えたクラスです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>を表示し、操作するためのクラスです。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synStatement">class</span> <span class="synIdentifier">MyPopupWindow</span>(wx.PopupWindow): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.st = wx.StaticText(self, -<span class="synConstant">1</span>,pos=(<span class="synConstant">10</span>,<span class="synConstant">10</span>)) <span class="synStatement">def</span> <span class="synIdentifier">ChangeTxt</span>(self,message,pos): self.st.SetLabel(message) sz = self.st.GetBestSize() gps = self.GetSize() self.SetDimensions(pos[<span class="synConstant">0</span>], pos[<span class="synConstant">1</span>], sz.width + <span class="synConstant">20</span> , sz.height + <span class="synConstant">20</span>) self.Show(<span class="synIdentifier">True</span>) </pre><p>初期化メソッドの方は単純ですね。スタティックテキストをセットしているだけです。<br /> ChangeTxt関数は、引数として表示する文字列と、ポジションとを受け取ります。</p> <ol> <li>引数で与えられたメッセージを、SetLabelでStaticTextに貼り付けます。</li> <li>ついで、GetBestSize()でそのメッセージにあう<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>の大きさの値を返します。</li> <li>SetDimensions()は、大きさと位置を指定する関数です。引数として受け取ったposから位置を。GetBestSize()で得た値から適切なサイズをセットしてます。</li> <li>Show(True)で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>を表示します</li> </ol> </div> <div class="section"> <h4>OnKeyChar</h4> <p>カーソルを上下すれば、それに併せて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>が表示されるようにします。OnKeyCharに数行付け加えます。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) f = <span class="synIdentifier">open</span>(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read() gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + <span class="synConstant">45</span>) self.win.ChangeTxt(fr,pos) </pre><p>下半分が今回付け加えた箇所ですね。<br /> <br /> </p> <div class="section"> <h5>ファイル内容の取得</h5> <pre class="code" data-lang="" data-unlink> f = open(self.AA_Dict[self.LBox.GetStringSelection()]) fr = f.read()</pre><p>一行目で、リストボックスで現在選択している文字列を取得し、それに対応したパスを、辞書を利用して取り出し、そのファイルを開いています。<br /> 二行目で、その内容を読み込んでます。<br /> <br /> </p> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示位置の取得</h5> <pre class="code" data-lang="" data-unlink> gps = self.GetSize() gp = self.GetPosition() pos = (gp.x + gps.x, gp.y + 45)</pre><p>ここでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>を表示する位置を取得してます。取得したい位置は、ちょうど○をつけたあたり。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525065907" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525065907.jpg" alt="f:id:tukasa1919:20120525065907j:image" title="f:id:tukasa1919:20120525065907j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>この位置を計算するために、現在の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>の位置と、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>の幅が必要になるわけですね。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>の位置をGetPosition()で。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>の大きさをGetSize()で取得。ここから適切なポジションを割り出します。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525071054" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525071054.jpg" alt="f:id:tukasa1919:20120525071054j:image" title="f:id:tukasa1919:20120525071054j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h5>ChangeTxtにファイル内容と表示位置を渡す</h5> <pre class="code" data-lang="" data-unlink> self.win.ChangeTxt(fr,pos)</pre><p>そして最後の行で、ここまでで取得した、カーソル位置に対応しているファイルの中身と、ポジションとをMyPopUpWindowクラスのChangeTxt関数に送っているわけです。</p><p>これで、カーソルを上下すれば、それに併せて<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>の横に、その中身を表示する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>を表示することができるようになりました。</p> </div> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第二回 ListBoxの操作 hatenablog://entry/10257846132626153734 2012-05-24T18:13:40+09:00 2018-09-10T16:08:59+09:00 あいさつ つかさです。 今回は、前回作ったGuiにリストをセットし、操作してみます。やっていることは、Pythonでコマンドラインランチャを作ろう!第二回イベント編とほぼ同じです。そちらもあわせて参考にしてください。 リストの作成 AAlist02.py import wx List = ["tukasa","konata","kagami","miwiki","yutaka", "minami","misao","ayano","hiyori","Martin"] class MyTxtFrm(wx.Frame): def __init__(self, parent, id): wx.Fra… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回は、前回作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gui">Gui</a>にリストをセットし、操作してみます。</p><p>やっていることは、<a href="http://d.hatena.ne.jp/tukasa1919/20100113/1263396691">Python&#x3067;&#x30B3;&#x30DE;&#x30F3;&#x30C9;&#x30E9;&#x30A4;&#x30F3;&#x30E9;&#x30F3;&#x30C1;&#x30E3;&#x3092;&#x4F5C;&#x308D;&#x3046;&#xFF01;&#x7B2C;&#x4E8C;&#x56DE;&#x30A4;&#x30D9;&#x30F3;&#x30C8;&#x7DE8;</a>とほぼ同じです。そちらもあわせて参考にしてください。</p> </div> <div class="section"> <h4>リストの作成</h4> <ul> <li>AAlist02.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx List = [<span class="synConstant">&quot;tukasa&quot;</span>,<span class="synConstant">&quot;konata&quot;</span>,<span class="synConstant">&quot;kagami&quot;</span>,<span class="synConstant">&quot;miwiki&quot;</span>,<span class="synConstant">&quot;yutaka&quot;</span>, <span class="synConstant">&quot;minami&quot;</span>,<span class="synConstant">&quot;misao&quot;</span>,<span class="synConstant">&quot;ayano&quot;</span>,<span class="synConstant">&quot;hiyori&quot;</span>,<span class="synConstant">&quot;Martin&quot;</span>] <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = List) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120524122805" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120524/20120524122805.jpg" alt="f:id:tukasa1919:20120524122805j:image" title="f:id:tukasa1919:20120524122805j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>前回から変更したのは二行。Listの追加と、それをListBoxの引数に追加したことです。<br /> まずはリストについて。見たままですね。</p> <pre class="code" data-lang="" data-unlink>List = [&#34;tukasa&#34;,&#34;konata&#34;,&#34;kagami&#34;,&#34;miwiki&#34;,&#34;yutaka&#34;, &#34;minami&#34;,&#34;misao&#34;,&#34;ayano&#34;,&#34;hiyori&#34;,&#34;Martin&#34;]</pre><p>これをListBoxにセットするため、ListBoxの引数にchoices = Listを追加します。</p> <pre class="code" data-lang="" data-unlink>self.LBox = wx.ListBox(self, -1, choices = List)</pre> </div> <div class="section"> <h4>リストボックスをエディットボックスから操作</h4> <p>AAlist02.pyからの変更は二点です。<br /> 関数OnKeyCharを付け加え、初期化メソッドに一文付け加えています。</p> <ul> <li>AAlist03.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx List = [<span class="synConstant">&quot;tukasa&quot;</span>,<span class="synConstant">&quot;konata&quot;</span>,<span class="synConstant">&quot;kagami&quot;</span>,<span class="synConstant">&quot;miwiki&quot;</span>,<span class="synConstant">&quot;yutaka&quot;</span>, <span class="synConstant">&quot;minami&quot;</span>,<span class="synConstant">&quot;misao&quot;</span>,<span class="synConstant">&quot;ayano&quot;</span>,<span class="synConstant">&quot;hiyori&quot;</span>,<span class="synConstant">&quot;Martin&quot;</span>] <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = List) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">else</span>: event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120524180326" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120524/20120524180326.jpg" alt="f:id:tukasa1919:20120524180326j:image" title="f:id:tukasa1919:20120524180326j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <div class="section"> <h5>イベント用の関数OnKeyCharを作成</h5> <p>ついで、エディットボックスからリストボックスを操作できるようにします。<br /> 文字を入力して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>をし、絞り込むということを後々するため、フォーカスはずっとエディットボックスになければならない。そこで、エディットボックスでキーを操作すればそれでリストボックスで動作するように、設定する必要があります。<br /> キーが押されたときに発生させるためのイベント用の関数OnKeyCharを作成します。</p> <pre class="code lang-python" data-lang="python" data-unlink> <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">else</span>: event.Skip() </pre><p>event.GetKeyCode()で打たれたキーを受け取り、そのキーによって</p> <ul> <li>Escape</li> <li>カーソル上</li> <li>カーソル下</li> </ul><p>の三つに分岐させています。</p> <ul> <li>キーが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ケープキー(wx.WXK_ESCAPE)だったら、wx.Exit()で終了させます。</li> <li>キーがカーソル上(wx.WXK_UP)だったら、GetSelection()で現在リストボックスで選択しているのは上から何番目かを受け取り、その一つ上を、SetSelection()でリストボックスにセットしてます。</li> <li>カーソル下(wx.WXK_DOWN)だったら、GetSelection()で現在リストボックスで選択している位置を受け取り、その一つ下を、SetSelection()でリストボックスにセットしてます。</li> </ul><p>GetCount()でリストボックスにあるアイテムの総数を受け取ったり、ifで条件分岐をしたりしているのは、端まで行ったときにループさせるためです。</p> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>と関数を結びつける</h5> <p>ついで、これをエディットボックスと結びつけます。class MyTxtFrmの初期化メソッド__init__に、次の一文を付け加えます。</p> <pre class="code" data-lang="" data-unlink>self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)</pre><p>これで、エディットボックスで上下カーソルを押すことで、リストボックスの選択カーソルを移動できるようになりました。</p> </div> </div> tukasa1919 wxPythonでAA管理ツールを作ろう!第三回 AAListと辞書 hatenablog://entry/10257846132626153704 2012-05-24T01:06:03+09:00 2018-09-10T16:08:55+09:00 あいさつ つかさです。今まではコマンドラインランチャ編と同じような進行でしたが、今回からいよいよAA管理ツールっぽいことをしていきます。 リストボックスにAAListフォルダ内のファイルが一覧表示されるようにします。 準備 AAlist.pyと同じフォルダに、AAListというフォルダを作ります。その中に、 ファイル名→アスキーアートの名前.txt ファイルの内容→アスキーアート となるファイルを、いくつか作ってください。 AAList内のファイル名をリスト化 前回から、MyTxtFrmクラスの初期化メソッドのところに数行追加してます。 AAlist04.py import wx,os cla… <div class="section"> <h4>あいさつ</h4> <p>つかさです。今までは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>ランチャ編と同じような進行でしたが、今回からいよいよAA管理ツールっぽいことをしていきます。<br /> リストボックスにAAListフォルダ内のファイルが一覧表示されるようにします。</p> </div> <div class="section"> <h4>準備</h4> <p>AAlist.pyと同じフォルダに、AAListというフォルダを作ります。</p><p>その中に、</p> <ul> <li>ファイル名→<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%AD%A1%BC%A5%A2%A1%BC%A5%C8">アスキーアート</a>の名前.txt</li> <li>ファイルの内容→<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%AD%A1%BC%A5%A2%A1%BC%A5%C8">アスキーアート</a></li> </ul><p>となるファイルを、いくつか作ってください。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525004504" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525004504.jpg" alt="f:id:tukasa1919:20120525004504j:image" title="f:id:tukasa1919:20120525004504j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120524204040" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120524/20120524204040.jpg" alt="f:id:tukasa1919:20120524204040j:image" title="f:id:tukasa1919:20120524204040j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>AAList内のファイル名をリスト化</h4> <p>前回から、MyTxtFrmクラスの初期化メソッドのところに数行追加してます。</p> <ul> <li>AAlist04.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx,os <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) aa_list = os.listdir(<span class="synConstant">&quot;AAList&quot;</span>) self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">def</span> <span class="synIdentifier">OnKeyChar</span>(self,event): key = event.GetKeyCode() <span class="synStatement">if</span> key == wx.WXK_ESCAPE: wx.Exit() <span class="synStatement">elif</span> key == wx.WXK_UP: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() - <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &gt;= <span class="synConstant">0</span>: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(count - <span class="synConstant">1</span>) <span class="synStatement">elif</span> key == wx.WXK_DOWN: count = self.LBox.GetCount() <span class="synIdentifier">next</span> = self.LBox.GetSelection() + <span class="synConstant">1</span> <span class="synStatement">if</span> <span class="synIdentifier">next</span> &lt; count: self.LBox.SetSelection(<span class="synIdentifier">next</span>) <span class="synStatement">else</span>: self.LBox.SetSelection(<span class="synConstant">0</span>) <span class="synStatement">else</span>: event.Skip() <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre> <div class="section"> <h5>osモジュールのインポート</h5> <p>まずは一番上をご覧ください。</p> <pre class="code" data-lang="" data-unlink>import wx,os</pre><p>となってますね。フォルダ内のファイルの情報を得るため、osモジュールが必要なのでimportしてます。</p> </div> <div class="section"> <h5>AAList内のファイル名一覧をリスト化</h5> <p>osモジュールには、listdir()という関数があります。これは、特定のフォルダ内にあるファイルをリスト化してくれる関数です。</p> <pre class="code" data-lang="" data-unlink>aa_list = os.listdir(&#34;AAList&#34;)</pre><p>これで、AAListフォルダ内のファイルをリスト化しているわけです。<br /> 中身は、</p> <pre class="code lang-python" data-lang="python" data-unlink> [<span class="synConstant">&quot;つかさ.txt&quot;</span>,<span class="synConstant">&quot;ティッシュやるから元気出せよ.txt&quot;</span>,<span class="synConstant">&quot;うーっす(キック).txt&quot;</span>, <span class="synConstant">&quot;おはようじょ.txt&quot;</span>,<span class="synConstant">&quot;まじで.txt&quot;</span>,<span class="synConstant">&quot;ゆのっち.txt&quot;</span>(以下略)] </pre><p>のようになってます。</p> </div> <div class="section"> <h5>辞書でファイル名とパスを結びつける</h5> <p>ついでこのリストを利用して、ファイル名をキーに。パスを値とした、辞書を作成します。</p> <pre class="code lang-python" data-lang="python" data-unlink> self.AA_Dict = {} <span class="synStatement">for</span> x <span class="synStatement">in</span> aa_list: key = os.path.splitext(x)[<span class="synConstant">0</span>].decode(<span class="synConstant">&quot;shift-jis&quot;</span>) path = os.path.join(<span class="synConstant">&quot;AAlist&quot;</span>,x) self.AA_Dict[key] = path </pre><p>まず空の辞書を作ります。<br /> ついで、リスト内の各要素への操作を、for文を使うことで行ってます。<br /> forのブロックの中で、</p> <ol> <li>keyにファイル名から拡張子を取り除いたものを入れ、デコードする</li> <li>pathにos.path.joinで結合して作ったパスを入れる</li> <li>self.Dict[key] = pathで拡張子を除いたファイル名をキーに。パスを値に</li> </ol><p>このようにして一々辞書にキーと値のペアを追加していき、ファイル名とパスとが一対一対応した辞書を作るわけです。<br /> 中身は</p> <pre class="code lang-python" data-lang="python" data-unlink> {<span class="synConstant">&quot;つかさ&quot;</span>:<span class="synConstant">&quot;AAList\つかさ.txt&quot;</span>, <span class="synConstant">&quot;ティッシュやるから元気出せよ&quot;</span>:<span class="synConstant">&quot;AAList\ティッシュやるから元気出せよ.txt&quot;</span>, <span class="synConstant">&quot;うーっす(キック)&quot;</span>:<span class="synConstant">&quot;AAList\うーっす(キック).txt&quot;</span>(以下略)} </pre><p>のようになってます。</p> </div> </div> <div class="section"> <h4>ListBoxにセット</h4> <pre class="code lang-python" data-lang="python" data-unlink>self.AA_Dict.keys() </pre><p>で、辞書のキーをリストとして取り出すことができます。中身はファイル名の一覧ですね。<br /> これをリストボックスにセットします。</p> <pre class="code lang-python" data-lang="python" data-unlink>self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>, choices = self.AA_Dict.keys()) </pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120525002058" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120525/20120525002058.jpg" alt="f:id:tukasa1919:20120525002058j:image" title="f:id:tukasa1919:20120525002058j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919 wxPythonでAA管理ツールをつくろう!第一回 GUIを作る hatenablog://entry/10257846132626153781 2012-05-21T16:02:07+09:00 2018-09-10T16:09:03+09:00 あいさつ つかさです。 最近AAを多用するので、AA管理ツールを作ろうと思います。 一つのテキストファイルに一つのAA インクリメンタルサーチ、migemoが使える ツールチップ表示で中身を確認できる くらいができたらなと思ってます。既存のツールもあるにはあるのですが、これらをすべて満たすものはなさそうという理由で自作します。今回、これを作成する過程を連載記事にしようと思います。高度なものにはなりようがないのですが、簡単なプログラムを作る人の参考になればと思います。最終的には次のようなのになる予定ですが、まだ未完成。同じようなコンセプトで以前連載したそして途中で投げ出したPythonでコマンド… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 最近AAを多用するので、AA管理ツールを作ろうと思います。</p> <ul> <li>一つのテキストファイルに一つのAA</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/migemo">migemo</a>が使える</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>表示で中身を確認できる</li> </ul><p>くらいができたらなと思ってます。既存のツールもあるにはあるのですが、これらをすべて満たすものはなさそうという理由で自作します。</p><p>今回、これを作成する過程を連載記事にしようと思います。高度なものにはなりようがないのですが、簡単なプログラムを作る人の参考になればと思います。最終的には次のようなのになる予定ですが、まだ未完成。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120521153221" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120521/20120521153221.jpg" alt="f:id:tukasa1919:20120521153221j:image" title="f:id:tukasa1919:20120521153221j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>同じようなコンセプトで以前連載した<del>そして途中で投げ出した</del><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>ランチャを作ろう!シリーズも参考にしてください。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>カテゴリーからたどれます。</p> </div> <div class="section"> <h4>インストール</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/wxPython">wxPython</a>をインストールします。<br /> あと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/wxPython">wxPython</a>のHPからは一緒に<a class="keyword" href="http://d.hatena.ne.jp/keyword/wxPython">wxPython</a> Demo for <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>もダウンロードすると参考になっていいと思います。</p> <ul> <li><a href="http://www.python.jp/Zope/download/pythoncore">PythonJapan</a></li> <li><a href="http://wxpython.org/download.php">wxPython</a></li> <li><a href="http://wxwindowsjp.sourceforge.jp/docs/html/wx/wx26.htm#classref">&#x30A2;&#x30EB;&#x30D5;&#x30A1;&#x30D9;&#x30C3;&#x30C8;&#x9806;&#x30AF;&#x30E9;&#x30B9;&#x30EA;&#x30D5;&#x30A1;&#x30EC;&#x30F3;&#x30B9;</a></li> </ul> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/Gui">Gui</a>を作る</h4> <p>まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>を作ります。</p> <ul> <li>AAlist01.py</li> </ul><pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> wx <span class="synStatement">class</span> <span class="synIdentifier">MyTxtFrm</span>(wx.Frame): <span class="synStatement">def</span> <span class="synIdentifier">__init__</span>(self, parent, <span class="synIdentifier">id</span>): wx.Frame.__init__(self, parent, <span class="synIdentifier">id</span>) self.TxtCtr = wx.TextCtrl(self, -<span class="synConstant">1</span>) self.LBox = wx.ListBox(self, -<span class="synConstant">1</span>) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, <span class="synConstant">0</span>, wx.EXPAND) self.sizer.Add(self.LBox, <span class="synConstant">1</span>, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(<span class="synConstant">1</span>) self.sizer.Fit(self) <span class="synStatement">class</span> <span class="synIdentifier">MyApp</span>(wx.PySimpleApp): <span class="synStatement">def</span> <span class="synIdentifier">OnInit</span>(self): self.TxtFrm = MyTxtFrm(<span class="synIdentifier">None</span>, -<span class="synConstant">1</span>) self.TxtFrm.SetSize( (<span class="synConstant">180</span>, <span class="synConstant">200</span>) ) self.TxtFrm.Show() self.TxtFrm.TxtCtr.SetFocus() <span class="synStatement">return</span> <span class="synConstant">1</span> app = MyApp() app.MainLoop() </pre><p>フレームを作り、そこにコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>を組み込み、Show()で表示する、というのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>ランチャを作ったときと同じです。<br /> 違うのは、Sizerを使っている点です。</p> <pre class="code" data-lang="" data-unlink> self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.TxtCtr, 0, wx.EXPAND) self.sizer.Add(self.LBox, 1, wx.EXPAND) self.SetSizer(self.sizer) self.SetAutoLayout(1) self.sizer.Fit(self)</pre> <ol> <li>wx.BoxSizerの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を作り</li> <li>そこにAddで必要なコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>を追加していき</li> <li>セットする</li> </ol><p>という順序です。<br /> こうすると、一つのウィンドウ内に複数のコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>(今回はTextCtrlとListBox)を入れるときに、大きさだとかを勝手に調整してくれます。</p><p>そしてできあがったのがこちら。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120521153220" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120521/20120521153220.jpg" alt="f:id:tukasa1919:20120521153220j:image" title="f:id:tukasa1919:20120521153220j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>どっかで見たような<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gui">Gui</a>ができあがりましたね^^<br /> 次回は、実際にリストを入れてそれを選択できるようにします。</p> </div> tukasa1919 PPcとPPvのIDを一対一対応させる hatenablog://entry/10257846132626153796 2012-05-03T16:58:41+09:00 2018-09-10T16:09:05+09:00 あいさつ 僕は、PPvでカーソル上下でPPcのカーソルを動かし、そのファイルを閲覧できるようにしている。PPvのファイル切り替えをカーソル上下左右でとかPPvのカスタマイズを参照。 ただ、これだと複数のPPcを開いたときに、たまに思った通りの挙動をしないことがある。たとえば、 PPc[A]でメモフォルダに移動しPPvを起動、閲覧する 思いついたことがあったので、PPc[B]で別のドキュメントフォルダを開き、そこのファイルをエディタで開いて何か書く じゃあまたメモの閲覧の続きをしようか、とPPvに戻りカーソルを上下すると、今度はPPc[B]に連動してドキュメントフォルダ内のファイルを閲覧してしま… <div class="section"> <h4>あいさつ</h4> <p>僕は、PPvでカーソル上下で<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>のカーソルを動かし、そのファイルを閲覧できるようにしている。<a href="http://d.hatena.ne.jp/tukasa1919/20120317/1332007636">PPv&#x306E;&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x5207;&#x308A;&#x66FF;&#x3048;&#x3092;&#x30AB;&#x30FC;&#x30BD;&#x30EB;&#x4E0A;&#x4E0B;&#x5DE6;&#x53F3;&#x3067;</a>とか<a href="http://d.hatena.ne.jp/tukasa1919/20110112/1294853901">PPv&#x306E;&#x30AB;&#x30B9;&#x30BF;&#x30DE;&#x30A4;&#x30BA;</a>を参照。<br /> ただ、これだと複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>を開いたときに、たまに思った通りの挙動をしないことがある。たとえば、</p> <ol> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>[A]でメモフォルダに移動しPPvを起動、閲覧する</li> <li>思いついたことがあったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>[B]で別のドキュメントフォルダを開き、そこのファイルをエディタで開いて何か書く</li> <li>じゃあまたメモの閲覧の続きをしようか、とPPvに戻りカーソルを上下すると、今度は<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>[B]に連動してドキュメントフォルダ内のファイルを閲覧してしまう</li> </ol><p>という具合だ。どの<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>がアクティブになったかで、挙動が変わってしまうわけですね。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120503165355" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120503/20120503165355.jpg" alt="f:id:tukasa1919:20120503165355j:image:w500" title="f:id:tukasa1919:20120503165355j:image:w500" class="hatena-fotolife" style="width:500px" itemprop="image"></a></span></p><p>これを解決するため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>とPPvのIDを一対一対応させて、カーソル上下の連動をIDに対応させようと思った。</p> </div> <div class="section"> <h4>拡張子別判別実行の挙動</h4> <p>まずは拡張子別判別実行から。</p> <pre class="code" data-lang="" data-unlink>E_cr = { ; [Enter]用判別 TXT ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD HOWM ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD JPEG ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD :JPEG ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD BMP ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD PNG ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD JPG ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD GIF ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD CFG ,%0\PPVW.EXE -bootid:%*regexp(%n,&#34;/.(.)/$1/&#34;) %FCD }</pre><p>これで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>のIDに対応したPPvが起動するようにする。</p> </div> <div class="section"> <h4>PPvの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AD%A1%BC%A5%D0%A5%A4%A5%F3%A5%C9">キーバインド</a></h4> <p>ついで、PPvの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AD%A1%BC%A5%D0%A5%A4%A5%F3%A5%C9">キーバインド</a>をカスタマイズ。カーソル上下で連動する<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>をIDに対応させる。</p> <pre class="code" data-lang="" data-unlink>KV_main = { ; PPvメイン窓 UP ,%KC%*regexp(%n,&#34;/.(.)/$1/&#34;) &#34;@UP V&#34; DOWN ,%KC%*regexp(%n,&#34;/.(.)/$1/&#34;) &#34;@DOWN V&#34; LEFT ,*execute C%*regexp(%n,&#34;/.(.)/$1/&#34;),*cursor 6, -1 %: %KC%*regexp(%n,&#34;/.(.)/$1/&#34;)&#34;V&#34; RIGHT ,*execute C%*regexp(%n,&#34;/.(.)/$1/&#34;),*cursor 6, 1 %: %KC%*regexp(%n,&#34;/.(.)/$1/&#34;)&#34;V&#34; }</pre><p>これで、PPvのIDに対応した<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>でカーソル移動するようになる。</p> </div> tukasa1919 ウィンドウの位置を下にずらすスクリプト hatenablog://entry/10257846132626153805 2012-04-26T08:39:53+09:00 2018-09-10T16:09:06+09:00 僕は、タスクバーを上に表示している。ウィンドウのボタンだとかメニューバーが上にあるので、このほうがマウスを移動する量が減り、都合がいいのだ。ただ、時たま起動するとこのタスクバーにかぶるソフトがある。今まではそのたびごとに、タスクバーの位置を左か下に一度ずらし、そのソフトを下の方にずらし、またタスクバーを上に戻す、ということをしていた。いい加減面倒なので、これをAHKを使って解決する。WinMove.ahk数行で書けるのがAHKのすばらしいところ。これは、アクティブなウィンドウを指定位置に移動するスクリプトです。これをfenrirのインスタントコマンドに登録。 win/="D:\data\AHK… <p>僕は、タスクバーを上に表示している。ウィンドウのボタンだとかメニューバーが上にあるので、このほうがマウスを移動する量が減り、都合がいいのだ。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120426082738" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120426/20120426082738.jpg" alt="f:id:tukasa1919:20120426082738j:image:w500" title="f:id:tukasa1919:20120426082738j:image:w500" class="hatena-fotolife" style="width:500px" itemprop="image"></a></span></p><p>ただ、時たま起動するとこのタスクバーにかぶるソフトがある。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120426082739" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120426/20120426082739.jpg" alt="f:id:tukasa1919:20120426082739j:image:w500" title="f:id:tukasa1919:20120426082739j:image:w500" class="hatena-fotolife" style="width:500px" itemprop="image"></a></span></p><p>今まではそのたびごとに、タスクバーの位置を左か下に一度ずらし、そのソフトを下の方にずらし、またタスクバーを上に戻す、ということをしていた。いい加減面倒なので、これを<a class="keyword" href="http://d.hatena.ne.jp/keyword/AHK">AHK</a>を使って解決する。</p><p><span class="deco" style="font-weight:bold;">WinMove.<a class="keyword" href="http://d.hatena.ne.jp/keyword/ahk">ahk</a></span></p><p><script src="https://gist.github.com/2494444.js?file=WinMove.ahk"></script></p><p>数行で書けるのが<a class="keyword" href="http://d.hatena.ne.jp/keyword/AHK">AHK</a>のすばらしいところ。これは、アクティブなウィンドウを指定位置に移動する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>です。</p><p>これをfenrirのインスタントコマンドに登録。</p> <pre class="code" data-lang="" data-unlink>win/=&#34;D:\data\AHKScript\WinMove.ahk&#34;</pre> tukasa1919 CatMemoNoteを使ってみる hatenablog://entry/10257846132626153815 2012-04-25T08:19:40+09:00 2018-09-10T16:09:08+09:00 あいさつ つかさです。 CatMemoNoteを使っているので、それの設定メモ。これは、Light Writeと同系列の、「保存を前提としない一時的なメモ」をとるためのソフトです。最初にインストールしたときはインターフェースのかわいさからあまり期待してなかったが、メモソフトとしては非常に硬派というか相当高機能。Light Writeを使っていてこういうのができたらな、と思ってたの(メモの削除時に確認しない設定だとか)がすべてできる。この種のソフトとしてはおそらく決定版になると思います。また、階層構造を作れ、縦書きにすることもできる。外部ツールの登録もできる。使いこなそうとすれば、相当いろんなこ… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> <a href="http://www.cc9.ne.jp/~pappara/catmemonote.html">CatMemoNote</a>を使っているので、それの設定メモ。これは、Light Writeと同系列の、「保存を前提としない一時的なメモ」をとるためのソフトです。</p><p>最初にインストールしたときはインターフェースのかわいさからあまり期待してなかったが、メモソフトとしては非常に硬派というか相当高機能。Light Writeを使っていてこういうのができたらな、と思ってたの(メモの削除時に確認しない設定だとか)がすべてできる。この種のソフトとしてはおそらく決定版になると思います。</p><p>また、階層構造を作れ、縦書きにすることもできる。外部ツールの登録もできる。使いこなそうとすれば、相当いろんなことができそうです。</p> <ul> <li>デフォルト</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075641" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075641.jpg" alt="f:id:tukasa1919:20120425075641j:image" title="f:id:tukasa1919:20120425075641j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>僕が使っているテーマ</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425081631" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425081631.jpg" alt="f:id:tukasa1919:20120425081631j:image" title="f:id:tukasa1919:20120425081631j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>オプションの設定</h4> <p>Ctrl+Oを押すことで、オプション画面が表示されます。</p> <div class="section"> <h5>ウィンドウ</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075642" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075642.jpg" alt="f:id:tukasa1919:20120425075642j:image" title="f:id:tukasa1919:20120425075642j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>起動時のウィンドウ−<a class="keyword" href="http://d.hatena.ne.jp/keyword/IME">IME</a>の日本語入力をONにする にチェック</li> </ul> </div> <div class="section"> <h5>操作</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075646" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075646.jpg" alt="f:id:tukasa1919:20120425075646j:image" title="f:id:tukasa1919:20120425075646j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075643" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075643.jpg" alt="f:id:tukasa1919:20120425075643j:image" title="f:id:tukasa1919:20120425075643j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>ホットキー−ウィンドウ表示切り替え Win+Z</li> <li>ショートカットキー−終了 Ctrl+Wに</li> </ul> </div> <div class="section"> <h5>テーマ</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075644" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075644.jpg" alt="f:id:tukasa1919:20120425075644j:image" title="f:id:tukasa1919:20120425075644j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>現在のテーマ−僕はHigh contrast Blackにしている</li> <li>壁紙で背景なし にチェック</li> </ul> </div> <div class="section"> <h5>その他</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120425075647" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120425/20120425075647.jpg" alt="f:id:tukasa1919:20120425075647j:image" title="f:id:tukasa1919:20120425075647j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>メモを削除するときに確認する のチェックをはずす</li> </ul> </div> </div> <div class="section"> <h4>system.ini</h4> <p>次は、CatMemoNoteフォルダ内にあるsystem.iniで細かい設定を変更。</p><p>DefaultWrapMode=2</p><p>で、ウィンドウ幅で折り返すようにする。</p> </div> <div class="section"> <h4>よく使いそうなショートカットキー</h4> <p>後は普通に使うだけですね。僕がよく使うショートカットキーをメモっておきます。</p> <ul> <li>一行目をファイル名に Ctrl+L</li> <li>新しいメモ Ctrl+N</li> <li>最前面のトグル Ctrl+T</li> <li>前のメモ、次のメモ Ctrl+↑↓</li> </ul> </div> tukasa1919 漸次的にまとめるプロセスを分離したい hatenablog://entry/10257846132626153830 2012-04-21T07:55:26+09:00 2018-09-10T16:09:10+09:00 漸次的にアイデアをまとめる方法論 個々のアイデアメモを、一つの成果にまとめる方法をずっと考えている。 これを、僕はPC上でやろうと思っていたができなかった。今までやってきたのは、Memo on the Electron #4 - 再生産するで述べていたように アイデアメモをつぎはぎして プリントアウトしたものを洗練し 元のデータに修正点をインプットする というものだが、そもそもそれへのとっかかりが面倒ということ、また何を基準にしてまとめるかが難しいということなどからあまりできていなかった。 カテゴリーフォルダの限界 僕が思ったのは、これは、カテゴリーフォルダ内でまとめようとすることの限界ではな… <div class="section"> <h4>漸次的にア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>をまとめる方法論</h4> <p>個々のア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモを、一つの成果にまとめる方法をずっと考えている。<br /> これを、僕はPC上でやろうと思っていたができなかった。今までやってきたのは、<a href="http://d.hatena.ne.jp/tukasa1919/20100727/1280205698">Memo on the Electron #4 - &#x518D;&#x751F;&#x7523;&#x3059;&#x308B;</a>で述べていたように</p> <ol> <li>ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモをつぎはぎして</li> <li>プリントアウトしたものを洗練し</li> <li>元のデータに修正点をインプットする</li> </ol><p>というものだが、そもそもそれへのとっかかりが面倒ということ、また何を基準にしてまとめるかが難しいということなどからあまりできていなかった。</p> </div> <div class="section"> <h4>カテゴリーフォルダの限界</h4> <p>僕が思ったのは、これは、カテゴリーフォルダ内でまとめようとすることの限界ではないかということ。</p><p>カテゴリーフォルダは、基本的に、完結したメモがどんどんとたまっていく仕組みになっている。不完全なものや思考途中のメモというのは、後では意味の分からないノイズにしかならないので、そのような性質である必要があるのだ。</p><p>だから、ここにおいて操作を行い、メモをくっつけたり、削除したり改変したりという、一つにまとめる過程を行おうとしても、どうしてもこの限界に規定されてしまう。どのようにしようと、ここにおいては完全な、完結したメモしか作ることはできないのだ。従って、一つにまとめるために、思いついたことをメモしたり、全体像について書いたり、試作的に書いたり、個々のメモについてメタ的なことを書いたりということをすることができない。物理的にできないことはないが、それをすると、本来のカテゴリーフォルダの機能と矛盾してしまうのである。</p><p>今までは、一つのまとまった文書を一気に作り、それを修正するというパターンでやっていた。だが、これはそれが理想というよりも、それ以外のやり方ができなかったという消極的な理由だったのではないかと思っている。実際この過程はかなり労力がかかり、一つのまとまったものを作り出すまでが長く、未処理のア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモがずっと残っているということが多かった。まとめる作業、というのをきちんと対象化しておらず、無理に乗り切ってきたのではないかと思っている。</p> </div> <div class="section"> <h4>カテゴリーフォルダの外へ</h4> <p>そこで、この「漸次的にまとめる」というプロセスを分離しようと思う。</p><p>ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモを見ながら、思いついたことをメモったり、試しに何か書いてみたり、思いついた構成をメモったり、複数のメモを見比べたり、という作業をカテゴリーフォルダとは別の場所で行いたい。そして、そこで色々とごちゃごちゃとやってから、その成果をカテゴリーフォルダなりDocumentフォルダなりの、まとまったところに作製する、というようにしたい。</p><p>それで、どこでやるかだが僕が大まかに思いついたのは二つだった。一つが、別の場所に作業用のフォルダを作り、そこにおいて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%AD%A5%B9%A5%C8%A5%A8%A5%C7%A5%A3%A5%BF">テキストエディタ</a>なり<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>なりを用いての作業。もう一つが、まとめるためのソフトウェアを導入すること。</p> </div> <div class="section"> <h4>案その1−PPxとWorkフォルダ</h4> <p>まずやるべきなのは、作業用のフォルダを作るということ。これについては、Workフォルダ内にでも作ればいいということになる。フォルダ名だとか、サブフォルダを作るだとか死蔵を防ぐ工夫だとか色々考えることはあるだろうが、とりあえずは問題ない。この中で、テキストファイルを複数作り、それを編集することで、考えをまとめる、という形になる。</p><p>一つ、あるいは複数のテキストファイル内に、色々ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>を書いて、消して、比較してという過程を繰り返すことで、徐々に一つのまとまったものにしていくというイメージです。</p><p>というわけで、ここでは今までとテキストファイルの扱いが異なってくる。ここに書くのは一時的なメモで、かつ編集が何度も行われ、削除も容易で、複数のウィンドウが同時に閲覧できる、といったこれまでカテゴリーフォルダでの操作では不要だったことが必要になる。</p> <ul> <li>複数のビューアが同時起動</li> <li>編集が容易</li> <li>削除も容易</li> </ul><p>他方、これまで必須だったことで、不要になることもある。</p> <ul> <li>ファイル単位での保存</li> <li>バックアップ</li> <li>それ単体で完結している必要はない。前提とかとっぱらっていい。分かればいい。</li> </ul><p>あたりでしょうか。</p><p>というわけで、これらのことをPPxでできるようにする必要がある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を利用したり、フォルダごとのカスタマイズをしたりして、この用途に最適化する必要があるわけです。</p><p>具体的には、次のようになるでしょう。<br /> howm2を開きながら、同時にこのメモフォルダなりメモソフトなりを起動して、作業していく。そして、適宜必要な処理をそれぞれに施していく。<br /> そして、ある程度まとまったら、再びカテゴリーフォルダに移すなり、Docフォルダに移すなりする。そして、それを作る過程でできた落書き類はすべて処分する。記録として、残さない。メモがずっと残って、それを元にして後で何かを考察してしまいそうな要素はできるだけ取り除いておきたい。</p> </div> <div class="section"> <h4>案その2−メモソフトの導入</h4> <p>ほかに、メモソフトを使うというのもあり得る。<br /> カテゴリーフォルダ内のメモを見ながら、ここに色々とア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>を書いていき、それをまとめる、ということも可能だと思う。この場合は、一々Workフォルダを作って、PPxで処理して、という手間が無くなるわけです。カテゴリーフォルダでやっているように、メモを後々まで残して利用する、ということをするわけではないから、この過程においてファイラを使って処理する必然性は無いかもしれない。そういった意味でこっちのほうがスマートな気がします。</p><p>この用途として思いつくのはLight Write、TextTree、CatMemoNote、CraftMemoあたり。あとはアウトプットエディタとかでしょうか。最近はあまり試したこと無かったので、一度試してみようとおもう。少し試してみた限りだと、CatMemoNoteがよさげだった。</p><p>案その1よりは、こっちのほうが見込みありそうかな、と思っています。</p> </div> tukasa1919 アイデアメモの使い方とポメラと hatenablog://entry/10257846132626153842 2012-03-19T12:23:34+09:00 2018-09-10T16:09:11+09:00 一度草稿をつくる 草稿を修正する この二つの過程を分離し、それぞれでアイデアメモを別に作り、利用するべきだと思う。 草稿を作る過程 発想段階のアイデアは後で再利用できない その時々で出るアイデアというのは、問題がはっきりと対象化されていない、もやもやしていることについて、脈絡なくでるものである。そのたびに思いついた解決方針だとか、その原因がこれではないかというのが、ランダムに生じており、それをメモにしている。 だから、その中には、結局は使えないものが多数混ざっているのである。実は頭の中に無意識に論理構造を含めてできあがっている論文が、章単位でアイデアという形で出てくるというわけではない。だから… <ol> <li>一度草稿をつくる</li> <li>草稿を修正する</li> </ol><p>この二つの過程を分離し、それぞれでア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモを別に作り、利用するべきだと思う。</p> <div class="section"> <h4>草稿を作る過程</h4> <div class="section"> <h5>発想段階のア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>は後で再利用できない</h5> <p>その時々で出るア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>というのは、問題がはっきりと対象化されていない、もやもやしていることについて、脈絡なくでるものである。そのたびに思いついた解決方針だとか、その原因がこれではないかというのが、ランダムに生じており、それをメモにしている。<br /> だから、その中には、結局は使えないものが多数混ざっているのである。実は頭の中に無意識に論理構造を含めてできあがっている論文が、章単位でア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>という形で出てくるというわけではない。だから、その思いつきを並びかえたら論文になる、というわけでもない。<br /> このア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>メモは、このなかから自分が考察したいことの核心的をつかむだとか、同じような問題意識のものをまとめるだとかで、論文の方向性を決めたり、自分の今ある問題意識をはっきりさせたりする点においては役に立つ。けれど、一度草稿を作ってしまったら、そこに残ったメモはただ曖昧で使えないものになってしまう。</p><p>だから、ある程度メモがたまったら、それをもとに草稿を作ってしまい、あとのメモは捨ててしまうのがいい。</p> </div> <div class="section"> <h5>記録に関するメモは別</h5> <p>ただ、誰かと話した記録といったためておくだけで有用になるメモは、別にしておく。僕は記録フォルダというのを作ってそこに保存するようにしている。</p> </div> <div class="section"> <h5>草稿の作り方</h5> <p>簡単な内容のものだったら、このメモから一気に作ってしまう。ソフトウェアだとかMoE関連だとかいうのはそうで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイルをエディタで開き、少し編集したらそのままブログにのっけるというようにしている。だが、理論的な込み入った領域になると難しい。<br /> そのときには、メモの中から、核心的なのをひとつプリントアウトし、それへ書き足すという形で行ったり、あるいはそれとは無関係に、一気に思いつくことを計算用紙に書き出し、それをたたき台にするということが多い。よく考えたら、あまりメモを有効活用していないかもな。</p> </div> </div> <div class="section"> <h4>草稿を修正する過程</h4> <p>そこに書き足しをしたり、修正をしたり、構成を適宜入れ替えたりして、どんどん大きくしていくということをする。</p> <div class="section"> <h5>草稿とツール</h5> <p>使っているのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>。三つの段階をたどる。</p> <ol> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>(章単位で分割)</li> </ol><p>まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>形式で作る。いきなり<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>でかっちりつくっても、後でやめてしまい、そのデータの処理に困ることがあるからだ。ここである程度の長さのを作ってしまい、見通しがたったら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>形式に変換するということをしている。</p><p>最初は<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>形式でも一つのファイルで作るが、ある程度内容がふくれてきたら、章単位で分割するようにしている。</p><p>修正の仕方は、基本的にはどれも同じ。プリントアウトして、それを読み、書き足し、後でその修正個所を元ファイルに付け足すという仕方でやっている。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120319121832" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120319/20120319121832.jpg" alt="f:id:tukasa1919:20120319121832j:image" title="f:id:tukasa1919:20120319121832j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h5>実際のやり方</h5> <p>喫<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%E3%C5%B9">茶店</a>とかに行って、プリントアウトしたものを最後まで読んでみる。その途中で思いついたことがあったら、それを余白に書き込む。それが長くなりそうなら、計算用紙に書き込む。そのあとで、その計算用紙を元にして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>で文章を打ち込んでいく。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>で保存するときのファイル名は、章番号(5.1.txt)とか章タイトル(ほげほげ.txt)に対応させると分かりやすい。</p> <ul> <li>打ち込み終わった計算用紙は二つに折って後で捨てる</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120319125531" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120319/20120319125531.jpg" alt="f:id:tukasa1919:20120319125531j:image" title="f:id:tukasa1919:20120319125531j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>また、一読して意味が取りにくい章があれば、修正ではなくその章だけ書き直すということをする。その箇所を読んで、そこに書いてあることを要素に分解して、計算用紙上に書き出す。他にも思いつくことがあればそれも書き出す。そして、次にそれを元に、新しく<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>で打ち込み、文章の形にする。</p><p>そして、家に帰ってきたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>で打ち込んだ箇所を元のファイルに反映させる。また、誤字の訂正もここで行う。</p> </div> <div class="section"> <h5>ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a></h5> <p>また、書いている途中で、どこに挿入したらいいかわからないア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>が出てくることもある。その場合は、とりあえず本文には挿入せず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイル形式で保存するというようにする。僕の場合は、カテゴリーフォルダ内に、その書いている論文に対応させたフォルダを新しく作り、そこに放り込むというようにしている。ここには、本文に即していないから削ったけれども、また使うかもしれないというデータも一緒にためている。</p> </div> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>の使い方</h4> <div class="section"> <h5>ファイル処理</h5> <p>ビューアから<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイルにコピペするという原始的なやり方をしている。<br /> 一行目をタイトルにしておくと、コピペするだけで<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>のタイトルになるので楽。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120319115054" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120319/20120319115054.jpg" alt="f:id:tukasa1919:20120319115054j:image" title="f:id:tukasa1919:20120319115054j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>こうして取り出した後の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E1%A5%E9">ポメラ</a>のテキストファイルは、一応今は保存するようにしている。Workフォルダにそれ用のフォルダを作り、そこに移動。そのうちやめるかもしれない。今のところここにおいたファイルを活用したりはしていない。</p> </div> </div> tukasa1919 ファイルの内容をクリップボードにコピー hatenablog://entry/10257846132626153864 2012-03-18T07:55:52+09:00 2018-09-10T16:09:14+09:00 あいさつ PPxでカーソル下のファイルの内容をクリップボードにコピー、あるいは追加コピーする方法。howmファイルで関係するのをまとめてコピーし、印刷できたら便利かもしれないと思って作ったが、結局使わないような気がしなくもない。 AutoHotKey AutoHotKeyを使います。コピー用と追加コピー用の二つのスクリプトを用意。 ClipFile.ahk ClipFileAdd.ahk PPxに登録 ファイルパスをコピーするメニューと一緒にしてみた。僕はこのメニューをShift+Nで起動するようにしている。以下を編集して取り込み。 M_ClipPath = { ** comment ** &… <div class="section"> <h4>あいさつ</h4> <p>PPxでカーソル下のファイルの内容を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>にコピー、あるいは追加コピーする方法。<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイルで関係するのをまとめてコピーし、印刷できたら便利かもしれないと思って作ったが、結局使わないような気がしなくもない。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/AutoHotKey">AutoHotKey</a></h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AutoHotKey">AutoHotKey</a>を使います。コピー用と追加コピー用の二つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を用意。</p> <div class="section"> <h5>ClipFile.<a class="keyword" href="http://d.hatena.ne.jp/keyword/ahk">ahk</a></h5> <p><script src="https://gist.github.com/2065829.js"> </script><br /> </p> </div> <div class="section"> <h5>ClipFileAdd.<a class="keyword" href="http://d.hatena.ne.jp/keyword/ahk">ahk</a></h5> <p><script src="https://gist.github.com/2065832.js"> </script><br /> </p> </div> </div> <div class="section"> <h4>PPxに登録</h4> <p>ファイルパスをコピーするメニューと一緒にしてみた。僕はこのメニューをShift+Nで起動するようにしている。以下を編集して取り込み。</p> <pre class="code" data-lang="" data-unlink>M_ClipPath = { ** comment ** &amp;CopyFileName = *cliptext %R Copy&amp;DirName = *cliptext %1 Copy&amp;FileName(拡張子無し) = *cliptext %Y CopyFilePath = *cliptext %FCD ファイルの内容をクリップボードにコピー = %Ob D:\data\AHKScript\ClipFile.ahk %FCD ファイルの内容をクリップボードに追加コピー = %Ob D:\data\AHKScript\ClipFileAdd.ahk %FCD } KC_main = { ; PPcメイン窓 \N ,%M_ClipPath,C }</pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120318075522" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120318/20120318075522.jpg" alt="f:id:tukasa1919:20120318075522j:image" title="f:id:tukasa1919:20120318075522j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919 PPvのファイル切り替えをカーソル上下左右で hatenablog://entry/10257846132626153880 2012-03-17T03:07:16+09:00 2018-09-10T16:09:15+09:00 PPvでは、カーソル上下でPPcのカーソルを動かし、そのファイルを閲覧できるようにしている。PPvのカスタマイズ参照。あふみたいな挙動にしてるわけです。このカーソル移動を、左右でもやれるのではないかと思いついた。 KV_main = { ; PPvメイン窓 LEFT ,*execute C,*cursor 6, -1 %: %KC"V" RIGHT ,*execute C,*cursor 6, 1 %: %KC"V" UP ,%KC"@UP V" DOWN ,%KC"@DOWN V" } KC_main = { ; PPcメイン窓 V ,%ME_View } E_view = { ** com… <p>PPvでは、カーソル上下で<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>のカーソルを動かし、そのファイルを閲覧できるようにしている。<a href="http://d.hatena.ne.jp/tukasa1919/20110112/1294853901">PPv&#x306E;&#x30AB;&#x30B9;&#x30BF;&#x30DE;&#x30A4;&#x30BA;</a>参照。あふみたいな挙動にしてるわけです。</p><p>このカーソル移動を、左右でもやれるのではないかと思いついた。</p> <pre class="code" data-lang="" data-unlink>KV_main = { ; PPvメイン窓 LEFT ,*execute C,*cursor 6, -1 %: %KC&#34;V&#34; RIGHT ,*execute C,*cursor 6, 1 %: %KC&#34;V&#34; UP ,%KC&#34;@UP V&#34; DOWN ,%KC&#34;@DOWN V&#34; } KC_main = { ; PPcメイン窓 V ,%ME_View } E_view = { ** comment ** JPG = @N TXT = @N PDF ,*set name=%*extract(C&#34;%%FCD&#34;) %: *script %0\Script\PDFView.vbs, &#34;%&#39;name&#39;&#34; * = @N }</pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120318030542" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120318/20120318030542.jpg" alt="f:id:tukasa1919:20120318030542j:image" title="f:id:tukasa1919:20120318030542j:image" class="hatena-fotolife" itemprop="image"></a></span></p> tukasa1919 行き詰まった時にありがちなパターン hatenablog://entry/10257846132626153896 2012-03-15T08:12:29+09:00 2018-09-10T16:09:17+09:00 よく行き詰まる 論文とかを書いていると、途中で行き詰まることがある。難しくて、それを考察していても、答えが出そうにない状態である。 このような場合というのは、ただ、必要でもないのに、惰性でひとつのことを当初の目的を忘れて何かを闇雲にやっているということが多い。だから、一度自分が今していることを外から眺めなおすと、解決することが多い。やっていることをテキストファイルにでも書き出し、手段とかそういうのを練り直した上でやり直すといい。いまやっている考察がどういう意味を持っていて、実際に必要なものなのかどうか。そしてその手段としてどのようなことを今とっており、いまどこで行き詰まっているのか。そうすれば… <div class="section"> <h4>よく行き詰まる</h4> <p>論文とかを書いていると、途中で行き詰まることがある。難しくて、それを考察していても、答えが出そうにない状態である。<br /> このような場合というのは、ただ、必要でもないのに、惰性でひとつのことを当初の目的を忘れて何かを闇雲にやっているということが多い。だから、一度自分が今していることを外から眺めなおすと、解決することが多い。やっていることをテキストファイルにでも書き出し、手段とかそういうのを練り直した上でやり直すといい。いまやっている考察がどういう意味を持っていて、実際に必要なものなのかどうか。そしてその手段としてどのようなことを今とっており、いまどこで行き詰まっているのか。そうすれば、一度その手段を変えてみようとなったりするのだ。そして、それでうまくいかなければ別の手段をやるなりするということになる。</p> </div> <div class="section"> <h4>投げ出す</h4> <p>このことを知ってはいるのだが、たいていはそのようにすることができない。ずっと没頭、突っ走るということをよくしている。<br /> そうするとどうなるかというと、途中で行き詰まり、気持ちが切れてしまう。一気にいろいろなことがイヤになり、やる気がなくなり、すべてを投げ出してしまう。僕の場合は生活リズムが崩れて何かネットとかをずっとやりつづけてということになる。そうすると、それまでやってた学習の蓄積も一気になくなってしまう。最悪である。</p> </div> <div class="section"> <h4>立ち直り方</h4> <p>ここから立ち直るには、何か別の集中できることをするのがいい。おもしろい本を読むというようにするといい。僕の場合は、漫画だとか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%CE%A5%D9">ラノベ</a>とかである。最近は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%CE%A5%D9">ラノベ</a>が多い。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%BE%C8%F8%B0%DD%BF%B7">西尾維新</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BD%CA%AA%B8%EC">化物語</a>を途中までしか読んでいないので、それを買って読むようにしている。<br /> 暇つぶしとして、将棋とかネットとかの、すぐに手元にあって惰性である程度の刺激があってというのは、何か向かってしまいがちなのだが、不適切だと思う。休んでいるようで、頭はずっとヒートアップしたままで休まらない。そういうのをずっと一週間くらいして、ああ、無駄なことをしているとよく感じる。</p> </div> <div class="section"> <h4>そのうち解決したい</h4> <p>何でこんなことを書いているかというと、このようなことをそのたびに思っては同じ失敗を繰り返しているからなんですね。というわけで、対象化するためにブログに書いてみる。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%CE%A5%D9">ラノベ</a>とか読むのはいいけど、金かかるのがネックになってるんだろうな。そこから考え直してみるか。働きたくねえ</p> </div> tukasa1919 PPxでPDFを閲覧する(改) hatenablog://entry/10257846132626153910 2012-03-10T10:12:14+09:00 2018-09-10T16:09:18+09:00 あいさつ つかさです。 前回に続き、PDFをPPxで閲覧する方法です。やりたいのは、カーソル上下での表示切り替えです。 PDFView.vbsも少し変更したので、最初から説明します。 必要な環境 GhostScriptのインストールが必要です。 スクリプト 以下の三つのスクリプト PDFView.vbs PPvUp.vbs PPvDown.vbs をScriptフォルダに保存します。 PDFView.vbsは前回から、引数に従って表示するように変更しています。 PPVUpはカーソル↑用の。PPVDownはカーソル↓用のスクリプトです。カーソルを一つ動かした後に、ファイル判別実行E_viewをし… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 前回に続き、PDFをPPxで閲覧する方法です。やりたいのは、カーソル上下での表示切り替えです。<br /> PDFView.vbsも少し変更したので、最初から説明します。</p> </div> <div class="section"> <h4>必要な環境</h4> <p>GhostScriptのインストールが必要です。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></h4> <p>以下の三つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a></p> <ul> <li>PDFView.vbs</li> <li>PPvUp.vbs</li> <li>PPvDown.vbs</li> </ul><p>をScriptフォルダに保存します。<br /> PDFView.vbsは前回から、引数に従って表示するように変更しています。<br /> PPVUpはカーソル↑用の。PPVDownはカーソル↓用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>です。カーソルを一つ動かした後に、ファイル判別実行E_viewをしています。</p> <div class="section"> <h5>PDFView.vbs</h5> <p><script src="https://gist.github.com/2009140.js"> </script><br /> </p> </div> <div class="section"> <h5>PPVUp.vbs</h5> <p><script src="https://gist.github.com/2009145.js"> </script><br /> </p> </div> <div class="section"> <h5>PPVDown.vbs</h5> <p><script src="https://gist.github.com/2009148.js"> </script><br /> </p> </div> </div> <div class="section"> <h4>カスタマイザー</h4> <p>以下を編集して取り込み。</p> <pre class="code" data-lang="" data-unlink>E_cr = { ; [Enter]用判別 :PDF ,*script %0\Script\PDFView.vbs, %FCD } E_view = { ** comment ** .TXT;.INI;.HOWM ,*set name=%*extract(C&#34;%%FCD&#34;) %: %0\PPVW.EXE -r %&#39;name&#39; .BMP;.JPG;.PNG;.JPEG ,*set name=%*extract(C&#34;%%FCD&#34;) %: %0\PPVW.EXE -r %&#39;name&#39; PDF ,*set name=%*extract(C&#34;%%FCD&#34;) %: *script %0\Script\PDFView.vbs, %&#39;name&#39; * ,*set name=%*extract(C&#34;%%FCD&#34;) %: %0\PPVW.EXE -r %&#39;name&#39; } KV_main = { ; PPvメイン窓 UP ,*script %0\Script\PPvUp.vbs DOWN ,*script %0\Script\PPvDown.vbs }</pre> </div> <div class="section"> <h4>使い方</h4> <ul> <li>PDFファイルにカーソルをあわせ、Enterを押すと一枚目の画像が表示される</li> <li>カーソル上下で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPc">PPc</a>の上下にあるファイルが閲覧できる</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120310100348" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120310/20120310100348.jpg" alt="f:id:tukasa1919:20120310100348j:image" title="f:id:tukasa1919:20120310100348j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>あとやりたいこと</h4> <p>これだとたまに表示がもたつくことがあります。もう少しスマートにやる方法もありそう。</p> </div> tukasa1919 PPxでPDFを閲覧する hatenablog://entry/10257846132626153931 2012-03-08T17:57:09+09:00 2018-09-10T16:09:20+09:00 あいさつ つかさです。 今回はPPxでPDFファイルを閲覧する方法です。こんな感じで、PPvにPDFファイルの一枚目を画像表示します。参考にしたのは、お気に入りのツールを気ままに拡張するブログのafxpdf、というかそれを少しいじっただけです。 仕組み ghostscriptでPDFの一枚目を画像に変換し、PPvで表示しているだけです。動作にはghostscriptが必要です。僕はTeXインストーラ 3で他のTeX関係のものと一緒にインストールしました。 インストール 以下をScriptフォルダに保存。'---------------------------------------------… <div class="section"> <h4>あいさつ</h4> <p>つかさです。<br /> 今回はPPxでPDFファイルを閲覧する方法です。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120308173813" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120308/20120308173813.jpg" alt="f:id:tukasa1919:20120308173813j:image:w550" title="f:id:tukasa1919:20120308173813j:image:w550" class="hatena-fotolife" style="width:550px" itemprop="image"></a></span></p><p>こんな感じで、PPvにPDFファイルの一枚目を画像表示します。参考にしたのは、<a href="http://yuratomo.seesaa.net/">&#x304A;&#x6C17;&#x306B;&#x5165;&#x308A;&#x306E;&#x30C4;&#x30FC;&#x30EB;&#x3092;&#x6C17;&#x307E;&#x307E;&#x306B;&#x62E1;&#x5F35;&#x3059;&#x308B;&#x30D6;&#x30ED;&#x30B0;</a>のafxpdf、というかそれを少しいじっただけです。</p> </div> <div class="section"> <h4>仕組み</h4> <p>ghostscriptでPDFの一枚目を画像に変換し、PPvで表示しているだけです。</p><p>動作にはghostscriptが必要です。僕は<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a> 3で他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/TeX">TeX</a>関係のものと一緒にインストールしました。</p> </div> <div class="section"> <h4>インストール</h4> <p>以下をScriptフォルダに保存。</p><p>'------------------------------------------------------------<br /> で囲った部分は各自の環境によって適宜変えて下さい</p> <div class="section"> <h5>pdfview.vbs</h5> <pre class="code" data-lang="" data-unlink>&#39;!*script Set fso = CreateObject(&#34;Scripting.FileSystemObject&#34;) Set ws = CreateObject(&#34;Wscript.Shell&#34;) &#39;------------------------------------------------------------ ghostscript = &#34;C:\gs\gs9.02\bin\gswin32c.exe&#34; resolution = 100 inputfile = PPx.Extract(&#34;%FCD&#34;) outputdir = PPx.Extract(&#34;%0&#34;) &amp; &#34;\PPXTMP.PDF\&#34; outputfile = &#34;%%03d.bmp&#34; outputfile1 = outputdir &amp; &#34;001.bmp&#34; ppv = PPx.Extract(&#34;%0&#34;) &amp; &#34;\PPVW.EXE&#34; &#39;------------------------------------------------------------ &#39; prepare outputdir if Not fso.FolderExists(outputdir) Then call fso.CreateFolder(outputdir) else set fld = fso.GetFolder(outputdir) For Each file In fld.Files if InStr(file.Name, outputprefix) &gt; 0 Then call fso.DeleteFile(outputdir &amp; file.Name, True) end if Next end if &#39; execute gswin32c (pdf2bmp) PPx.Execute (&#34;%Obds &#34; &amp; ghostscript &amp; &#34; -dSAFER -dBATCH -dNOPAUSE -sDEVICE=bmp256 -r&#34; &amp; resolution &amp; &#34; -sOutputFile=&#34; &amp; outputdir &amp; outputfile &amp; &#34; -dFirstPage=1 -dLastPage=1 &#34; &amp; inputfile) PPx.Execute (ppv &amp; &#34; -r &#34; &amp; outputfile1 ) Set fso = Nothing Set ws = Nothing</pre> </div> <div class="section"> <h5>PPx側の設定</h5> <p>ファイル判別で、PDFならこの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>が起動するように登録。以下を編集して取り込み。</p> <pre class="code" data-lang="" data-unlink>E_cr = { ; [Enter]用判別 :PDF ,*script %0\Script\PDFView.vbs }</pre><p>カスタマイザーからなら次のようにする。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120308173814" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120308/20120308173814.jpg" alt="f:id:tukasa1919:20120308173814j:image" title="f:id:tukasa1919:20120308173814j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h5>使うとき</h5> <p>PDFファイルにカーソルをあわせてEnterを押すと、そのPDFの一枚目の画像がPPvで表示される。</p> </div> </div> <div class="section"> <h4>あとやりたいこと</h4> <p>僕は、<a href="http://d.hatena.ne.jp/tukasa1919/20110112/1294853901">PPv&#x306E;&#x30AB;&#x30B9;&#x30BF;&#x30DE;&#x30A4;&#x30BA;</a>で書いたように、PPvではカーソル上下で、同じフォルダ内の別の画像を表示するようにカスタマイズしているので、PDFもこれにあわせたい。次回くらいには、これができるようにしたい。</p> </div> tukasa1919 クリップボード履歴とAA管理にClip.netを使ってみる hatenablog://entry/10257846132626153957 2012-02-15T13:52:49+09:00 2018-09-10T16:09:22+09:00 クリップボードスレを見ていて、Clip.netの存在に気づいた。Everything以来、ひさびさにおもしろいソフトを見つけた気がします。eClipと似たような、というかそれに機能を追加したようなソフト。インクリメンタルサーチができ、かつMigemoも使える。 左がClip.netで、右がeClipです。Readme.txtによると 本ソフトは、クリップボードの履歴を取得し再利用するソフトです。 C#の勉強目的にeClipと同じものを作ってみようという所から始まりました。 設計思想については本家eClipにほぼ合わせています。 その他、Unicode文字列取得可能、ストックモード、定型文機能な… <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215131456" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215131456.jpg" alt="f:id:tukasa1919:20120215131456j:image" title="f:id:tukasa1919:20120215131456j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>スレを見ていて、<a href="http://www.rupan.net/other/software.html">Clip.net</a>の存在に気づいた。Everything以来、ひさびさにおもしろいソフトを見つけた気がします。</p><p><a href="http://hp.vector.co.jp/authors/VA026310/soft2.htm">eClip</a>と似たような、というかそれに機能を追加したようなソフト。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%AF%A5%EA%A5%E1%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%C1">インクリメンタルサーチ</a>ができ、かつ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>も使える。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215072435" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215072435.jpg" alt="f:id:tukasa1919:20120215072435j:image:left" title="f:id:tukasa1919:20120215072435j:image:left" class="hatena-fotolife hatena-image-left" itemprop="image"></a></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215131457" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215131457.jpg" alt="f:id:tukasa1919:20120215131457j:image" title="f:id:tukasa1919:20120215131457j:image" class="hatena-fotolife" itemprop="image"></a></span></p><br /> <p>左がClip.netで、右がeClipです。Readme.txtによると</p> <pre class="code" data-lang="" data-unlink> 本ソフトは、クリップボードの履歴を取得し再利用するソフトです。  C#の勉強目的にeClipと同じものを作ってみようという所から始まりました。  設計思想については本家eClipにほぼ合わせています。  その他、Unicode文字列取得可能、ストックモード、定型文機能など  オリジナルの機能を加えています。</pre><p>とのこと。<br /> 追加されている機能は</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a>対応</li> <li>ストックモード</li> <li>定型文</li> </ul><p>の三つ。</p> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/UNICODE">UNICODE</a></h4> <p>( &#9593;ω&#9593;)つ-----&#9584;&#8899;&#9583;----&#9988;</p><p>みたいなのを保存することができる。</p> </div> <div class="section"> <h4>ストックモード</h4> <p>これをonにすると、コピーしたものを上から順番に取り出すことができる。デフォルトではAlt+Sで切り替え可能。<br /> 文書の構造をいじっていて、順番を入れ替えるときとかに便利そうです。</p> </div> <div class="section"> <h4>定型文</h4> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215072436" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215072436.jpg" alt="f:id:tukasa1919:20120215072436j:image" title="f:id:tukasa1919:20120215072436j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>定型文を登録することが可能。</p> <ol> <li>タスクバーのアイコンを右クリックし、定型文の追加を選択</li> <li>タイトルと本文を入力</li> </ol><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215131455" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215131455.jpg" alt="f:id:tukasa1919:20120215131455j:image" title="f:id:tukasa1919:20120215131455j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>これで、Clip.netを開くと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴と一緒にタイトルが表示される。それを選択することで、その内容を貼り付けることができる。</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215072437" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215072437.jpg" alt="f:id:tukasa1919:20120215072437j:image" title="f:id:tukasa1919:20120215072437j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>このように<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>で内容を表示することも可能。</p> </div> <div class="section"> <h4>インストール</h4> <ul> <li>Dict</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>.dll</li> <li>Bregexp.dll</li> </ul><p>の三つをClip.netフォルダに入れる。これで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>が使えるようになる。</p> </div> <div class="section"> <h4>Clip.net.ini</h4> <p>重要そうなのは</p> <ul> <li>履歴保存数を無制限に(HistoryMax=-1)</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%C1%A5%C3%A5%D7">ツールチップ</a>に表示するテキストの最大文字数を変更(ToolTipMax=5000)</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Migemo">Migemo</a>検索をonに(MigemoSearch=1)</li> <li>貼り付け方法をShift+Insertに(PasteMethod=1)</li> </ul><p>あたりだろうか。<br /> 一応僕の設定で、デフォルトから変えたところを晒してみる。</p> <pre class="code" data-lang="" data-unlink>[MAIN] HistoryMax=-1 ShowNearCaret=0 ShowStartUp=0 ImeOffAlways=1 AutoHide=1 PasteMethod=1 [STYLE] ShowControlBox=0 [TOOLTIP] ToolTipMax=5000 [HOTKEY] ShowHideToggle=1 [MIGEMO] MigemoSearch=1</pre> </div> <div class="section"> <h4>感想</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>履歴はeClipで。AA管理はesPstで行こうかと思ってたけど、これを導入することで一本化できそう。今のところの実感として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9">クリップボード</a>管理ソフトの完成系じゃねえのこれ、と思ってます。</p> </div> tukasa1919 MoEの最小構成 hatenablog://entry/10257846132626153973 2012-02-15T06:27:21+09:00 2018-09-10T16:09:24+09:00 普段使っているPC以外でもMoEができるように、fenrirとかを抜いた最小構成を考えてみる。MoEでやってるのは大掛かりだけどちょっと試してみたいという場合とかもいいかもしれない。あれやろうとすると、フォルダ構造とか少しがんばる必要あるので。MoEの本質は、howm形式でとったメモの編集を、PPxでやることにある。 Xyzzy Xyzzyをインストールした後、次のスクリプトをsite-lispフォルダに入れる。 howmcreate2dir.l ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;… <p>普段使っているPC以外でもMoEができるように、fenrirとかを抜いた最小構成を考えてみる。MoEでやってるのは大掛かりだけどちょっと試してみたいという場合とかもいいかもしれない。あれやろうとすると、フォルダ構造とか少しがんばる必要あるので。</p><p>MoEの本質は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>形式でとったメモの編集を、PPxでやることにある。</p> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xyzzy">Xyzzy</a></h4> <p><a href="http://www.jsdlab.co.jp/~kamei/">Xyzzy</a>をインストールした後、次の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>をsite-<a class="keyword" href="http://d.hatena.ne.jp/keyword/lisp">lisp</a>フォルダに入れる。</p> <ul> <li>howmcreate2dir.l</li> </ul><pre class="code" data-lang="" data-unlink>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;本体 (defvar *temp-howm-dir* nil) (defun make-howm-create2dir-file (howm-dir) (let* ((filename (format-date-string &#34;%Y-%m-%d-%H%M%S.howm&#34;)) (filepath (merge-pathnames filename howm-dir)) (directory (directory-namestring filepath))) (if (not (file-directory-p directory)) (create-directory directory)) (find-file filepath) (if (eq (point-max) (point-min)) (progn (insert (format-date-string &#34;= \n\n[%Y-%m-%d %H:%M]\n&#34;)) (goto-char (+ (point-min) 2)))) )) (defun howm-create2dir () (interactive) (if si:*command-line-args* (setq *howmdir* (pop si:*command-line-args*))) (make-howm-create2dir-file *temp-howm-dir*) (howm-create2dir-mode)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;キーバインド (defun hateda-heading1 () (interactive &#34;*&#34;) (save-excursion (goto-bol) (insert &#34;*&#34;) (fix-selection-point))) (defun hateda-heading2 () (interactive &#34;*&#34;) (save-excursion (goto-bol) (insert &#34;**&#34;) (fix-selection-point))) (defun hateda-num-list () (interactive &#34;*&#34;) (save-excursion (goto-bol) (insert &#34;+&#34;) (fix-selection-point))) (defun hateda-list () (interactive &#34;*&#34;) (save-excursion (goto-bol) (insert &#34;-&#34;) (fix-selection-point))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;モードの設定 (defun howm-create2dir-mode () (interactive) (kill-all-local-variables) (setq buffer-mode &#39;howm-create2dir-mode) (setq mode-name &#34;howm Create2dir&#34;) (make-local-variable &#39;regexp-keyword-list) (setq hateda-regexp-keyword-list (compile-regexp-keyword-list `( (&#34;^[=].*&#34; t (:color 7 13 :line :bold )) (&#34;^[*][*][^*].*&#34; t (:color 10 15 :line )) (&#34;^[*][*][*][^*].*&#34; t (:color 9 12 :line )) ))) (setq regexp-keyword-list hateda-regexp-keyword-list) (use-keymap *howm-create2dir-mode-map*)) (defvar *howm-create2dir-mode-map* nil) (unless *howm-create2dir-mode-map* (setq *howm-create2dir-mode-map* (make-sparse-keymap)) (define-key *howm-create2dir-mode-map* &#39;#\C-] &#39;hateda-heading1) (define-key *howm-create2dir-mode-map* &#39;#\C-: &#39;hateda-heading2) (define-key *howm-create2dir-mode-map* &#39;#\C-+ &#39;hateda-num-list) (define-key *howm-create2dir-mode-map* &#39;#\C-- &#39;hateda-list) (define-key *howm-create2dir-mode-map* &#39;(#\C-c #\, #\c) &#39;howm-create2dir))</pre><p>ついで、.<a class="keyword" href="http://d.hatena.ne.jp/keyword/xyzzy">xyzzy</a>に以下を追加。</p> <pre class="code" data-lang="" data-unlink>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;howmモード (pushnew &#39;(&#34;\\.howm$&#34; . howm-create2dir-mode) *auto-mode-alist* :test #&#39;equal) (require &#34;howm-create2dir&#34;)</pre> </div> <div class="section"> <h4>PPx</h4> <ul> <li><a href="http://homepage1.nifty.com/toro/slppx.html">Paper Plane xUI&#x672C;&#x4F53;</a></li> <li>Paper Plane xUI Script Module(これも本体と同じページからダウンロード)</li> </ul><p>をインストールした後、PPxフォルダにscriptフォルダを作る。<br /> そこに次の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を保存。</p> <ul> <li>MakeComment.js</li> </ul><pre class="code" data-lang="" data-unlink>//!*script var strLine = &#34;\n&#34;; currentDir = PPx.Extract(&#34;%1&#34;); // ファイル操作 var objApl = new ActiveXObject(&#34;Shell.Application&#34;); var objFolder = objApl.NameSpace(currentDir); // ファイルのリストを取得 var objFolderItems = objFolder.Items(); // フォルダ内のファイルとフォルダへの処理 for(var i=0;i&lt;objFolderItems.Count;i++) { var objItem = objFolderItems.Item(i); var objFileSys = new ActiveXObject(&#34;Scripting.FileSystemObject&#34;); // ディレクトリでなく空ファイルでもなく00_INDEX.txtでもなく拡張子がtxtかhowmの場合に処理する if (objItem.IsFolder==false &amp;&amp; objItem.Size != 0 &amp;&amp; objItem != &#34;00_INDEX.txt&#34; &amp;&amp; (objFileSys.GetExtensionName(objItem) == &#34;txt&#34; || objFileSys.GetExtensionName(objItem) == &#34;howm&#34;)) { // ファイルの内容を取得 objInFile = objFileSys.OpenTextFile(objItem, 1); // ファイル名+Tab+一行目の最初二文字を切り取ったもの+改行をstrに代入 str = objItem + &#34;\t&#34; + objInFile.ReadLine().slice( 2 ) + &#34;\n&#34; strLine = strLine + str; objInFile.Close(); }else{} } // カレントディレクトリに00_INDEX.txtを作成 strCreateFile = objFileSys.BuildPath(currentDir,&#34;00_INDEX.txt&#34;); objFileSys.CreateTextFile(strCreateFile); // 00_INDEX.txtに書き込み objOutFile = objFileSys.OpenTextFile(strCreateFile, 2); objOutFile.Write(strLine); objOutFile.Close(); PPx.Execute(&#34;%K\&#34;@[F5]\&#34;&#34;)</pre><p>次に、以下をコピペして、カスタマイザーから編集して取り込み。</p> <pre class="code" data-lang="" data-unlink>;PPcのキーカスタマイズ KC_main = { ; PPcメイン窓 F6 ,*script %0\Script\MakeComment.js \K ,%M_makefile,H E ,%&#34;Text edit&#34;%Orib,editor %FDC } ;表示形式&#34;howmtitle&#34;の追加 MC_celS = { ; エントリ表示 書式([;]メニュー) howmtitle = M cF50,5 C z7 S1 tC&#34;y-N-D&#34; s1 } ;拡張子がhowmの時にEnterを押すとビューアが起動 E_cr = { HOWM ,%v %FCD } ;PPvのキーカスタマイズ KV_main = { UP ,%KC&#34;@UP@N&#34; DOWN ,%KC&#34;@DOWN@N&#34; SPACE ,%KC&#34;@SPACE@N&#34; \SPACE ,%KC&#34;@\SPACE@N&#34; ENTER = @Q } ;howm作成用メニュー ;パスはxyzzyをインストールした場所になおす M_makefile = { ** comment ** &amp;howm-create2dir = %Ob D:\bin\xyzzy\xyzzy.exe -e (howm-create2dir) %1 -- = ディレクトリ(&amp;D) = *makedir %1\%E }</pre><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120215062704" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120215/20120215062704.jpg" alt="f:id:tukasa1919:20120215062704j:image" title="f:id:tukasa1919:20120215062704j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> </div> <div class="section"> <h4>利用するとき</h4> <p>PPxで適当なフォルダに行き、</p> <ul> <li>Shift+Kで<a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイル作成用メニューを起動する。</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120214140314" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120214/20120214140314.jpg" alt="f:id:tukasa1919:20120214140314j:image" title="f:id:tukasa1919:20120214140314j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/xyzzy">xyzzy</a>が起動するのでメモを書き、保存する</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120214132306" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120214/20120214132306.jpg" alt="f:id:tukasa1919:20120214132306j:image" title="f:id:tukasa1919:20120214132306j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li>メモがいくつかたまったら、F6を押してコメントファイルを作成</li> <li>";"を押し表示形式メニューを出し、howmtitleを選択してタイトル表示に</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120214132307" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120214/20120214132307.jpg" alt="f:id:tukasa1919:20120214132307j:image" title="f:id:tukasa1919:20120214132307j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> </p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/howm">howm</a>ファイル上でEnterを押すとビューアが起動。カーソル上下で移動する。もう一度Enterを押すと閉じる</li> </ul><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/tukasa1919/20120214132308" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tukasa1919/20120214/20120214132308.jpg" alt="f:id:tukasa1919:20120214132308j:image" title="f:id:tukasa1919:20120214132308j:image" class="hatena-fotolife" itemprop="image"></a></span></p> </div> tukasa1919