2012-04-22 20 views
3

JLabelとJButtonを含む複合オブジェクトのJTreeを作成しようとしています。ノードはJLabelによって示されるサーバーとポートを表しています.JButtonはDesktop APIを使用してデフォルトのブラウザを開き、URLに移動します。複合JTreeノードの下にあるオブジェクトにイベントを渡すノード

私は次のことをすでに読んでおり、できるだけ忠実に従ってきました。ノードはどのようにして表示されますか(主に後でそれをより良くすることができます)が、ボタンをクリックしようとするとJTreeはボタンではなくイベントに応答します。 JButtonまたはJLabelの - 私は、それらが下にオブジェクト(複数可)によって処理されるようにイベントがJTreeの通過を可能にする方法を知っておく必要があり

java swing: add custom graphical button to JTree item

http://www.java2s.com/Code/Java/Swing-JFC/TreeCellRenderer.htm

https://stackoverflow.com/a/3769158/1344282

。ここで

は私のTreeCellEditorです:ここでは

public class UrlValidationCellEditor extends DefaultTreeCellEditor 
{ 
    public UrlValidationCellEditor(JTree tree, DefaultTreeCellRenderer renderer) 
    { 
     super(tree, renderer); 
    } 

    @Override 
    public Component getTreeCellEditorComponent(JTree tree, Object value, 
      boolean isSelected, boolean expanded, boolean leaf, int row) 
    { 
     return renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true); 
    } 

    @Override 
    public boolean isCellEditable(EventObject anEvent) 
    { 
     return true; // Or make this conditional depending on the node 
    } 
} 

はのTreeCellRendererです:

public class UrlValidationRenderer extends DefaultTreeCellRenderer implements TreeCellRenderer 
{ 
    JLabel titleLabel; 
    UrlGoButton goButton; 

    JPanel renderer; 

    DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer(); 

    public UrlValidationRenderer() 
    { 
     renderer = new JPanel(new GridLayout(1, 2)); 
     titleLabel = new JLabel(" "); 
     titleLabel.setForeground(Color.blue); 
     renderer.add(titleLabel); 
     goButton = new UrlGoButton(); 
     renderer.add(goButton); 
     renderer.setBorder(BorderFactory.createLineBorder(Color.black)); 
     backgroundSelectionColor = defaultRenderer 
      .getBackgroundSelectionColor(); 
     backgroundNonSelectionColor = defaultRenderer 
      .getBackgroundNonSelectionColor(); 
    } 

    @Override 
    public Component getTreeCellRendererComponent(JTree tree, Object value, 
     boolean selected, boolean expanded, boolean leaf, int row, 
     boolean hasFocus) 
    { 
     Component returnValue = null; 
     if ((value != null) && (value instanceof DefaultMutableTreeNode)) 
     { 
      Object userObject = ((DefaultMutableTreeNode) value) 
       .getUserObject(); 
      if (userObject instanceof UrlValidation) 
      { 
       UrlValidation validationResult = (UrlValidation) userObject; 
       titleLabel.setText(validationResult.getServer()+":"+validationResult.getPort()); 
       goButton.setUrl(validationResult.getUrl()); 

       if (selected) { 
        renderer.setBackground(backgroundSelectionColor); 
       } else { 
        renderer.setBackground(backgroundNonSelectionColor); 
       } 
       renderer.setEnabled(tree.isEnabled()); 
       returnValue = renderer; 
      } 
     } 
     if (returnValue == null) 
     { 
      returnValue = defaultRenderer.getTreeCellRendererComponent(tree, 
       value, selected, expanded, leaf, row, hasFocus); 
     } 
     return returnValue; 
    } 

} 

私は任意の洞察力や提案をいただければ幸いです。ありがとう!

+0

ユーザーがそのツリーノードを選択したのにボタンを選択しなかった場合、どうなるでしょうか? –

+0

まあ、ノードにはラベルとボタンの2つの部分が必要です。ユーザーがラベルをクリックすると、ノードに関する詳細な情報がGUIの別の部分に表示されます。ユーザーがボタンをクリックすると、ブラウザウィンドウが開きます。 JTreeがユーザー入力に応答するのを防ぐ方法がわからないので、ユーザーがラベルまたはボタンをクリックしたときに、それらのイベントがそれぞれラベルまたはボタンによって処理されるようになります。 – Kal

答えて

10

レンダラはこのように動作しません。それらはラバースタンプとして使用されます。つまり、実際にJListがペイントされるときにレンダリングされるレンダラーのインスタンスは1つだけです。オブジェクトは実際には存在しないので、マウスの入力を処理することはできません。

