0

rootNode を使用して Jtree を作成し、ルート ノードを非同期的に更新する別のスレッドを作成しています。

この Jtree をいくつかの JPanel で独立して実行するとうまくいきます。プロジェクトのどこかで動作していましたが、この Jtree をいくつかの新しい Swing コンポーネントに含めるように求められました。

新しい Swing パネルでは、完全に読み込まれるのではなく、Jtree が画面にレンダリングされる前に (開始時に数ミリ秒間) 挿入されたノードのみが読み込まれます。Jtree がレンダリングされると、更新されません。ここで興味深いのは、ノードにマウス リスナーを作成して、ノード作成機能を右クリックして新しいノードを作成し、その新しいノードを作成して Jtree ルート ノードに追加できるようにすることです。

追加する重要なことは、newThread(){void run}).start() メソッドを使用してスレッドを作成し、Jtree にノードを追加することでした。これまで SwingUtilities.invokeLater メソッドの必要性を感じたことがないためです。しかし、メインウィンドウも開かないよりも SwingUtilities.invokeLater メソッドを使用すると、起動中に停止するだけで、SwingUtilities.invokeLater も古いコンポーネントで正常に動作し、もちろん独立して正常に動作することを確認しました。

そして、私は model.nodeStructureChanged(changedNode); を呼び出します。ノードを追加した後、それが以前は正常に機能していた理由です。

コードを抽出するのが難しく、以前は Jtree コードが正常に動作していましたが、一部のコンポーネントが含まれているウィジェットをブロックして、それ自体を非同期に更新している可能性があります。

いくつかのコードを含めるように更新を編集します。Nickが提供するTempクラスを使用しています:-

    public BasicGraphEditor(String appTitle, mxGraphComponent component)
{
    // Stores and updates the frame title
    this.appTitle = appTitle;

    // Stores a reference to the graph and creates the command history
    graphComponent = component;
    final mxGraph graph = graphComponent.getGraph();
    undoManager = createUndoManager();

    // Do not change the scale and translation after files have been loaded
    graph.setResetViewOnRootChange(false);

    // Updates the modified flag if the graph model changes
    graph.getModel().addListener(mxEvent.CHANGE, changeTracker);

    // Adds the command history to the model and view
    graph.getModel().addListener(mxEvent.UNDO, undoHandler);
    graph.getView().addListener(mxEvent.UNDO, undoHandler);

    // Keeps the selection in sync with the command history
    mxIEventListener undoHandler = new mxIEventListener()
    {
        @Override
        public void invoke(Object source, mxEventObject evt)
        {
            List<mxUndoableChange> changes = ((mxUndoableEdit) evt
                    .getProperty("edit")).getChanges();
            graph.setSelectionCells(graph
                    .getSelectionCellsForChanges(changes));
        }
    };

    undoManager.addListener(mxEvent.UNDO, undoHandler);
    undoManager.addListener(mxEvent.REDO, undoHandler);

    // Creates the graph outline component
    graphOutline = new mxGraphOutline(graphComponent);

    // Creates the library pane that contains the tabs with the palettes
    libraryPane = new JTabbedPane();

            /////////////////////////////////////////////////
            // Only change i have done here: start
            ////////////////////////////////////////////////
    Temp tempExplorer = new Temp();

    libraryPane.add("new Explorere", tempExplorer);

            /////////////////////////////////////////////////
            // Only change i have done here: End
            ////////////////////////////////////////////////

    // Creates the inner split pane that contains the library with the
    // palettes and the graph outline on the left side of the window
    JSplitPane inner = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            libraryPane, graphOutline);
    inner.setDividerLocation(320);
    inner.setResizeWeight(1);
    inner.setDividerSize(6);
    inner.setBorder(null);

    // Creates the outer split pane that contains the inner split pane and
    // the graph component on the right side of the window
    JSplitPane outer = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inner,
            graphComponent);
    outer.setOneTouchExpandable(true);
    outer.setDividerLocation(200);
    outer.setDividerSize(6);
    outer.setBorder(null);

    // Creates the status bar
    statusBar = createStatusBar();

    // Display some useful information about repaint events
    installRepaintListener();

    // Puts everything together
    setLayout(new BorderLayout());
    add(outer, BorderLayout.CENTER);
    add(statusBar, BorderLayout.SOUTH);
    installToolBar();

    // Installs rubberband selection and handling for some special
    // keystrokes such as F2, Control-C, -V, X, A etc.
    installHandlers();
    installListeners();
    updateTitle();
}

上記のクラスは、https: //github.com/jgraph/jgraphx として Jgraph ライブラリから のもので、上記のように jtree コンポーネントを追加するだけで、他の変更はありません。助けてください。

4

1 に答える 1

2

明示的に記述されていない限り、Swing はスレッドセーフではありません。JTree の JavaDocsでは、これはスレッドセーフではないと明示的に述べています。EDT 以外のスレッドで更新した場合、何も機能しないという保証はありません。SwingUtilities.invokeLater(Runnable run);したがって、別のスレッドから JTree を更新する場合は、EDT にリクエストを送信するためにを使用する必要があります。

JTree の情報を格納するためのデータ構造を持ち、(データ ストレージではなく) ユーザー インタラクションにのみ JTree を使用することをお勧めします。

編集

SwingUtilities.invokeLater()コンポーネント モデル内で JTree を更新するために使用する例を次に示します。あなたがコードを投稿しなくても、これは私が作業しなければならない最高のものです. これを使用して問題を再現してみてください (問題が何であるかを絞り込むまで、コードの一部をこの例に追加してください)。

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class Temp extends JPanel{
    JTree tree = new JTree();

    public Temp(){
        JScrollPane jsp = new JScrollPane(tree);

        // Creates the library pane that contains the tabs with the palettes
        JTabbedPane libraryPane = new JTabbedPane();

        libraryPane.add("new Explorere", jsp);

        // Creates the inner split pane that contains the library with the
        // palettes and the graph outline on the left side of the window
        JSplitPane inner = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                libraryPane, new JPanel());
        inner.setDividerLocation(320);
        inner.setResizeWeight(1);
        inner.setDividerSize(6);
        inner.setBorder(null);

        // Creates the outer split pane that contains the inner split pane and
        // the graph component on the right side of the window
        JSplitPane outer = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inner,
                new JPanel());
        outer.setOneTouchExpandable(true);
        outer.setDividerLocation(200);
        outer.setDividerSize(6);
        outer.setBorder(null);

        // Puts everything together
        setLayout(new BorderLayout());
        add(outer, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        final Temp temp = new Temp();
        SwingUtilities.invokeLater(new Runnable(){

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(temp);
                frame.pack();
                frame.setVisible(true);
            }});

        Thread updater = new Thread(temp.new CustomThread());
        updater.start();
    }

    public class CustomThread implements Runnable{

        @Override
        public void run() {
            for(int i = 0; i < 1000; i++){
                updateTree("New Item "+ i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        public void updateTree(final String nodeToAdd){
            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {
                    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
                    DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
                    DefaultMutableTreeNode child = new DefaultMutableTreeNode(nodeToAdd);
                    model.insertNodeInto(child, root,root.getChildCount());
                    tree.scrollPathToVisible(new TreePath(child.getPath()));
                }});

        }

    }
}
于 2012-12-20T16:04:08.973 に答える