Readmeじゃないよ 4

■990926

なんか、こだわってプログラミングにハマッちゃうと寝食を忘れるってのは、典型的な体を壊すパターンだよな。別にシェアウェアとかを作っているわけじゃないし、あんまり気にする必要ないんだけど。でも、いろいろなところに気を回して、凝っちゃうんだよね。まぁ、他の人が見てもそこにこだわりがあった、なんてこと伝わらないんだけどさ。自己満足、自己満足。

ちょっと、メニューにこだわってみた。コンビネーションで追加する機能をメニューで登録できるようにして。そこで問題になったことが2点。まずは、追加する際の順序。次が、やっぱりのディアクティベートイベントの発生。順序の方は、既にある項目が選択されていた場合、その前に挿入するようにしたほうが、一律に最後に追加するかということ。明示的に挿入/追加が見えないと操作が難解に感じられちゃうんだよね。ルールが見えないっていうかさ。こちらは一律追加ということに、まずはすることにした。こっちのほうが楽というのもあるんだけど。

問題は後者。以前にも引用符のコンボで問題になったことがあって。そのときは、なんか解決しちゃったので、まぁいいか、という感じだったんだけど、やっぱり出てきたね。基本的にポップアップメニューとかは、内部的にウインドウを開いているはずで(未確認)、そちらに選択動作を行ってフォーカスが動けば、ウインドウの切り替えが発生するのは理解できるんだけど。これについては、結局、メニューを開いているかどうかを示すフラグを入れることにした。

まぁ、こんなもんか。

ところで、申し込んでおいた一太郎Arkのβテスターに返事がきた。希望者多数につきハズレ。でも、メーリングリストには参加できないけど、β版をダウンロードするのはいいよ、ということらしい。いろいろ機能を盛り込んであるから、TechnologyPreview版より安定度が低いよ、ってのはお笑いだけど、現状のJavaじゃぁ、こんなもんだろうね。出来は、というと、なんというか、どうもちゃちな印象。いろいろ、作りこんであって、その辺りを評価すれば、それなりなんだけど。でも、とにかく、ワードプロセッサというよりはエディタに近いというか。

もうちょっと、見てみることにします。

■991009

GUIの部分が大体形になって、あとはやっぱり、設定内容の保持機能を作りこまなきゃな、という気になったので、その辺りを。単純に全てのオブジェクトをシリアライズして、ファイルに書き出す、ってのをまず試してみた。まずは、メインでnewしてオブジェクトを作る前に、シリアライズしたオブジェクトがあるかどうか調べないと。でも、その辺りの機構をメインに入れておく、ってのはちょっとな。

結局、静的なメソッド、getInstanceを用意することにしてみた。getInstanceのなかで、シリアライズされたオブジェクトをファイルから取り出すことを試して、うまく行かなかったらnewすると。お手軽手法は流れとしては、全然問題なく動作するんだけど、やっぱり、丸ごとシリアライズするってのはうまく行かない。

イベント周りのクラスがSerializableを実装していなくて。やっぱり、書き出す必要のないクラスは、書き出さないようにしておきなさい、ということね。ということで、ParamBlockなる値を保持するクラスを用意してみた。でも、しかし、改めて見直してみると、タブのパネル側に分散的に実装できることを結構へんてこに集中的に実装したりしている。

例えば、タブの切り替えで発生するイベントを受け取るかどうかを保持するのに、タブの個々のパネル側じゃなくて、ポップアップメニュー側に格納していたり。なんという仕様だろうねぇ。変に分散していて、統一してないんだよね、この辺りは。やっぱり、分散して持てるものは統一的に分散させちゃって、定型的に処理できるようにしておくべきね。

また、課題が増えた。うーん。

■991023

設定内容の保持に絡んで起きた、設定をどこに格納しておくか、という話し。結局、インタフェースとそれを実装した抽象クラスという継承の階層構造を含めてオーバーホールすることになってしまった。結構な苦労だね。でも、抽象クラスに実装の共通部分を入れこんだので、まぁ、それぞれのパネルの実装は、すっきりした。分散させるべきものは分散させて、効果ありって感じだ。

