简体   繁体   English

在运行时更改JList行颜色

[英]Changing JList row color at runtime

I am trying to change JList rows dynamically. 我试图动态更改JList行。 I need change nth row colour, highlight it(n is unknown during compilation). 我需要更改第n行的颜色,突出显示它(在编译过程中n是未知的)。 I saw a lot of examples with custom ListCellRenderer, but all were "static". 我看到了很多使用自定义ListCellRenderer的示例,但是所有示例都是“静态的”。

In other words I have JList with x rows. 换句话说,我的JList有x行。 During runtime my "business logic" detects nth row is important. 在运行时,我的“业务逻辑”检测到第n行很重要。 So I want make its background green, wait one second, and then make it white again. 因此,我想将其背景设置为绿色,等待一秒钟,然后再次将其设置为白色。 One more thing, don't wan change row selection. 还有一件事,不要更改行选择。

What is the best way to do so? 最好的方法是什么?

Simple, set a custom ListCellRenderer to your JList using: 很简单,使用以下方法将自定义ListCellRenderer设置为JList:

list.setCellRenderer(myListCellrenderer);

Now inside the overridden method getListCellRendererComponent() do something like this: 现在,在重写的方法getListCellRendererComponent()中,执行以下操作:

public Component getListCellRendererComponent(.....) {
    Component c = super.getListCellRendererComponent();
    c.setBackGround(Color.blue)
    return c;
}

The above example assumed that your custom renderer overrid DefaultListCellRenderer 上面的示例假设您的自定义渲染器覆盖了DefaultListCellRenderer

Based on ListDemo sample from SUN. 基于SUN的ListDemo样本。

If you enter some text in the textfield which isn't in the list and you hit highlight it gets added. 如果您在文本字段中输入的文本不在列表中,然后单击突出显示,则会添加该文本。

If the text is in the list and you hit highlight the entry in the list gets temporarily highlighted blue. 如果文本在列表中,并且您单击突出显示,则列表中的条目将暂时突出显示为蓝色。

Note the solution here with the match field is just for demo. 请注意,此处具有match字段的解决方案仅用于演示。 For more correct implementation consider the other ideas proposed and consider using javax.swing.Timer 为了更正确地实现,请考虑提出的其他想法,并考虑使用javax.swing.Timer

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class ListDemo extends JPanel {
    private JList list;
    private DefaultListModel listModel;
    public String match = null;

    private static final String hireString = "Highlight";
    private JTextField employeeName;

    public ListDemo() {
        super(new BorderLayout());

        listModel = new DefaultListModel();
        listModel.addElement("Test1");
        listModel.addElement("Test2");
        listModel.addElement("Test3");

        list = new JList(listModel);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setSelectedIndex(0);
        list.setVisibleRowCount(5);
        list.setCellRenderer(new MyListCellRenderer());
        JScrollPane listScrollPane = new JScrollPane(list);

        JButton hireButton = new JButton(hireString);
        HireListener hireListener = new HireListener(hireButton);
        hireButton.setActionCommand(hireString);
        hireButton.addActionListener(hireListener);
        hireButton.setEnabled(false);

        employeeName = new JTextField(10);
        employeeName.addActionListener(hireListener);
        employeeName.getDocument().addDocumentListener(hireListener);
        listModel.getElementAt(list.getSelectedIndex()).toString();

        JPanel buttonPane = new JPanel();
        buttonPane.setLayout(new BoxLayout(buttonPane,
                                           BoxLayout.LINE_AXIS));
        buttonPane.add(Box.createHorizontalStrut(5));
        buttonPane.add(employeeName);
        buttonPane.add(hireButton);
        buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

        add(listScrollPane, BorderLayout.CENTER);
        add(buttonPane, BorderLayout.PAGE_END);
    }
    class MyListCellRenderer extends JLabel implements ListCellRenderer {
        public MyListCellRenderer() {
            setOpaque(true);
        }
        public Component getListCellRendererComponent(JList paramlist, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            setText(value.toString());
            if (value.toString().equals(match)) {
                setBackground(Color.BLUE);
                SwingWorker worker = new SwingWorker() {
                    @Override
                    public Object doInBackground() {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) { /*Who cares*/ }
                        return null;
                    }
                    @Override
                    public void done() {
                        match = null;
                        list.repaint();
                    }
                };
                worker.execute();
            } else
                setBackground(Color.RED);
            return this;
        }
    }
    class HireListener implements ActionListener, DocumentListener {
        private boolean alreadyEnabled = false;
        private JButton button;
        public HireListener(JButton button) {
            this.button = button;
        }
        public void actionPerformed(ActionEvent e) {
            String name = employeeName.getText();
            if (listModel.contains(name)) {
                match = name;
                list.repaint();
                employeeName.requestFocusInWindow();
                employeeName.selectAll();
                return;
            }
            if (name.equals("")) {
                Toolkit.getDefaultToolkit().beep();
                employeeName.requestFocusInWindow();
                employeeName.selectAll();
                return;
            }
            int index = list.getSelectedIndex();
            if (index == -1)
                index = 0;
            else
                index++;
            listModel.insertElementAt(employeeName.getText(), index);
            employeeName.requestFocusInWindow();
            employeeName.setText("");
            list.setSelectedIndex(index);
            list.ensureIndexIsVisible(index);
        }
        public void insertUpdate(DocumentEvent e) {
            enableButton();
        }
        public void removeUpdate(DocumentEvent e) {
            handleEmptyTextField(e);
        }
        public void changedUpdate(DocumentEvent e) {
            if (!handleEmptyTextField(e))
                enableButton();
        }
        private void enableButton() {
            if (!alreadyEnabled)
                button.setEnabled(true);
        }
        private boolean handleEmptyTextField(DocumentEvent e) {
            if (e.getDocument().getLength() <= 0) {
                button.setEnabled(false);
                alreadyEnabled = false;
                return true;
            }
            return false;
        }
    }
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ListDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JComponent newContentPane = new ListDemo();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() { createAndShowGUI(); }
        });
    }
}

Your custom ListCellRenderer, which implements the method getListCellRendererComponent , will have access to both the JList and the value that it is redering. 您的自定义ListCellRenderer实现了getListCellRendererComponent方法,将可以访问JList及其要重载的值。 This gives you a couple options for how to determine when to paint the n th row green: 这为您提供了几个选项,用于确定何时将第n行涂成绿色:

  1. You could subclass JList and have the renderer ask it which color to use for the bg. 您可以JList并让渲染器询问它为bg使用哪种颜色。 The JList subclass could trigger a repaint when the business logic determines that it is time for the n th row to be green, and then start an Swing Timer to trigger a repaint returning the bg back to normal 当业务逻辑确定是第n行为绿色的时候, JList子类可以触发重新绘制,然后启动Swing Timer触发重新绘制以使bg恢复正常
  2. When the business logic determines when you should show the row as green, you also have the option of setting state on the backing object of the row, and test it for that state within getListCellRendererComponent , setting the bg green if the state is correct. 当业务逻辑确定何时将行显示为绿色时,您还可以选择在行的getListCellRendererComponent对象上设置状态,并在getListCellRendererComponent测试该状态是否为该状态,如果状态正确则将bg设置为绿色。 Again, you have the option of setting an Swing Timer to revert the state on the backing object. 同样,您可以选择设置Swing Timer以还原支持对象上的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM