Swing/Scrollspy の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/Scrollspy へ行く。
- Swing/Scrollspy の差分を削除
--- category: swing folder: Scrollspy title: JEditorPaneのスクロールに連動してJTreeのノードを選択する tags: [JEditorPane, JTree, JScrollPane, HTMLDocument, Html] author: aterai pubdate: 2020-01-13T03:43:21+09:00 description: JEditorPaneのスクロールに連動して表示状態になったリンクと同名のJTreeノードを検索・選択します。 image: https://drive.google.com/uc?id=1WPiIXVEn_n8seXVfgwCByMIWUPocOwmF hreflang: href: https://java-swing-tips.blogspot.com/2020/01/automatically-update-jtree-node.html lang: en --- * 概要 [#summary] `JEditorPane`のスクロールに連動して表示状態になったリンクと同名の`JTree`ノードを検索・選択します。 #download(https://drive.google.com/uc?id=1WPiIXVEn_n8seXVfgwCByMIWUPocOwmF) * サンプルコード [#sourcecode] #code(link){{ JScrollPane scroll = new JScrollPane(editor); scroll.getVerticalScrollBar().getModel().addChangeListener(e -> { HTMLDocument.Iterator itr = doc.getIterator(HTML.Tag.A); for (; itr.isValid(); itr.next()) { try { Rectangle r = editor.modelToView(itr.getStartOffset()); if (r != null && editor.getVisibleRect().contains(r.getLocation())) { searchTreeNode(tree, itr.getAttributes().getAttribute(HTML.Attribute.NAME)); break; } } catch (BadLocationException ex) { UIManager.getLookAndFeel().provideErrorFeedback(editor); } } }); }} * 解説 [#explanation] 上記のサンプルでは、`JEditorPane`を配置した`JScrollPane`の縦`ScrollBar`に`ChangeListener`を設定し、表示状態になったリンクと同名の`JTree`ノードを検索して選択します。 - リンクが表示されているかは`HTMLDocument#getIterator(HTML.Tag.A)`で取得した`<a>`タグの先頭位置が`JEditorPane#getVisibleRect()`で取得した表示範囲に含まれるかで判断 - リンクが表示されているかは`HTMLDocument#getIterator(HTML.Tag.A)`で取得した`<a>`タグの先頭位置が`JEditorPane#getVisibleRect()`で取得した表示範囲に含まれるかで判断する - `JTree`側にはノードをマウスクリックなどで選択したら`JEditorPane#scrollToReference(ref)`でそのリンクまでスクロールする`TreeSelectionListener`を追加しているので、`JEditorPane`側からのノード選択を実行する場合はその`TreeSelectionListener`が反応しないよう設定する必要がある #code{{ tree.addTreeSelectionListener(e -> { if (!tree.isEnabled()) { // JEditorPane側からのノード選択は無視する return; } Object o = e.getNewLeadSelectionPath().getLastPathComponent(); if (o instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) o; String ref = Objects.toString(node.getUserObject()); editor.scrollToReference(ref); } }); // ... private static void searchTreeNode(JTree tree, Object name) { TreeModel model = tree.getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); Collections.list((Enumeration<?>) root.preorderEnumeration()).stream() .filter(DefaultMutableTreeNode.class::isInstance) .map(DefaultMutableTreeNode.class::cast) .filter(node -> Objects.equals(name, Objects.toString(node.getUserObject()))) .findFirst() .ifPresent(node -> { tree.setEnabled(false); // JTreeに設定したTreeSelectionListenerを無効にする TreePath path = new TreePath(node.getPath()); tree.setSelectionPath(path); tree.scrollPathToVisible(path); tree.setEnabled(true); // JTreeに設定したTreeSelectionListenerを有効に戻す }); } }} * 参考リンク [#reference] - [[JEditorPane内のリンク参照位置までスクロールする>Swing/ScrollToReference]] * コメント [#comment] #comment #comment