gpt4 book ai didi

java - 排序后,如何在 Netbeans swing 大纲(树表)中保持搜索结果一致?

转载 作者:行者123 更新时间:2023-12-02 10:18:58 29 4
gpt4 key购买 nike

我尝试实现的搜索是类似 google-chrome 的搜索类型,所有匹配项均以黄色突出显示,当前匹配项以橙色突出显示,并且可以使用 Enter 向前导航或使用 Shift+Enter 向后导航。我使用的 Swing 组件是 Netbeans Swing Outline,它基本上看起来像 JTree 表。它一直有效,直到通过单击大纲的任何列对大纲进行排序为止。对于本示例,只有一列。

为了使这个示例正常工作,我们需要来自 Netbeans 发行版的大纲 jar,该文件位于 netbeans\platform\modules\org-netbeans-swing-outline.jar。另一种选择是将此 Gradle 构建文件 (build.gradle) 放置在 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);
}
}

}

还有一个行模型,它使用对象的哈希代码定义一个名为 Value 的列(仅用于演示目的)

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;
}
}

主类使用快速过滤器(不匹配的节点被过滤掉)和触发搜索的关键监听器构建大纲。当输入 Enter 键时,它会增加计数器 (nthMatch),并且索引 nthMatch 处的当前匹配项会被渲染器以橙色高亮显示。

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 反复查找“test”。每当单击某一列进行排序时,搜索结果的顺序就会困惑。Outline中有2个继承的方法convertRowIndexToModel和convertRowIndexToView似乎做了索引映射,但我不知道如何使用它们。

最佳答案

每当搜索字段发生变化时,只需通知渲染器新的搜索模式即可。这将处理键入时以黄色突出显示的部分:

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());
}
});

然后监听 Enter 和 Shift+Enter。只需在 View 中查找上一个、当前和下一个匹配节点:

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());
}
}

});

关于java - 排序后,如何在 Netbeans swing 大纲(树表)中保持搜索结果一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54476528/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com