これで、それぞれのタブを構成するパネルに設定を保存するためのParamBlockを作らせて、集めてシリアライズすればいいわけだ。しかし、最近の設定ファイルの構成のトレンドはxmlなんだよなぁ。まぁ、xmlを解釈するクラスを入れちゃうと、それだけでサイズが倍以上に膨らみかねないから、やってられないけど。さらにリソースバンドルを使うなんて手もあるんだよな。どうしたものかね、こまった、困った。

さてさて、バグを発見。jarしてアプリケーション化しておいた古い版を起動すると、「About...」のイメージが表示されない。今までは、jarで固めても、固めていないファイルをそのまま残しておいていて。jarファイルをカレントフォルダが同じになるようにしておいたから、展開されたほうから読み出されているのに気がつかなかったんだよね。たまたま動いていただけなのね。うーん。jarファイルからイメージを取り出す処理を入れないとな。

■991024

ということで、jarファイルのハンドリングに取り組んだんだけど。しかし、これをjavadocだけをみて作るってので、非常に骨が折れた。JarFileやJarEntry、JarInputStreamなんて、jar関連のクラスがjava.util.jarパッケージに定義されているわけだけど、どれを使えばいいの、てなところ。いろいろ試して、jarファイル内でのイメージファイルのパスを格納するJarEntryを作って、そのInputStreamを取り出してから、データを読み出せばいいってことがわかった。ただ単にデータを読み出すだけなら、JarInputStreamは使わなくていいわけね。

で、次に悩んだのが、InputStreamからデータを読み出すところ。イメージデータをストリームから読み出すなんて、やったことないんだよね。まぁ、とにもかくにも、jarファイルに限った話しじゃないんだけどさ、この辺は。JarEntryはZipEntryを継承していて、ZipEntryにはエントリのサイズを読み出すメソッドが定義されている。ストリームからのデータの読み出しはバッファを引数に渡す必要があるから、あらかじめサイズがわかれば問題ないんだけど、サイズを取り出すメソッドがサイズ不明を示す-1しか返さない。どうしたもんかね、全くさ。

結局、JarInputStreamのソースを読んで、ByteArrayOutputStreamに一旦書き出す、ってな方法を見つけた。確かに、ストリームってのは、サイズの分からないデータが流れてくるわけだから。でも、これってば、JavaAdvancedImaging APIが標準になれば、しなくてもいいのかもしれない。

どうも、ファイル絡みの処理追加ばかりが発生している今日この頃だぞ。

さてさて、そんなこんなでjarファイル内のイメージを取得できるようになったんだけど、もう一つ、以前に臭い物にふたをした一件。引用符のペーストでコンボのメニューでディアクティベートしちゃうって問題。この際なので、動作を見てみたら、なんとも。JComboBoxのメニューは、メニューがウインドウからはみ出していないとウインドウ内に描画し、はみ出している場合はウインドウを開いてメニューを描画する模様。良く出来てるんだけど、後者の場合、ウインドウがディアクティベートしちゃうわけ。

まぁ、ソースコードのレベルまで追ったわけじゃないんだけどさ。一応対策は入れたんだけど、後者に合わせちゃったから、前者の場合1回変換が実施されない、てな事象が発生します。単純にメニューが開いた/閉じたを拾えればいいんだけど、コンボはポップアップとは違うからな。うーん。痛しかゆし。

■991025

めずらしく、平日もJava。ちょっと、昨日の夜、ふとんの中で天井を見ていて、思いついて。まぁ、寝る前にパラパラめくっていたDelphiのプログラミング大全がいい影響与えてくれたんだけどね。しかしまぁ、寝る前になんて本を読んでろうねぇ。

今までは、メニューが開くってタイミングを何とかつかんで、メニューの状態フラグを「開いてます」にセットする、ってことをしてた。開いている間はこれをチェックして、ディアクティベートしても処理しないようにしておいたわけだ。でも、これだとそれぞれのタブからMorePasteウインドウの、メニューフラグ変更メソッドを呼び出すってことをしないといけないわけで、どうもすっきりしなかった。フラグをMorePasteに持たせたってのも含めて、もともと明示的にメニューを開いてやらないといけないポップアップ向けに作った機構で、コンボじゃうまく行かなかったし。

