Changing JList row color at runtime

后端 未结 3 1509
谎友^
谎友^ 2020-12-16 06:36

I am trying to change JList rows dynamically. I need change nth row colour, highlight it(n is unknown during compilation). I saw a lot of examples with custom ListCellRender

相关标签:
3条回答
  • 2020-12-16 06:39

    Based on ListDemo sample from SUN.

    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. For more correct implementation consider the other ideas proposed and consider using 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(); }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-16 06:41

    Simple, set a custom ListCellRenderer to your JList using:

    list.setCellRenderer(myListCellrenderer);
    

    Now inside the overridden method getListCellRendererComponent() do something like this:

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

    The above example assumed that your custom renderer overrid DefaultListCellRenderer

    0 讨论(0)
  • 2020-12-16 06:50

    Your custom ListCellRenderer, which implements the method getListCellRendererComponent, will have access to both the JList and the value that it is redering. This gives you a couple options for how to determine when to paint the nth row green:

    1. You could subclass JList and have the renderer ask it which color to use for the bg. The JList subclass could trigger a repaint when the business logic determines that it is time for the nth row to be green, and then start an Swing Timer to trigger a repaint returning the bg back to normal
    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. Again, you have the option of setting an Swing Timer to revert the state on the backing object.
    0 讨论(0)
提交回复
热议问题