12

JTreeノードを更新する必要があるJavaSE7アプリケーションがあります。このスレッドを使用してOracleが提供したチュートリアルから、コードのラベル(ツリー上のノードの表示テキスト)を更新する方法についてのヒントはありません。現在、私DefaultTreeModelは自分のモデルとして、JTreeそしてDefaultMutableTreeNode前述のツリーのノードとして使用しています。

私が取り組んでいるアプリケーションの詳細については、アカウントごとに連絡先が可用性ステータス(オンライン、オフラインなど)で表示されるチャット機能を開発しています。

問題は、特定のノードの表示されたテキストを、その親から(せいぜい)削除して指定されたインデックスに追加せずに、どうすれば更新できるかということです。のようにDefaultMutableTreeNode.setText("<new label>")


更新:2013年1月20日

明確化のために質問を再定義しました。

4

4 に答える 4

10

おそらく、「reload()」の代わりに「nodeChanged()」を使用すると、希望する効果が得られます。

DefaultTreeModelクラスには、ツリーのさまざまな部分を変更して再描画するための一連のメソッドがあります。DefaultTreeModelには、再描画のみを実行する他のメソッドもあります。

'reload(node)'について言及し、呼び出すとツリーが崩壊することをコメントしました。'reload'により、サブツリー全体がそのノードから完全に再描画されます。(ただし、そのノードが表示されていない場合は、何も変更されません。)これは「構造変更」と呼ばれます。

'insertNodeInto()'および'removeNodeFromParent()'は、ノードを追加または削除してから再描画することにより、ツリー構造を変更します。

'nodeChanged()'は、ノードで何かが変更されて表示が異なることをモデルに通知するだけなので、必要なものだと思います。おそらく、表示可能なテキストは以前とは異なっています。おそらく、ノードのユーザーオブジェクトを変更しました。これは、ノードで「nodeChanged()」を呼び出すときです。

折りたたみ中の独自のコードおよび提供されているサンプルプログラムvels4jで、「reload()」呼び出しの代わりに「nodeChanged()」を試す必要があります。これで問題が解決する可能性があります。

DefaultTreeModelには、他の場合に使用される他の2つのメソッドファミリーもあることに注意してください。

これらのメソッドはツリーノードで機能し、ツリーパスを使用して変更が行われた場所を定義します。ツリーの基礎となるデータ構造は変更されませんが、モデルに何かが変更されたことを通知するため、実際に再描画したり、変更に応答したりするリスナーに通知できます。

nodesWereInserted() nodesWereRemovde() nodesChanged() nodeStructureChanged()

fire...()DefaultTreeModelおよび作成するサブクラスの内部で使用される一連のメソッドもあります。何かが変わったことをリスナーに通知するだけです。それらが保護されていることに注意してください。

于 2013-01-21T19:13:38.343 に答える
8

このシンプルで実行可能なプログラムが問題の解決に役立ちますように。

