Я пытаюсь динамически добавлять узлы в Java Swing JTree, и пользователь должен иметь возможность просматривать и сворачивать иерархию при постоянном добавлении узлов. Когда я добавляю Thread.sleep(10) в свой цикл, он работает нормально; но это грязный трюк ...
Вот урезанный код, который вызывает эту проблему. Всякий раз, когда я запускаю это и дважды щелкаю по корневому узлу, чтобы развернуть / свернуть его (пока узлы добавлены), я получаю ArrayIndexOutOfBoundsException. Когда я добавляю Thread.sleep(10), этого не происходит. Я предполагаю, что это проблема с потоками, но я понятия не имею, как это синхронизировать? Будем признательны за любые подсказки!
public static void main(String[] args) throws InterruptedException {
final JFrame frame = new JFrame();
frame.setSize(600, 800);
frame.setVisible(true);
MutableTreeNode root = new DefaultMutableTreeNode("root");
final DefaultTreeModel model = new DefaultTreeModel(root);
final JTree tree = new JTree(model);
frame.add(new JScrollPane(tree));
while (true) {
MutableTreeNode child = new DefaultMutableTreeNode("test");
model.insertNodeInto(child, root, root.getChildCount());
tree.expandRow(tree.getRowCount() - 1);
// uncommenting this to make it work
// Thread.sleep(10);
}
}
Я хочу использовать это для приложения для поиска при вводе текста, поэтому предоставление (почти) мгновенных результатов для меня важно.
Обновлено: Спасибо за быстрые ответы! SwingUtilities.invokeLater() решает проблему.
Я сейчас делаю это:
SwingUtilities.invokeLater();После 100 элементов я запускаю это, чтобы можно было обновить графический интерфейс:
// just wait so that all events in the queue can be processed
SwingUtilities.invokeAndWait(new Runnable() {
public void run() { };
});
Таким образом, у меня очень отзывчивый графический интерфейс, и он отлично работает. Спасибо!




Вы можете захотеть запустить команду tree.expandRow из события treeNodesInsertedTreeModelListener, чтобы она выполнялась только после обновления модели.
tree.expandRow необходимо выполнить в потоке событий, поэтому измените цикл следующим образом:
while (true)
{
MutableTreeNode child = new DefaultMutableTreeNode("test");
model.insertNodeInto(child, root, root.getChildCount());
final int rowToExpand = tree.getRowCount() - 1; // ? does this work ?
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
tree.expandRow(rowToExpand);
}
});
}
Пока вы это делаете, вам, вероятно, нужно убедиться, что любой список, который использует ваша древовидная модель, синхронизирован, чтобы вы не вставляли в коллекцию, пока дерево просматривается потоком рисования.
Разве вам не нужно продолжить и сохранить tree.getRowCount () - 1, учитывая, что, возможно, было вставлено 50 строк до того, как этот Runnable наконец запустится?
Swing враждебен потокам, поэтому выполняйте манипуляции с Swing в потоке AWT Event Diaptch Thread (EDT).
Бесконечный цикл - это ерунда, поэтому сложно придумать предложение. Лучший эквивалент, который я могу придумать, - это повторная публикация даже для повторного запуска кода. Поскольку в очереди событий есть определенные приоритеты, я не уверен, что даже это сработает.
public static void main(String[] args) throws InterruptedException {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
runEDT();
}});
}
private static void runEDT() {
assert java.awt.EventQueue.isDispatchThread();
final JFrame frame = new JFrame();
frame.setSize(600, 800);
frame.setVisible(true);
final MutableTreeNode root = new DefaultMutableTreeNode("root");
final DefaultTreeModel model = new DefaultTreeModel(root);
final JTree tree = new JTree(model);
frame.add(new JScrollPane(tree));
frame.validate();
new Runnable() { public void run() {
final MutableTreeNode child = new DefaultMutableTreeNode("test");
model.insertNodeInto(child, root, root.getChildCount());
tree.expandRow(tree.getRowCount() - 1);
final Runnable addNode = this; // Inner class confusion...
java.awt.EventQueue.invokeLater(addNode);
}}.run();
}
(Отказ от ответственности: не скомпилировано и не протестировано.)
Я только что пробовал это сейчас, но получаю точно такой же результат.