如何保持搜索结果中的一个NetBeans摆动大纲(树状图)一致它被排序之后?

问题描述 投票:0回答:1

我试图实现搜索与所有匹配搜索的谷歌铬样型以黄色突出显示和当前的匹配橙色高亮显示,并有可能与转移输入或向后+ Enter键向前导航。我使用Swing组件是Netbeans的摇摆大纲基本上看起来像一个JTree表。它的工作原理,直到轮廓通过单击任何列进行排序。在这个例子中,只有一个列。

为了使我们所需要的轮廓罐子从位于这里的Netbeans的分配这个例子中工作的NetBeans \平台\模块\为org-netbeans-摆动outline.jar。另一种选择是把这个摇篮构建文件(的build.gradle)在摇篮项目的根目录:

plugins {
    id 'java-library'
}

dependencies {
    compile 'uk.gov.nationalarchives.thirdparty.netbeans:org-netbeans-swing-outline:7.2'
}

repositories {
    mavenCentral()
}

树模型有把搜索到列表的搜索功能findNodesWithPattern:

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;

public class TestTreeModel extends DefaultTreeModel {

    private static final long serialVersionUID = 1L;

    public TestTreeModel() {
        super(buildModel());
    }

    private static TreeNode buildModel() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("");
        for (int i = 0; i < 3; i++) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode("test" + i);
            for (int j = 0; j < 3; j++) {
                node.add(new DefaultMutableTreeNode("subtest" + j));
            }
            root.add(node);
        }
        return root;
    }

    @Override
    public DefaultMutableTreeNode getRoot() {
        return (DefaultMutableTreeNode) super.getRoot();
    }

    public List<TreeNode> findNodesMatchingPattern(Pattern pattern) {
        List<TreeNode> matchingNodes = new ArrayList<>();
        findNodesWithpattern(matchingNodes, getRoot(), pattern);
        return matchingNodes;
    }

    private void findNodesWithpattern(List<TreeNode> matchingNodes, TreeNode node, Pattern pattern) {
        if (pattern.matcher(node.toString()).find()) {
            matchingNodes.add(node);
        }
        Enumeration<DefaultMutableTreeNode> children = node.children();
        while (children.hasMoreElements()) {
            findNodesWithpattern(matchingNodes, children.nextElement(), pattern);
        }
    }

}

还有,其定义了一个名为值一列与所述对象的哈希码的行模型(用于演示目的只)

import org.netbeans.swing.outline.RowModel;

public class TestRowModel implements RowModel {
    @Override
    public Class getColumnClass(int column) {
        return Integer.class;
    }

    @Override
    public int getColumnCount() {
        return 1;
    }

    @Override
    public String getColumnName(int column) {
        return "Value";
    }

    @Override
    public Object getValueFor(Object node, int column) {
        return node.hashCode();
    }

    @Override
    public boolean isCellEditable(Object node, int column) {
        return false;
    }

    @Override
    public void setValueFor(Object node, int column, Object value) {
        // do nothing for now
    }
}

渲染它负责在黄色或橙色突出:

import java.awt.Color;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

import org.netbeans.swing.outline.RenderDataProvider;

public class TestRenderData implements RenderDataProvider {

    private String searchPattern;
    private TreeNode currentMatch;

    @Override
    public java.awt.Color getBackground(Object o) {
        return null;
    }

    @Override
    public String getDisplayName(Object o) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) o;
        if (searchPattern == null || searchPattern.length() == 0) {
            return node.toString();
        }
        try {
            Pattern pattern = Pattern.compile("(" + searchPattern + ")");
            Matcher matcher = pattern.matcher(node.toString());
            Color bgColor = Color.YELLOW;
            if (matcher.find()) {
                if (node == currentMatch) {
                    bgColor = Color.ORANGE;
                }
            }
            String bgHexColor = Integer.toHexString(bgColor.getRGB() & 0xffffff);
            String replacement = matcher.replaceAll("<span style=\"background-color: #" + bgHexColor + "\">$1</span>");
            return "<html>" + replacement + "</html>";
        } catch (PatternSyntaxException e) {
            return node.toString();
        }
    }

    @Override
    public java.awt.Color getForeground(Object o) {
        return null;
    }

    @Override
    public javax.swing.Icon getIcon(Object o) {
        return null;
    }

    @Override
    public String getTooltipText(Object o) {
        return null;
    }

    @Override
    public boolean isHtmlDisplayName(Object o) {
        return false;
    }

    public void setSearchPattern(String searchPattern) {
        this.searchPattern = searchPattern;
    }

    public void setCurrentMatch(TreeNode currentMatch) {
        this.currentMatch = currentMatch;
    }
}

主类构建具有快速过滤(非匹配的节点被过滤掉),并且触发搜索按键侦听轮廓。当回车键被输入,它增加一个计数器(nthMatch)和指数nthMatch在橙渲染highited当前匹配。

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.netbeans.swing.etable.QuickFilter;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.netbeans.swing.outline.OutlineModel;

public class MainFrame extends JFrame {
    private static final long serialVersionUID = 1L;