それで思いついたのは、MorePasteがディアクティベートしたときに、その時選択されているタブにメニューを開いていないか調べさせるというやり方。これであればMorePaste自身は、タブに用意したそれを調べるメソッドを呼び出すだけでいいから、すっきりする。タブの方もそれぞれ、コンボの状態とか、ポップアップの状態とかを自分の都合で調べるだけだから、処理を局所化して実現できるわけだ。

問題は、そういう確認処理を受け取るタブを、どうやってMorePasteに教えるかってことね。まぁ、どのタブでも一律に聞きに行くようにしてもいいんだけどさ。ちょっと考えて、インタフェースとinstanceof演算子を使うことにした。インタフェースを用意して、そこに確認のメソッドとかの宣言を集めちゃう。実装しているかどうかをinstanseofで調べて、あれば呼び出す、という仕組みね。

結構すっきりした実装が出来て、うまく動いたということで、今夜は良く寝られそう。

■991103

文化の日です。先日ノートPCを買ったんだけど、注文して4日目にIntelから新しいCPUの出荷が発表された。5日目にノートPCの新しいモデルが発表された。6日目に注文したPCが届いた。うーん。ちなみにメーカのコールセンタの人は、「送り返してもいいですよ」と言ってくれた。でも、新しいのに注文し直したとして、手に入るのは12月初旬になるっているし、まぁ、大した性能アップでもないからな。で、会社に届けてもらったPCを車で取りに行こうかと思ったんだけど、プログラムをいじり始めたら行きそびれちゃった。

タブのパネル側にいろいろと属性設定をして、それを読み出すことで初期状態を制御するようになったので、新しいパネルを作ることにした。ファイルパスのペースト。今までのは加工して出す、って機能ばかりだったけど、今回のはただ貼りつけるだけです。

JTreeを使って、MorePasteの小さなウインドウの中にエクスプローラのようにフォルダの構造を表示する。ファイルを選択してMorePasteをディアクティベートすれば、パスがペーストされます。これってば結構評判のいい機能だったりする。

しかし、JTreeもAPIドキュメントだけだとさすがに辛い。JavaSoftのWebサイトにあるチュートリアルへのリンクは必須だね。いろいろとAPIだけじゃわからないことが書いてある。

java.ioのFileクラスを使って、必要に応じてフォルダ階層を調べて、JTreeに枝を追加していく。しかし、マルチプラットフォーム対応ということになると、Windows特有のフォルダ構成が記述できなくて、少なくともWindows環境だと機能不足に見えそう。Windowsは、ルートフォルダがデスクトップで、その下にマイコンピュータがあって、その中にストレージがあるから、でもそんな構造を動的に調べるなんてことはJavaのクラスには出来ないんだよね。まぁ、当然なんだけどさ。

あと、ネットワークドライブをUNC形式で取得したり、なんてことも出来ない。この辺りはちょっと痛いと言えば痛い。うーん。

とりあえず、いろいろと指向錯誤して、フォルダ構成をくみ上げるってことは出来るようになって。Delphi版より優れているのは、複数のファイルやフォルダを選択して、一度にパスをペーストする機能。とにかくDelphiでは実装していなかったから。

今はまだ、他のタブと同様にプラグインにはしてないんだけど、これ自体はプラグインにするつもり。だからあとは、プラグインローダを作るだけだな。

■991107

件のノートPCをとってきた。ノートとは言っても今まで家で使っていたデスクトップよりナンボ速いからね。まぁ、Windows98でしかもSecondEditionなのが気になるけど、USBを使ったり、ってことを考えるとしかたがないし。しかし、いろいろと環境のセットアップをしていて、問題発見。オブジェクトモデルを描くのにそれ用のエディタを使ってるんだけど、それがAdobeのAcrobatとぶつかる。困った、こまった。PDFの作成は、他のマシンですることにして、とりあえず、Acrobat Readerを入れておくことにしよう。