マウスイベントを下のオブジェクトに渡すには、セルエディタを実装する必要があります。エディタがレンダラと異なって見えることがあります(文字列レンダラはラベル、エディタはテキストフィールドなど)。このロジックに従って、エディタはコンポーネントの別のインスタンスを使用して実装する必要があります。

これで、ボタンをレンダリングし、操作(つまり編集)に使用します。エディタはレンダラとは別のJButtonの別のインスタンスでなければなりません。レンダラとしてボタンを実装するのは簡単ですが、難しい部分はエディタとして実装することです。 AbstractCellEditorを拡張し、TreeCellEditor とActionListenerを実装する必要があります。このボタンは、エディタクラスのフィールドです。エディタクラスのコンストラクタでは、ボタンを初期化し、の新しいアクションリスナとしてを追加します。を追加します。 getTreeCellEditorComponentメソッドでは、ボタンを返します。 actionPerformedでは、ボタンを押してコードを実行し、stopCellEditing()を呼び出します。

これは私のために働く。

私は、ノードが2部ラベルとボタンを持つべきである文字列ツリー

public class Start 
{ 
    public static class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor, ActionListener, MouseListener 
    { 
     private JButton button; 
     private JLabel label; 
     private JPanel panel; 
     private Object value; 

     public ButtonCellEditor(){ 
      panel = new JPanel(new BorderLayout()); 
      button = new JButton("Press me!"); 
      button.addActionListener(this); 
      label = new JLabel(); 
      label.addMouseListener(this); 
      panel.add(button, BorderLayout.EAST); 
      panel.add(label); 
     } 

     @Override public Object getCellEditorValue(){ 
      return value.toString(); 
     } 

     @Override public void actionPerformed(ActionEvent e){ 
      String val = value.toString(); 
      System.out.println("Pressed: " + val); 
      stopCellEditing(); 
     } 

     @Override public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row){ 
      this.value = value; 
      label.setText(value.toString()); 
      return panel; 
     } 

     @Override public void mouseClicked(MouseEvent e){ 
     } 

     @Override public void mousePressed(MouseEvent e){ 
      String val = value.toString(); 
      System.out.println("Clicked: " + val); 
      stopCellEditing(); 
     } 

     @Override public void mouseReleased(MouseEvent e){ 
     } 

     @Override public void mouseEntered(MouseEvent e){ 
     } 

     @Override public void mouseExited(MouseEvent e){ 
     } 

    } 

    public static class ButtonCellRenderer extends JPanel implements TreeCellRenderer 
    { 
     JButton button; 
     JLabel label; 

     ButtonCellRenderer(){ 
      super(new BorderLayout()); 
      button = new JButton("Press me!"); 
      label = new JLabel(); 
      add(button, BorderLayout.EAST); 
      add(label); 
     } 

     @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus){ 
      label.setText(value.toString()); 
      return this; 
     } 

    } 

    public static void main(String[] args){ 
     JTree tree = new JTree(); 
     tree.setEditable(true); 
     tree.setCellRenderer(new ButtonCellRenderer()); 
     tree.setCellEditor(new ButtonCellEditor()); 

     JFrame test = new JFrame(); 
     test.add(new JScrollPane(tree)); 
     test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     test.setSize(500, 500); 
     test.setLocationRelativeTo(null); 
     test.setVisible(true); 
    } 
} 
+0

しかし、この例をお寄せいただきありがとうございます。 JTreeのノードとしてJButtonを使用していますが、JLabelとJButtonを含むJPanelを使用したいとします。次に、ユーザーがJLabelまたはJButtonをクリックできるようにしたいとします。 – Kal

+0

@Kal編集を参照してください。私は今、あなたのニーズにその例を適応させることができると信じています。 –

+0

本当にありがとうございました。再度、感謝します! – Kal

1

の使用状況を示しSSCCEを作りました。ユーザーがラベルをクリックすると、ノードに関する詳細な情報がGUIの別の部分に表示されます。ユーザーがボタンをクリックすると、ブラウザウィンドウが開きます。 ..

このようにしないでください。代わりに、ラベルだけをツリーに入れてください。 「ノードに関する詳細情報」を表示する同じGUIにボタンを追加します。

+0

これは、クリックが余分に必要になります。ボタンを頻繁に使用する場合は、ツリーの中に入れる方がよいでしょう。それ以外の場合は、GUIを一貫性のあるものにするために、記述したようにする方がよいでしょう。 – Nulano

関連する問題