用搜索词过滤JTable而不丢失背景颜色
Posted
技术标签:
【中文标题】用搜索词过滤JTable而不丢失背景颜色【英文标题】:Filter JTable with search word without losing background color 【发布时间】:2018-04-19 18:31:46 【问题描述】:我已按照教程过滤和突出显示 JTable here 中的文本。
我唯一添加的是 LookAndFeel,它设置为 Nimbus。该代码有效,除了当我选择一行时,该行的背景颜色和前景颜色都丢失了。
没有渲染器:
使用渲染器:
在代码中,渲染器创建了一个新标签(LabelHighlighted extends JLabel),它覆盖了 painComponent 方法。我猜想这个方法应该采用表格中行的背景颜色。
@Override
protected void paintComponent(Graphics g)
if (rectangles.size() > 0)
Graphics2D g2d = (Graphics2D) g;
Color c = g2d.getColor();
for (Rectangle2D rectangle : rectangles)
g2d.setColor(colorHighlight);
g2d.fill(rectangle);
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(rectangle);
g2d.setColor(c);
super.paintComponent(g);
注意:我知道 JTable 的 JXTable 变体有更多用于过滤和突出显示行的选项,但我还没有找到解决方案...
渲染器:
public class RendererHighlighted extends DefaultTableCellRenderer
private JTextField searchField;
public RendererHighlighted(JTextField searchField)
this.searchField = searchField;
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean selected, boolean hasFocus,
int row, int column)
Component c = super.getTableCellRendererComponent(table, value, selected, hasFocus, row, column);
JLabel original = (JLabel) c;
LabelHighlighted label = new LabelHighlighted();
label.setFont(original.getFont());
label.setText(original.getText());
label.setBackground(original.getForeground());
label.setForeground(original.getForeground());
label.setHorizontalTextPosition(original.getHorizontalTextPosition());
label.highlightText(searchField.getText());
return label;
标签突出显示:
public class LabelHighlighted extends JLabel
private List<Rectangle2D> rectangles = new ArrayList<>();
private Color colorHighlight = Color.YELLOW;
public void reset()
rectangles.clear();
repaint();
public void highlightText(String textToHighlight)
if (textToHighlight == null)
return;
reset();
final String textToMatch = textToHighlight.toLowerCase().trim();
if (textToMatch.length() == 0)
return;
textToHighlight = textToHighlight.trim();
final String labelText = getText().toLowerCase();
if (labelText.contains(textToMatch))
FontMetrics fm = getFontMetrics(getFont());
float w = -1;
final float h = fm.getHeight() - 1;
int i = 0;
while (true)
i = labelText.indexOf(textToMatch, i);
if (i == -1)
break;
if (w == -1)
String matchingText = getText().substring(i,
i + textToHighlight.length());
w = fm.stringWidth(matchingText);
String preText = getText().substring(0, i);
float x = fm.stringWidth(preText);
rectangles.add(new Rectangle2D.Float(x, 1, w, h));
i = i + textToMatch.length();
repaint();
@Override
protected void paintComponent(Graphics g)
if (rectangles.size() > 0)
Graphics2D g2d = (Graphics2D) g;
Color c = g2d.getColor();
for (Rectangle2D rectangle : rectangles)
g2d.setColor(colorHighlight);
g2d.fill(rectangle);
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(rectangle);
g2d.setColor(c);
super.paintComponent(g);
【问题讨论】:
提供完整的Renderer
课程
我编辑了我的原始帖子并添加了渲染器和标签类。我的问题顶部只有一个链接的副本。
【参考方案1】:
对JLabel
使用html
标签可能很容易。
<span style='color:#000000; background-color:#FFFF00'>%s</span>
import java.awt.*;
import java.util.Objects;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
class RendererHighlighted extends DefaultTableCellRenderer
private final JTextField searchField;
public RendererHighlighted(JTextField searchField)
this.searchField = searchField;
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column)
String txt = Objects.toString(value, "");
String pattern = searchField.getText();
if (Objects.nonNull(pattern) && !pattern.isEmpty())
Matcher matcher = Pattern.compile(pattern).matcher(txt);
int pos = 0;
StringBuilder buf = new StringBuilder("<html>");
while (matcher.find(pos))
int start = matcher.start();
int end = matcher.end();
buf.append(String.format(
"%s<span style='color:#000000; background-color:#FFFF00'>%s</span>",
txt.substring(pos, start), txt.substring(start, end)));
pos = end;
buf.append(txt.substring(pos));
txt = buf.toString();
super.getTableCellRendererComponent(table, txt, isSelected, hasFocus, row, column);
return this;
public class HtmlHighlightCellTest
public JComponent makeUI()
String[] columnNames = "A", "B";
Object[][] data =
"aaa", "bbaacc", "bbb", "defg",
"ccccbbbbaaabbbbaaeabee", "xxx", "dddaaabbbbb", "ccbbaa",
"cc cc bbbb aaa bbbb e", "xxx", "ddd aaa b bbbb", "cc bbaa"
;
TableModel model = new DefaultTableModel(data, columnNames)
@Override public boolean isCellEditable(int row, int column)
return false;
@Override public Class<?> getColumnClass(int column)
return String.class;
;
JTable table = new JTable(model);
table.setFillsViewportHeight(true);
TableRowSorter<? extends TableModel> sorter = new TableRowSorter<>(model);
table.setRowSorter(sorter);
JTextField field = new JTextField();
RendererHighlighted renderer = new RendererHighlighted(field);
table.setDefaultRenderer(String.class, renderer);
field.getDocument().addDocumentListener(new DocumentListener()
@Override public void insertUpdate(DocumentEvent e)
update();
@Override public void removeUpdate(DocumentEvent e)
update();
@Override public void changedUpdate(DocumentEvent e)
private void update()
String pattern = field.getText().trim();
if (pattern.isEmpty())
sorter.setRowFilter(null);
else
sorter.setRowFilter(RowFilter.regexFilter("(?i)" + pattern));
);
JPanel sp = new JPanel(new BorderLayout(2, 2));
sp.add(new JLabel("regex pattern:"), BorderLayout.WEST);
sp.add(field);
sp.add(Box.createVerticalStrut(2), BorderLayout.SOUTH);
sp.setBorder(BorderFactory.createTitledBorder("Search"));
JPanel p = new JPanel(new BorderLayout(2, 2));
p.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
p.add(sp, BorderLayout.NORTH);
p.add(new JScrollPane(table));
return p;
public static void main(String[] args)
EventQueue.invokeLater(() ->
try
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
catch (Exception ex)
ex.printStackTrace();
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new HtmlHighlightCellTest().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
);
【讨论】:
以上是关于用搜索词过滤JTable而不丢失背景颜色的主要内容,如果未能解决你的问题,请参考以下文章