SwingのSwingWorkerでテキストエディタの語句強調表示について

このQ&Aのポイント
  • Javaでテキストエディタを作成しています。TeraPadのように特定の語句を強調表示したいのですが、SwingWorkerを使用して実装しています。しかし、SwingWorkerを利用すると無限ループが発生してしまいます。この原因はSwingWorkerで強調表示した際にDocumentListenerが反応しているためです。無限ループを回避するための対策方法を教えてください。
  • Javaのテキストエディタで、特定の語句の強調表示を実装しています。これにはSwingWorkerを使用していますが、SwingWorkerを利用すると無限ループが発生してしまいます。この問題の原因は、SwingWorkerで強調表示する際にDocumentListenerが反応してしまい、無限ループが発生するためです。無限ループを回避するためにはどのような対策が必要でしょうか?
  • 現在Javaでテキストエディタを作成しており、特定の語句を強調表示したいと考えています。これを実現するためには、SwingWorkerを使用しています。しかし、SwingWorkerを利用すると無限ループが発生してしまいます。この問題の原因は、SwingWorkerで強調表示する際にDocumentListenerが反応してしまい、無限ループが発生するからです。無限ループを回避するための解決策をご教示いただけませんか?
回答を見る
  • ベストアンサー

SwingのSwingWorkerについて

現在Javaでテキストエディタを作成しています TeraPadみたいに特定の語句を強調表示できるように JTextPane(フィールドで保持) DocumentListenerを実装したクラス(JTextPaneに編集があったらSwingWorkerを継承したクラスのインスタンスを生成してexecute) SwingWorkerを継承したクラス(doBackgroundで語句の検索や位置の取得,publishでそれらの情報を送ってproccesで実際に強調表示する) のようなことをしているのですが SwingWorkerを通じてJTextPaneの文字を強調表示しようとすると 無限ループしてしまいます これってSwingWorkerで強調表示したときにもDocumentListenerが反応してるんでしょうか? あとどうすれば無限ループしないようにできますか?

noname#226281
noname#226281
  • Java
  • 回答数1
  • ありがとう数7

質問者が選んだベストアンサー

  • ベストアンサー
  • KSOH
  • ベストアンサー率93% (29/31)
回答No.1

>SwingWorkerで強調表示したときにもDocumentListenerが反応してるんでしょうか? 強調表示した際にもDocumentListenerは反応すると思います。AbstractDocument/DocumentListenerのAPI Documentの冒頭に非同期な更新に関する説明があります。それについてどういった配慮で設計されているのか上記質問の内容だけからは不明ですが、DocumentListenerがprocessによる強調表示の際に反応しないことを期待されているとすれば、まずはその点が問題ではないでしょうか。 まずはAPI Documentを見直してみたほうがよいかも知れません。

noname#226281
質問者

お礼

回答ありがとうございます 一応自己解決しました DocumentListener#changeUpdate DocumentListener#insertUpdate DocumentListener#removeUpdate のどのメソッドでも新たにワーカーを作成し、すぐにexecuteしていたのですが 強調表示の処理をproccesではなくdoneで実行するように変えて まだ他のワーカーの処理が終わっていなければなにもせず、 他のワーカーの処理が終わっていればexecuteする としたところうまく動作しました 具体的には、DocumentListenerを実装したクラスのフィールドでワーカーのLinkedListを作成し イベントが呼び出されるたびに先頭の要素をチェック 先頭の要素がnull→execute 先頭の要素がnullでない→処理が終わっていない→return; 先頭の要素がnullでない→処理が終わっている→先頭の要素を削除してexecute,そのワーカーをLinkedListに追加 みたいな感じになりました つまり、複数のスレッドで同時に処理していたのが原因だった?のでしょうか ありがとうございました

