1

これが状況です。タブ付きペインのあるjFrameがあり、タブ内に2つのjTableとjTreeがあります。ユーザーがCtrl/Shift +クリックを使用するか、通常のクリックを使用するかに基づいて、テーブルとツリーの間で選択を連鎖できるようにしたいと思います。(Ctrlキーを押しながら最初のテーブル/ツリーをクリックすると、全体の選択に追加されます。通常のクリックを使用すると、他のテーブル/ツリーの選択がクリアされます)。現在、JavaのjTreeコンポーネントに問題があります。TreeSelectionListenerとMouseListenerを追加し、両方のインターフェイスを実装するクラスを追加しました。これをMyBigListenerと呼びます。すなわち

MyBigListener listener = new MyBigListener();
jTree1.addMouseListener( listener );
jTree1.addTreeSelectionListener( listener );

MyBigListener implements TreeSelectionListener, MouseListener {
  private boolean chained = false;
  public synchronized setChained(boolean ch){
    chained = ch;
  }
  public synchronized boolean isChained(){
    return chained
  }
  public void valueChanged(TreeSelectionEvent e){
    if(isChained()){ blah... }
  }

  public void mousePressed(MouseEvent e){
    setChained(e.isControlDown() || e.isShiftDown());
  }
}

私の計画は、ユーザーがctrl / shift +クリックを使用する場合にブールフラグを設定することでした。これは、ツリー選択リスナーによって実装されたvalueChanged(TreeSelectionEvent e)中に確認できます。valueChanged TreeSelectionEventsの前にマウスイベントを処理できるようにしたいのですが、問題は、valueChangedtreeSelectionイベントの後にマウスイベントを受け取ることです。これは、マウスを押すことによって選択の変更が実際に開始されたときに、マウスを押すイベントが発生する前に選択の変更を受け取ることは私には奇妙に思えます。(私はすでにブールフラグ設定を同期しました。これは皮肉なことに、イベントの順序の誤りを強調するのに役立ちました。)

keyListenerを追加するなどの代替手段をすでに試しましたが、フォーカスが別のフレームにある場合は機能しません。これは、ユーザーがCtrlキーを押しながらjTreeをクリックすると、フォーカスと起動の両方を受け取るようになります。 valueChanged選択イベント。

助けていただければ幸いです、ありがとう!

--編集--@akf タブ付きペインに個別のjTableとjTreeがあり、ノードグラフのデータの要約/コントロールパネルとして機能します。タブ付きペインでこれらのコンポーネントを使用して、別のjFrameに表示されるグラフを調整して選択しています。個別に、各テーブルは、jTreeと同様に、その選択に対して問題なく機能します。トリッキーなのは、ペイン間の調整です。これは、jTableコンポーネントでこれまでのところ正常に機能します。これは、Shift / Ctrlボタンが押されているかどうかを確認できるMouseEventの結果として新しい選択を起動し、新しい選択を作成して、すべての間で選択を調整する親フレームに渡すためです。ペインを作成し、最終的な選択をグラフに送信します。ただし、親は、選択範囲をペイン間でチェーンする必要があるのか​​、それとも他のペインを押しつぶす必要があるのか​​を知る必要があります。jTablesを使用すると、再び問題ありません。マウスクリックの結果として選択の変更を起動するためです。私はいくつかの強制的な選択を行っているので、jTreeはもっと問題です。ブランチをクリックすると、すべての葉が選択範囲に強制されます。これを行うにはTreeSelectionListenerを実装する必要がありましたが、実現された変更に対してvalueChanged(TreeSelectionEvent)のみを取得します。ctrl+clicksとshift+clicksをリッスンするためにmouseListenerを追加しましたが、イベントが常に同じ順序で発生するとは限らないようです。少なくともこれまでのところ、mousePressedイベントの前にvalueChangedイベントを受け取っているので、ctrlかどうかを確認します。 +選択がすでに変更された後、発生した投稿をクリックします。これを行うにはTreeSelectionListenerを実装する必要がありましたが、実現された変更に対してvalueChanged(TreeSelectionEvent)のみを取得します。ctrl+clicksとshift+clicksをリッスンするためにmouseListenerを追加しましたが、イベントが常に同じ順序で発生するとは限らないようです。少なくともこれまでのところ、mousePressedイベントの前にvalueChangedイベントを受け取っているので、ctrlかどうかを確認します。 +選択がすでに変更された後、発生した投稿をクリックします。これを行うにはTreeSelectionListenerを実装する必要がありましたが、実現された変更に対してvalueChanged(TreeSelectionEvent)のみを取得します。ctrl+clicksとshift+clicksをリッスンするためにmouseListenerを追加しましたが、イベントが常に同じ順序で発生するとは限らないようです。少なくともこれまでのところ、mousePressedイベントの前にvalueChangedイベントを受け取っているので、ctrlかどうかを確認します。 +選択がすでに変更された後、発生した投稿をクリックします。