この前から作っているパスのペースト機能を使っていて、お笑いなバグを発見。スクロールバーが出て、スクロールした状態にすると、ポップアップメニューがクリックした場所に出ない。そりゃそうだ。クリックの反応はスクロールペインの中身に対して受け取らせるように指定している。中身はスクロールしようがしまいが関係なく、それ自身のクリックされた座標を返すから、当然、見た目とはずれた値になるわな。補正してやらないと。
まぁ、これはそれほど難しくないからいいんだけどさ。おんなじような状況は、コンボ機能でも起きているはずだよな、と思って確かめたみたら、やっぱりその通り。ちゃんと入れておきます、こっちにもさ。

ところで、ポップアップメニューってのは、この前つけた新しい機能。そもそも、今までのだと、システムファイルとか不可視設定のファイルなんかも見えちゃうので、そういうのは表示しないことにしようと思って。で、どうせそんな機能をつけるなら、選べるようにしましょ、ということで付けたのでした。

それしか機能がないのにポップアップってのもねぇ、ということで、ファイルとフォルダの並び順を変更したり、表示の中身をリフレッシュしたり、なんてのも付けてみた。はっきり言って蛇足だったね。指定した並び順で取り出す処理なんか、結構大変。とりあえず、並び順に関する機能はまぁ、なんとかできた。問題は、今すでに表示されている木の構造をリフレッシュしたり、並び順変更を反映させたり、ってことだな。

なんだかんだで、パスのペーストが現時点で、一番大きくなっちゃった。それでもまだ、未実装な機能がいくつかあるってんだから。プラグインとして、外出しにするのに足る、それなりのものになりそうだけど、しかし、まだ先が長いな。

■991122

ノートPCで作業をするのが、やっと軌道に乗ってきた。2週間かかったからね、結構時間がかかったもんだ。予算の都合から、Windows98のSecondEditionのモデルを選んだんだけど、結局、WindowsNTに入れ替えた。これが時間のかかった原因ということにしておこう。どうしても、ServletとかJSPとかの開発のできる環境がほしかったんだよね。Win98だとGigsawとかは例外を吐くし、JSWDKなんかは環境変数の長さが125(?)までっていう制限で、付属の開発用サーバのバッチがうまく動作しないし。Apacheは動作設定が面倒だし。とにかく、あんまり気持ちよくない。うーん。

マシン環境の設定に時間がかかったのは確かなんだけど、それ以上に時間がかかったのはやっぱり懸念したとおり、パスのリフレッシュ機能の実装。悩んだのは、ファイル数が変わったときへの対処で、これはファイルの削除とかがあったり、不可視属性のファイルの表示切り替えをしたり、なんかで起こったりする。

JTreeにすでに表示されている枝を削除する、ってのはいいんだけど、並べ替えとか、挿入なんてのは、あんまりやり易いようにJTreeは作られてない。さらに、展開されているパスや選択されているパスを保存するようにしたかったし。WinのExplorerだと選択なんかは、「最新の情報に更新」すると外れちゃうんだよね。選択しているフォルダとか削除しちゃうと、マイコンピュータにフォーカスが飛んじゃうし。こういう良くない部分は、解決するように実装しないとな。

この辺りの解決は、TreePathとTreeNodeの関係がわかったり、Javaのガーベージコレクションの仕組みに気をまわせるようになるまでかかった。フォルダの中身の並びをVectorに保持する一方で、対応するTreeNodeはTreeMapを使ってファイル/フォルダ名と関連付けて保持する。TreeNodeから子Nodeを削除するメソッドは、内部的にはVectorから要素を外すだけだから、ほかで参照を保持しておけばごみ拾いされることはないし。並び順を変更するために、JTreeからTreeNodeを一旦外して、TreeMapで管理する、ってのが思いつかなかったんだよね。

でも一番の時間がかかった理由は多分、JTreeのモデルのreloadを呼び出してやらないと、描画が更新されない、ってことを知らなかったってことかなぁ。そりゃそうだよなぁ、うーん。山を越えて、ちょっと欲が出たので、Tooltipを出すってことをやってみよう。こいつもAPIドキュメントだけだと、なにもできないです。

おしまい
Mail to author Mail to author. Top of this page.

[This page was updated: 2003-03-09 ]

 

 
Copyright © 2001-2003 Takashi KOBAYASHI. All Rights Reserved.