java - Swing - JTable 单元格以不同颜色突出显示

标签 java swing jtable

我有一个带有搜索按钮的文本框,如果我单击搜索文本,字符串会在 JTable 单元格中突出显示,如果搜索文本具有多个以逗号分隔的字符串,则所有这些逗号分隔的字符串必须以不同的颜色显示动态地。

您能否建议我需要对以下工作代码进行哪些更改(单个字符串突出显示)

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.DefaultHighlighter;
import java.awt.*;

public class TableExample {
    JFrame f;
    private JTextField textField; 

    TableExample() {
        f = new JFrame();
        String data[][] = {{"101", "lala", "670000"}, {"101", "lala", "670000"}, {"102", "Jai", "780000"},
                {"101", "Sachin", "700000"}};
        String column[] = {"ID", "NAME", "SALARY"};
        JTable jt = new JTable();
        jt.setBounds(30, 40, 200, 300);
        JScrollPane sp = new JScrollPane(jt); 

        DefaultTableModel dtm = new DefaultTableModel(data, column); 
        dtm.setColumnIdentifiers(column);
        jt.setModel(dtm);

        JPanel inputpanel = new JPanel();
        inputpanel.setLayout(new BoxLayout(inputpanel, BoxLayout.LINE_AXIS));

        textField = new JTextField();
        JButton button = new JButton("Highlight");

        button.addActionListener(e -> { 
            jt.repaint();
        });

        inputpanel.add(textField);
        inputpanel.add(button);
        jt.setDefaultRenderer(Object.class, new CellHighlightRenderer()); 

        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, inputpanel, sp);

        f.add(splitPane);
        f.setSize(300, 400);
    }
    class CellHighlightRenderer extends JTextField implements TableCellRenderer {
        public DefaultHighlighter high = new DefaultHighlighter();
        public DefaultHighlighter.DefaultHighlightPainter highlight_painter = new DefaultHighlighter.DefaultHighlightPainter(
                Color.YELLOW);

        public CellHighlightRenderer() {
            setBorder(BorderFactory.createEmptyBorder());
            setHighlighter(high);
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                                                       int row, int column) {

            setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
            setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());

            setFont(table.getFont());
            setValue(value);
            int pos = 0;
            String pattern = textField.getText(); // Grab the text.
            if (pattern != null && pattern.trim().length() > 0)
                while ((pos = value.toString().indexOf(pattern, pos)) >= 0) {
                    try {
                        high.addHighlight(pos, pos + pattern.length(), highlight_painter);
                        pos += pattern.length();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            return this;
        }

        protected void setValue(Object value) {
            setText((value == null) ? "" : value.toString());
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->{
            TableExample te = new TableExample();
            te.f.setVisible(true); 
        });

    }
}

最佳答案

我已经按照你的要求做了。阅读代码中的推荐。每当您看到评论时,请尝试将其与您的代码进行比较。我不知道你想要什么颜色,所以我对每个单词使用了随机颜色。

预览:

enter image description here

package test;

import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.DefaultHighlighter;

public class TableExample {
    JFrame f;
    private JTextField textField; // make the textfield a field so u can grab its text whenever u need it (in our
                                    // case in renderer)
    private HashMap<String, Color> words = new HashMap<>();

    TableExample() {
        f = new JFrame();
        // I changed the data a bit for my tests, take care of that.
        String data[][] = { { "101", "lala", "670000" }, { "101", "lala", "670000" }, { "102", "Jai", "780000" },
                { "101", "Sachin", "700000" } };
        String column[] = { "ID", "NAME", "SALARY" };
        JTable jt = new JTable();
        jt.setBounds(30, 40, 200, 300);
        JScrollPane sp = new JScrollPane(jt); // You were not adding the sp into your panel, take care that next time.

        DefaultTableModel dtm = new DefaultTableModel(data, column); // Create the model with our data.
        dtm.setColumnIdentifiers(column);
        jt.setModel(dtm);

        JPanel inputpanel = new JPanel();
        inputpanel.setLayout(new BoxLayout(inputpanel, BoxLayout.LINE_AXIS));

        textField = new JTextField();
        JButton button = new JButton("Highlight");

        button.addActionListener(e -> { // Button should only repaint the table (a.k.a read the renderer again).
            words.clear(); //Clear the map with the words
            String text = textField.getText(); // Grab the text.
            if (text.trim().length() > 0) {
                String[] splitPattern = text.split(","); //Split the words
                for (String s : splitPattern) {
                    words.put(s, getARandomColor()); //Put each word with a RANDOM color.
                }
            }
            jt.repaint();// Changing the table's renderer is bad on every button click, and no needed.
        });

        inputpanel.add(textField);
        inputpanel.add(button);
        jt.setDefaultRenderer(Object.class, new CellHighlightRenderer()); // Add the renderer only 1 time.

        // I add sp here, not the table (if you want your table to actually have a
        // scrollpane)
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, inputpanel, sp);

        f.add(splitPane);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Hopefully you didnt forget this.
        f.setSize(300, 400);
        f.pack(); // Use pack() to the frame between set it visible.
        // f.setVisible(true); //setVisible to constructor is bad idea. I suggest you to
        // avoid that, and show your frame after its initiation.
    }

    class CellHighlightRenderer extends JTextField implements TableCellRenderer {
        public DefaultHighlighter high = new DefaultHighlighter();
        public DefaultHighlighter.DefaultHighlightPainter highlight_painter = new DefaultHighlighter.DefaultHighlightPainter(
                Color.YELLOW);

        public CellHighlightRenderer() {
            setBorder(BorderFactory.createEmptyBorder());
            setHighlighter(high);
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {

            setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
            setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());

            setFont(table.getFont());
            setValue(value);
            int pos = 0;

            if (words.size() > 0) {
                for (String word : words.keySet()) {
                    while ((pos = value.toString().indexOf(word, pos)) >= 0) {
                        try {
                            highlight_painter = new DefaultHighlighter.DefaultHighlightPainter(words.get(word));
                            // high.addHighlight(first, last, highlight_painter);
                            high.addHighlight(pos, pos + word.length(), highlight_painter);
                            pos += word.length();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return this;
        }

        protected void setValue(Object value) {
            setText((value == null) ? "" : value.toString());
        }
    }

    private Color getARandomColor() {
        return new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
    }

    public static void main(String[] args) {
        /* *******THIS IS VERY IMPORTANT******* */
        /* All swing applications should run in their own thread, named EDT */
        SwingUtilities.invokeLater(() -> {
            TableExample te = new TableExample();
            te.f.setVisible(true); // Here, make it visisble
        });

    }
}

关于java - Swing - JTable 单元格以不同颜色突出显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50251816/

相关文章:

java - 使 JTable 单元格编辑器值可选择,但不可编辑?

java - 如何为在 Apache POI 演示文稿中创建的 XSLF 形状设置渐变填充?

java - DefaultTtableModel 上的单选按钮

java - 使用 Xstream 定义 XML 结构

java - 如何在复选框中输入值

java - JProgressBar不会更新

java - Netbeans 历史记录显示有 100 个更改,但我只做了几个。我该如何避免这种情况?

java - 如何让jtable成为jtree的一个节点

java - 使用 Java 从 SharePoint 列表中删除文件

java - H2 数据库仅在文件中不能在内存中工作