Я реализовал свое дерево расширив JTree, в него добавил поиск по элементам дерева. При нажатии на клавишу показываю попап в котором текстовое поле, при вводе значений в который, проверяю есть ли в названии узлов(нод) слово начинающееся также, если есть устанавливаю выделение на этот узел(ноду).
Это все работает, вот только вопрос как при больших деревьях, прокручивать еще содержимое дерева, чтобы выделенный узел (нода) всегда была в поле видимости пользователя?
дерево реализовал вот так:
| Код | public class Tree extends JTree { private JPopupMenu searchPopup = new JPopupMenu(); // всплывающее меню private JTextField searchText = new JTextField(); // поле в который пользователь вводит текст для поиска private ArrayList<Node> matches = new ArrayList<Node>(); // список в котором я храню все узлы которые соответствуют поиску public Tree() { searchPopup.setLayout(new BorderLayout()); searchText.setColumns(5); searchPopup.add(new JLabel(" найти "), BorderLayout.WEST); searchPopup.add(searchText, BorderLayout.EAST); setComponentPopupMenu(searchPopup); initEvents(); //инициализация событий }
private void initEvents() { final JTree my = this; searchText.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e){search(e);} public void removeUpdate(DocumentEvent e){search(e);} public void changedUpdate(DocumentEvent e){search(e);} }); searchText.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { // выделяю узлы соответсвующие поиску при нажатии на клавыши вниз или вверх из текстового поля if (getSelectedNodes().length>0 && (KeyEvent.VK_DOWN == e.getKeyCode() || KeyEvent.VK_UP == e.getKeyCode())) { int i = matches.indexOf(getSelectedNodes()[0]); if(KeyEvent.VK_DOWN == e.getKeyCode())selectMatch(++i); // выделение следуещего else selectMatch(--i); // выделение предыдущего } } }); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { // если нажата клавиша символа на дереве показываю форму поиска if (Character.isLetter(e.getKeyChar())) { searchPopup.show(my, 90, 0); searchText.grabFocus(); } } }); } private void search(DocumentEvent e) { matches.clear(); // очищаю ранее найденные результаты search((Node)getModel().getRoot()); // начинаю поиск selectMatch(0); // выделяю первый найденный результат } private void search(Node parent) { for (int i=0; i<getModel().getChildCount(parent);i++) { Node child = (Node)getModel().getChild(parent, i); if (child.getLabel().getText().toLowerCase().startsWith(searchText.getText().toLowerCase())) // добавляю узел в список соответствующих поиску matches.add(child); if (child.getChildCount()>0) search(child); // рекурсия } } private void selectMatch(int index) { // если список найденных узлов не пуст и идекс соответствует размерности списка выделяю путь к этому узлу if (!matches.isEmpty() && index<matches.size() && index>=0) setSelectionPath(new TreePath(matches.get(index).getPath())); }
.... другие методы.... }
|
|