現在、保留中の選択の変更を投稿してから、MouseListenerにそれを取得してチェーンに送信させていますが、これらのイベントが同じ順序で発生することが保証されていない場合、ある時点で失敗します。遅延器を実装することも私を間違った方法でこすります。

これまでの助けに感謝します。

--編集2--@ykaganovich

fireValueChangedメソッドをオーバーライドする方が、物事を進める正しい方法に近いと思います。どのアクションが他のコンポーネントへの「連鎖」選択を引き起こすかについての私の定義に応じて、valuedChangedメソッドが起動する前に何が起こっているかについてのコンテキストを収集する必要があります。これは基本的に、誰がそれをトリガーするかによってそれが何を意味するかを定義できるすべての場合に自分でそれを呼び出すことを意味します。つまり、マウスイベントが原因で、Ctrlキーが下がっている場合は、設定(解釈)する必要があるものを設定してから起動します。キーボードイベントが原因で変更される場合は、もう一度、設定する必要があるものを設定してから起動します。イベントが発生したときの状況がまだわからないため、TreeSelectionModelが進むべき道ではないと思います。これは、これを行うためにjTreeの一部を書き直す必要があることを意味すると思いますが、私は それがどうなるか見てみましょう。ありがとう。

4

3 に答える 3

1

ツリー選択イベントの前後にマウスイベントが発生する場合があります。そのような注文に頼らないのが最善です。その理由は、ツリー選択イベントがマウスイベントに応答して発生するためです。そのマウスイベントリスナーは、リスナーの前または後に呼び出されますか?どちらかである可能性があります。

このようなことは、PL&Fの実施と密接に関係しています。

于 2009-09-24T03:00:08.497 に答える
1

そのようにしないでくださいJTree.fireValueChanged。代わりにオーバーライドしてください。

このようなものを試してください(テストされていません):

class ChainedSelectionEvent extends TreeSelectionEvent {
  ChainedSelectionEvent(TreeSelectionEvent e) {
    super(e.newSource, e.paths, e.areNew, e.oldLeadSelectionPath, e.newLeadSelectionPath);
  }
}

protected void fireValueChanged(TreeSelectionEvent e) {
  if(chained) { // figure out separately
      super.fireValueChanged(new ChainedSelectionEvent(e));
  } else {
      super.fireValueChanged(e);
  }
}

次に、リスナーでChainedSelectionEventのinstanceofを確認します

編集

実際、これを行う正しい方法は、独自のTreeSelectionModelを実装し、代わりにそこでfireValueChangedをオーバーライドすることだと思います。setSelectionPath(s)メソッドが新しい選択を意味し、連鎖を意味すると仮定すると add/removeSelectionPath(s)、2つを明確に区別できます。キーボードまたはマウスのイベントを明示的に聞くのは好きではありません。選択を変更する方法が複数あるためです(たとえば、誰かがShiftキーを押しながら下矢印を押している場合、マウスイベントは発生しません)。

于 2009-09-24T06:12:17.830 に答える
0

ここで重要なのは、JTreeがBasicTreeUI.MouseHandlerで提供されることを理解することです。javax.swing.plaf.basic.BasicTreeUIを参照してください。

「fireValueChangedを起動するもの」という中心的な質問に答えるには、答えは「このマウスハンドラー」です...これは、tree.getMouseListeners()に移動したときに返される唯一のマウスリスナーであることがわかります。

したがって、このデフォルトのマウスリスナーを独自のバージョンに置き換える必要があります...これは少し注意が必要です。私は誰もが発見する必要のあるJythonを使用しています。ただし、このコードをJavaに変換するのはそれほど難しくありません。

  from javax.swing.plaf.basic import BasicTreeUI      
  def makeMouseHandlerClass():
    class MouseHandlerClass( BasicTreeUI.MouseHandler ):
      def mousePressed( self, mouseEvent ):
        genLog.info( "mouse handler MOUSE PRESSED!" )
        nTFSelf.mousePressedStatus = True
        BasicTreeUI.MouseHandler.mousePressed( self, mouseEvent )
        nTFSelf.mousePressedStatus = False

    return MouseHandlerClass
  suppliedMouseHandler = nTFSelf.taskTree.mouseListeners[ 0 ]
  nTFSelf.taskTree.removeMouseListener( suppliedMouseHandler  ) 
  nTFSelf.taskTree.addMouseListener( makeMouseHandlerClass()( nTFSelf.taskTree.getUI() ))

...基本的にここでの同等のJavaは、BasicTreeUI.MouseHandlerをMyMouseHandlerとして拡張し、最後の行でnew MyMouseHandler(tree.getUI())に置き換えます...ここでの「nTFSelf」は単に「this」への参照です。 "これがすべて書かれているコードのオブジェクト...

于 2012-02-29T18:38:37.703 に答える