    public MainFrame() {
        TestTreeModel treeMdl = new TestTreeModel();
        OutlineModel mdl = DefaultOutlineModel.createOutlineModel(treeMdl, new TestRowModel(), true, "Test");
        Outline outline = new Outline();
        TestRenderData renderData = new TestRenderData();
        outline.setRenderDataProvider(renderData);
        outline.setRootVisible(false);
        outline.setModel(mdl);
        JScrollPane jScrollPane1 = new JScrollPane(outline);
        jScrollPane1.setViewportView(outline);
        JMenuBar mb = new JMenuBar();
        JLabel searchPatternLabel = new JLabel("  Search :  ");
        mb.add(searchPatternLabel);
        JTextField searchPatternTextField = new JTextField();
        searchPatternLabel.setLabelFor(searchPatternTextField);
        outline.setQuickFilter(0, new QuickFilter() {

            @Override
            public boolean accept(Object aValue) {
                if (searchPatternTextField.getText() == null || searchPatternTextField.getText().length() == 0) {
                    return true;
                }
                if (aValue instanceof DefaultMutableTreeNode) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) aValue;
                    Enumeration<DefaultMutableTreeNode> children = node.children();
                    while (children.hasMoreElements()) {
                        DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
                        if (accept(child)) {
                            return true;
                        }
                    }
                    try {
                        Pattern searchPattern = Pattern.compile(searchPatternTextField.getText());
                        return searchPattern.matcher(node.toString()).find();
                    } catch (PatternSyntaxException ex) {
                        return true;
                    }
                }
                return false;
            }
        });
        mb.add(searchPatternTextField);
        setJMenuBar(mb);
        getContentPane().add(jScrollPane1);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        searchPatternTextField.addKeyListener(new KeyAdapter() {

            private int nthMatch = 0;

            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    if (e.isShiftDown()) {
                        nthMatch--;
                    } else {
                        nthMatch++;
                    }
                }
                try {
                    Pattern searchPattern = Pattern.compile(searchPatternTextField.getText());
                    List<TreeNode> matchingNodes = treeMdl.findNodesMatchingPattern(searchPattern);
                    if (matchingNodes.size() > 0) {
                        if (nthMatch >= matchingNodes.size()) {
                            nthMatch = 0;
                        }
                        if (nthMatch < 0) {
                            nthMatch = 0;
                        }
                        TreeNode matchingNode = matchingNodes.get(nthMatch);
                        renderData.setCurrentMatch(matchingNode);
                        TreePath matchingNodePath = new TreePath(((DefaultMutableTreeNode) matchingNode).getPath());
                        outline.expandPath(matchingNodePath);
                        outline.scrollRectToVisible(outline.getPathBounds(matchingNodePath));
                        renderData.setSearchPattern(searchPatternTextField.getText());
                    }
                } catch (PatternSyntaxException ex) {

                }
                //outline.repaint();
                treeMdl.nodeChanged(treeMdl.getRoot());
            }

        });

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainFrame();
            }
        });

    }
}

作为一个基本的情况下,我找“测试”反复按Enter键。搜索结果的顺序乱了,只要点击排序列。有迹象表明,似乎做一个索引映射和2种继承的方法convertRowIndexToModel和convertRowIndexToView大纲,但我不知道如何使用它们。

java swing netbeans
1个回答
1
投票

每当搜索领域的变化,只是告知新的搜索模式的渲染器。这将需要亮点,在黄色 - 为 - 您 - 类型部分护理:

searchPatternTextField.getDocument().addDocumentListener(new DocumentListener() {

    @Override
    public void removeUpdate(DocumentEvent e) {
        renderData.setSearchPattern(searchPatternTextField.getText());
        treeMdl.nodeChanged(treeMdl.getRoot());
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        renderData.setSearchPattern(searchPatternTextField.getText());
        treeMdl.nodeChanged(treeMdl.getRoot());
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        renderData.setSearchPattern(searchPatternTextField.getText());
        treeMdl.nodeChanged(treeMdl.getRoot());
    }
});

然后监听输入和Shift +回车键。只是查找在视图先前,当前和下一个匹配的节点:

searchPatternTextField.addKeyListener(new KeyAdapter() {

    private void showMatchingNode(TreeNode node) {
        renderData.setCurrentMatch(node);
        TreePath matchingNodePath = new TreePath(((DefaultMutableTreeNode) node).getPath());
        outline.expandPath(matchingNodePath);
        outline.scrollRectToVisible(outline.getPathBounds(matchingNodePath));
    }

    public TreeNode findNextMatchingNode(boolean lookForPrevious) {
        try {
            Pattern searchPattern = Pattern.compile(searchPatternTextField.getText());
            boolean currentMatchFound = false;
            TreeNode previousMatch = null;
            for (int i = 0; i < outline.getRowCount(); i++) {
                TreeNode node = (TreeNode) outline.getValueAt(i, 0);
                if (node == renderData.getCurrentMatch()) {
                    currentMatchFound = true;
                    if (previousMatch != null && lookForPrevious) {
                        return previousMatch;
                    }
                } else if (searchPattern.matcher(node.toString()).find()) {
                    if (renderData.getCurrentMatch() == null || (currentMatchFound && !lookForPrevious)) {
                        return node;
                    }
                    previousMatch = node;
                }
            }
        } catch (PatternSyntaxException ex) {

        }
        return null;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            TreeNode node = findNextMatchingNode(e.isShiftDown());
            if (node != null) {
                showMatchingNode(node);
            }
            treeMdl.nodeChanged(treeMdl.getRoot());
        }
    }

});
© www.soinside.com 2019 - 2024. All rights reserved.