関連するQ&A

  • 継承・実装の関係で悩んでいます。

    継承・実装の関係について悩んでいます。 ここでは、アクセス制御を考えずに、インスタンスかstaticかabstract(ここではabstract final staticやabstract classのこと)の違いで、どう継承するのか考えています。 // 継承 はメソッドのオーバーライドのことを考えます。(オーバーロードは考えない) クラスAからクラスBでオーバーライドしたメソッドは、 クラスCでさらにオーバーライドできるのでしょうか? クラスCが クラスBのクラスAからオーバーライドしたメソッド をクラスBのメソッドとして見たときに、オーバーライドすることは可能なのでしょうか? クラスA │ インスタンスフィールドA │ staticフィールドA │ │ クラスA() { } │ │ インスタンスメソッドA () { } │ staticメソッドB() { } ↓ クラスB extends クラスA │ インスタンスフィールドA // 継承 │ インスタンスフィールドB │ staticフィールドB │ │ サブクラス1() { } // コンストラクタは継承しない、super()で呼び出す │ │ インスタンスメソッドA () { } // 継承 │ │ インスタンスメソッドB () { } │ staticメソッドB () { } ↓ クラスC extends クラスB implements インタフェースD, ... ↑ インスタンスフィールドA // クラスBのフィールドを継承 │ インスタンスフィールドB // クラスBのフィールドを継承 │ インスタンスフィールドC │ staticフィールドC │ │ サブクラス2() { } │ │ インスタンスメソッドA () { } // クラスBのメソッドを継承 │ インスタンスメソッドB () { } // クラスBのメソッドを継承 │ インスタンスメソッドD () { } // インタフェースDのメソッドを実装 │ インスタンスメソッドE () { } // インタフェースDのメソッドを実装 │ │ │ インスタンスメソッドC () { } │ staticメソッドC() { } │ interface インタフェースD extends インタフェースE ↑ │ staticフィールドD // public static final │ │ インスタンスメソッドD() { } // public abstract │ インスタンスメソッドE() { } // 継承 │ interface インタフェースE staticフィールドE // public static final インスタンスメソッドE() { } // public abstract

    • ベストアンサー
    • Java
  • servletのマルチスレッドとはどこまで意識をする必要があるのか?

    「servletはマルチスレッドを意識して実装しなくてはいけない」とよく聞きます。 マルチスレッドを意識しなければならないのは、HttpServletを継承したクラスのみなのでしょうか? それとも、そこからインスタンス化される汎用クラスなどもマルチスレッドを意識し、インスタンス変数は悪とされるのでしょうか? となると、汎用クラスのコンストラクタ引数に値を渡し汎用クラス内でインスタンス変数を使用するってコーディングは完全なNGになりますよね。 HttpServlet継承のサーブレットからインスタンス化されれば、都度個別のメモリが割り当てられると思うのですが・・。 ご存知な方いらっしゃいましたらご教授お願いいたします。 以上

    • ベストアンサー
    • Java
  • 抽象クラスが継承されているかどうか検証したい

    Class.forName()にて取得したクラスが、特定の抽象クラスを継承しているかどうかを 検証したいです。 Class.getInterfaces()にて、実装されているインターフェースを取得することが出来ましたが、 Class.getClasses()、Class.getDeclareClasses()のいずれでも、継承されている 抽象クラスを取得することが出来ません。 そもそも抽象クラスはインスタンス化できないからなのかもしれませんが、 ならば、その抽象クラス名称を取得したいです。 方法はありますでしょうか? 無理ならばインターフェースの実装にし、基盤部で動作のカバーを する作りで考え直すつもりです。

    • ベストアンサー
    • Java
  • 同一クラスインスタンス名で別クラスのインスタンス作成方法(C++)

    下記ソース(Java)の処理をするような、C++の実装方法を教えていただきたいです。 【処理内容】 クラスBのインスタンスを保持しており、クラスBのインスタンス名と同一であるクラスAのインスタンス生成 ClassA A_Instance = (ClassA)Class.forName(B_instance.name).newInstance(); 要はクラスインスタンスの名前の求め方がわからないのです。それさえわかれば、newしてクラスポインタを返すメソッドを用意すれば何とかなると考えていますが。 ※C++のAPI一覧はどこにあるのだろうか・・・

  • こういうエディタはありますか?(文字の強調表示)

    こんにちは。 こども向けの文章を書く必要から、 学習漢字に制限しての入力をしたいと思います。 そこで、学年別漢字配当表をエディタに登録し その文字を強調表示させる方法を考えました。 現在使っているエディタは「TeraPad」なのですが プログラミング用モードのキーワードを編集すれば まずまず、希望どおりのことができるようです。 ただ、唯一の難点は、1モードで1種類(1色)の キーワードしか登録できないため、 例えば小学校1年生用漢字と6年生用漢字が 同じ色になってしまいます。 できれば6種類(6色)の強調表示ができ、 そのキーワードを自分で編集できるエディタがあると ありがたいのですが、ご存知でしょうか? もしくは、TeraPadでできるのでしょうか? よろしくお願いいたします。

  • ADODB.Connectionはインターフェイス

    いつもお世話になっております。 C#で特定のDBに接続するクラスを作ろうとADODB.Connection(ADO.Conn)を継承しようとしたところADO.Connはインターフェイスであるため、各メンバの実装をしなくてはなりません。ADO.Connはオブジェクトととしてインスタンスを生成できていたため、なぜインターフェイスがインスタンスを生成してオブジェクトとして使えるのかがわかりません(Excel.Applicationなども同様です)。 これはどのような仕組みになっているのでしょうか?

  • スレッドの待機と再開

    お世話になります。 マルチスレッドのプログラムで悩んでいます。 public class ThreadLocker {  private static boolean isLocked = false;    public static void lock() {   isLocked = true;   while(isLocked) { ; }  }    public static void unlock() {   isLocked = false;  } } まず、このようなクラスを定義しました。そして複数のスレッドが ThreadLocker.lock(); を呼び出して、処理の進行をストップしている状態があるとします。この状態に対して、とある別のスレッドが ThreadLocker.unlock(); を呼び出すと、それまで無限ループしていたスレッドが解放されて処理を始める、という感じです。 この方法を試してみましたが、無限ループで何も処理をしていないとは言え、リソースを食いまくっているようで、マシンが重くなってしまいました。 そこで、スレッドの待機・再開を行う事ができる wait / notify(All?) メソッドを使用すれば良いのではないかと考えたのですが、具体的な方法が分からず、質問させていただきました。 具体的に、どのインスタンスの wait 及び notify(All?) を呼び出せば良いのかが分かりません。 APIリファレンスの「現在のスレッドはこのオブジェクトのモニターのオーナでなければなりません。」の意味もよく分かりません。 ちなみに、待機しているスレッドは複数あり、class Lock の method execute 中で ThreadLocker.lock() しているとします。 また、再開を促すスレッドは1つで、class Unlock の method execute 中で ThreadLocker.unlock() を呼び出すものとします。 そして、それぞれのスレッドは、お互いのインスタンスを知りません。(説明しづらいので、補足要求があれば、ソースで示します。) よろしくお願いいたします。

    • ベストアンサー
    • Java
  • サーブレット、Strutsのスレッドの動きについて

    ここ教えてgooでもこの類の質問は多いですが、現在ある問題に直面しています。過去の質問を見てもピンと来るものがなかったので、2つ質問させてもらいます。 1. 1リクエスト1インスタンスではないことは過去の質問やブログでもわかりました。ということは1リクエスト(サブミット)1スレッドという解釈でよろしいでいいと思います。これを踏まえて例えさせてください。 10台の端末からほぼ同時に同一アクションへサブミットした場合、1つのインスタンスから10スレッドが生まれるということでいいでしょうか?今直面している問題は、トークンチェック等2重サブミット対応をしていない状態で、1台の端末(自分)でサブミットを連打した場合(例えば10回)、10台の端末から同時アクセスした場合と同じ状況になるのでしょうか? 2. 以下はソースのイメージです。 // アクションクラス BarAction継承クラス {  execute {   ~中略~   HogeLogic logic = new HogeLogic();   logic.doLogic();   ~中略~  } } // ロジック HogeLogicクラス {  //インスタンス変数  FooService service=new FooService();  doLogic {   ~中略~   service.insert();   ~中略~  } } 分かりづらかったら申し訳ないです。 言いたいことはBarAction#execute内でHogeLogicクラスを生成しています。ということは生成されたHogeLogicのインスタンス(logic)はスレッドセーフだと思います。 しかしHogeLogicクラスではFooService.serviceがインスタンス変数として宣言されています。 この場合、FooService.serviceはスレッドセーフなのでしょうか?

    • ベストアンサー
    • Java
  • Javaのstaticメソッドの意味を教えて下さい

    Javaのstaticメソッドの意味を教えて下さい。 現在の解釈では、staticなメソッドとはインスタンスの生成に依存せず呼び出せる処理のことだと認識しています。逆にstaticでないメソッドは、生成後のインスタンスにしか使えない処理だと理解しています。 しかし、コンストラクタがstaticでないことに気がつき、疑問が生まれました。コンストラクタはstaticではないので、コンストラクタを呼び出す時にはそのクラスのインスタンスが必要になるはずです。しかしこのインスタンスを作るのにもコンストラクタが必要です。コンストラクタを使うためにインスタンスが必要で、インスタンスを作るためにコンストラクタが必要という無限ループになってしまいました。 そこで改めて、staticメソッドの意味を教えて頂きたいです。

  • c# この高速化の方法あり?

     こんにちは、c#初心者です。  今回は初期化の高速化の方法で悩んでいるので質問させていただきました。  ライブラリ内でstrring型と同じくらい頻繁に初期化が行われる使い方をされるクラスAを作り、そこからクラスBへ、クラスBからクラスCへ…クラスEといった感じで継承させています。  ところが、どのクラスもクラスAと同じように頻繁に新しいインスタンスが初期化されるのでコンストラクタの処理時間が一部のパフォーマンスに結構ひびくのですが、継承しているために、クラスCを初期化するだけで、クラスAとクラスBのコンストラクタが呼び出されてしまい、このことが特にクラスEではきついのです。  確かに呼び出しに取られる時間は少ないとはいえ、もともとコンストラクタでの作業は少ないので、割合としてはそこそこな時間を取っている状態になっています。  そこで思いついたのが、インターフェイスを利用して継承を使わないという方法です。  それぞれ、IA, IB, …, IEで対応するインターフェイスを実装。例えばクラスBはIA, IBの二つ、クラスEはIA~IE全てのインターフェイスを実装している状態です。  他に思いついたのは、上記の方法+クラスB以降を全てクラスAから派生させるという方法です。速度は満点ではありませんが、これならある程度抽象化もできて、余分なコンストラクタ呼び出しも1回で済みます。  ちなみにこれは現在製作中のライブラリ内で使われているクラスです。末端のアプリケーションなら問題ないような気がするのですが、何しろライブラリなのでこんな手法は如何かと思い質問させていただきました。  自分が見る限りではコンストラクタ内に他に余分なコードはありませんし、無論ループはありませんが、他に高速化する方法があればそれも教えていただきたいです。  とりあえず、言語の性能を最大限に引き出すことでの高速化をコンセプトにしているので多言語への乗り換えは無しということでお願いします。

専門家に質問してみよう