public class JTreeDemo  extends JPanel
    implements Runnable {

private JTree tree;
private DefaultTreeModel treeModel ;
private Random rnd = new Random();
private List<User> userList;
public JTreeDemo() {
    super( );

    //Create the nodes.
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode("Users");
    treeModel = new DefaultTreeModel(top);
    createNodes(top);

    //Create a tree that allows one selection at a time.
    tree = new JTree(treeModel);
    tree.getSelectionModel().setSelectionMode
            (TreeSelectionModel.SINGLE_TREE_SELECTION);

    //Create the scroll pane and add the tree to it. 
    JScrollPane treeView = new JScrollPane(tree);


    //Add the split pane to this panel.
    add(treeView);
}

public String getRandomStatus() {
    int nextInt = rnd.nextInt(100);
    if( nextInt%2==0) {
        return "Online";
    } else {
        return "Offline";
    }
}
@Override
public void run() {
     while(true) {
        try {   
          Thread.sleep(1000);
          int nextInt = rnd.nextInt(10);
          User user = userList.get(nextInt);
          user.setStatus(getRandomStatus());
          treeModel.nodeChanged(user);
        } catch (InterruptedException ex) {
            // handle it if necessary
        }
     }
}

private class User extends DefaultMutableTreeNode {
    public String userName;
    public String status;

    public User(String name) {
        userName = name;

    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }

    @Override
    public String toString() {
        String color = status.equals("Online") ? "Green" : "Red";
        return "<html><b color='"+color+"'>"+
                userName +"-"+status +"</b></html>";
    }

}


private void createNodes(DefaultMutableTreeNode top) {
    userList = new ArrayList() ;
    for(int i=0;i<10;i++) {
        User u1 = new User("User " + (i+1));
        u1.setStatus("Online");
         top.add(u1);
         userList.add(u1);
    }
}

private static void createAndShowGUI() {

    JFrame frame = new JFrame("TreeDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Add content to the window.
    JTreeDemo jTreeDemo = new JTreeDemo();
    frame.add(jTreeDemo);
    frame.pack();
    frame.setVisible(true);
    // update status randomly
    Thread thread = new Thread(jTreeDemo);
    thread.start();
}

 public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
 }
}

ステータスをランダムに更新するスレッドを追加しました。必要に応じて変更できることを願っています。

出力:
ここに画像の説明を入力してください


編集:
1。提案に基づいて、reload(node)ツリーモデルのリロードを削除して追加しました。

于 2013-01-20T10:58:09.877 に答える
0

ノードにツリー内で一意でメソッドが実装されているオブジェクトが含まれている場合は簡単です(たとえば、データベースから一意のIDを持つ文字列またはオブジェクトを表示します)equalshashCodeまず、すべての展開されたノードを反復処理し、ノードのオブジェクトをセットに保存します。次に、モデルの更新を実行します。更新後、すべてのノードを反復処理し、それらがセットに含まれている場合は、ツリー内のノードを展開します。
ノードが一意でない場合は、完全なツリーパス(リストなど)をセットに保存し、更新後にチェックしてノードを展開する必要があります。
オブジェクトにどちらequalsも含まれていない場合hashCode(これらのメソッドの両方を実装する必要があります)-このバリアントは使用できません。

于 2013-01-23T18:58:49.320 に答える
0

記録のために(私はLee Meadorに投票しました)、DefaultTreeModel#nodeChanged(javax.swing.tree.TreeNode) が次の方法です。

public class TestFrame extends JFrame {

    public TestFrame() {
        //create gui with simple jtree (and DefaultTreeModel)
        JButton changeBtn = new JButton();
        final JTree jTree = new JTree();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        changeBtn.setText("update selected node");
        getContentPane().add(changeBtn, java.awt.BorderLayout.PAGE_END);
        DefaultMutableTreeNode treeNode1 = new DefaultMutableTreeNode("root");
        DefaultMutableTreeNode treeNode2 = new DefaultMutableTreeNode("blue");
        treeNode1.add(treeNode2);
        treeNode2 = new DefaultMutableTreeNode("violet");
        DefaultMutableTreeNode treeNode3 = new DefaultMutableTreeNode("red");
        treeNode2.add(treeNode3);
        treeNode3 = new DefaultMutableTreeNode("yellow");
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        jTree.setModel(new DefaultTreeModel(treeNode1));
        getContentPane().add(jTree, BorderLayout.CENTER);
        pack();
        //add listener to button, to change selected node on button click
        changeBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                DefaultMutableTreeNode dmt = (DefaultMutableTreeNode)jTree.getSelectionPath().getLastPathComponent();
                //update content/representation of selected node
                dmt.setUserObject("My update: " + new Date());
                //nodeChanged
                ((DefaultTreeModel) jTree.getModel()).nodeChanged(dmt);
            }
        });
    }

    public static void main(String args[]) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestFrame().setVisible(true);
            }
        });
    }
}
于 2013-01-27T17:54:10.560 に答える