user2019594
user2019594

Reputation: 353

Java Swing repaint issue

I'm trying to repaint a panel but it won't work. Basically my panel takes in an ArrayList and then for each element in the ArrayList, it prints it out. When I click on a button, it removes that respective element of the ArrayList and then calls for the entire panel to repaint itself. I expect it after the repaint to show the same panel but without that politician but clicking the button does nothing. It does affect the message though so clearly the politician is being removed from the list but it is not being removed from the JPanel.

class fakeMPTable extends JPanel //table using Grid Layout
        {
            public void refresh()
            {
                revalidate();
                repaint();
            }

            public fakeMPTable()
            {
                setLayout(new GridBagLayout());
                GridBagConstraints c = new GridBagConstraints();
                c.fill = GridBagConstraints.HORIZONTAL;

                for (int i=0; i<politicians.size();i++)
                {
                    final int j=i;
                    JLabel politician = new JLabel(politicians.get(j));
                    JButton delete = new JButton();
                    delete.addActionListener(new 
                            ActionListener()
                    {
                        public void actionPerformed(ActionEvent e)
                        {
                            int selectedOption = JOptionPane.showConfirmDialog(null, 
                                    "Are you sure you want to delete \'" + politicians.get(j)+"\'?",
                                    "Warning", 
                                    JOptionPane.YES_NO_OPTION); 
                            if (selectedOption==0)
                            {
                                politicians.remove(j);
                                refresh();
                            }
                        }
                    }
                    c.gridy++;
                    add(delete, c);
                    add(politician,c);
             }

Upvotes: 1

Views: 616

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347334

Basically, you are not removing the components associated with the select politician.

You have a couple of possible solutions.

You Could

Create a seperate List for the labels and buttons, where each item match the same item in the politicians list.

This would mean that when you access the n politician, you could access the associated label and button using the same index...

class FakeMPTable extends JPanel //table using Grid Layout
{

    private List<String> politicians;
    private List<JLabel> labels;
    private List<JButton> buttons;

    public void refresh() {
        revalidate();
        repaint();
    }

    public FakeMPTable() {

        politicians = new ArrayList<>(25);
        for (int index = 0; index < 26; index++) {
            politicians.add(Character.toString((char) ('A' + index)));
        }

        labels = new ArrayList<>(25);
        buttons = new ArrayList<>(25);

        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;

        for (int i = 0; i < politicians.size(); i++) {
            final int j = i;
            JLabel politician = new JLabel(politicians.get(j));
            JButton delete = new JButton();
            labels.add(politician);
            buttons.add(delete);
            delete.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    int selectedOption = JOptionPane.showConfirmDialog(null,
                            "Are you sure you want to delete \'" + politicians.get(j) + "\'?",
                            "Warning",
                            JOptionPane.YES_NO_OPTION);
                    if (selectedOption == 0) {
                        politicians.remove(j);
                        remove(labels.remove(j));
                        remove(buttons.remove(j));
                        refresh();
                    }
                }
            });
            c.gridy++;
            add(delete, c);
            add(politician, c);
        }
    }
}

This has problems in the fact that it is to easy for the list to become unsynced, meaning that the indexes no longer match up...

You Could

Map each button and label to a politician...

class FakeMPTable extends JPanel //table using Grid Layout
{

    private List<String> politicians;
    private Map<String, JLabel> labels;
    private Map<String, JButton> buttons;

    public void refresh() {
        revalidate();
        repaint();
    }

    public FakeMPTable() {

        politicians = new ArrayList<>(25);
        for (int index = 0; index < 26; index++) {
            politicians.add(Character.toString((char) ('A' + index)));
        }

        labels = new HashMap<>(25);
        buttons = new HashMap<>(25);

        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;

        for (int i = 0; i < politicians.size(); i++) {
            final int j = i;
            JLabel politician = new JLabel(politicians.get(j));
            JButton delete = new JButton();
            labels.put(politicians.get(j), politician);
            buttons.put(politicians.get(j), delete);
            delete.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    int selectedOption = JOptionPane.showConfirmDialog(null,
                            "Are you sure you want to delete \'" + politicians.get(j) + "\'?",
                            "Warning",
                            JOptionPane.YES_NO_OPTION);
                    if (selectedOption == 0) {
                        String key = politicians.remove(j);
                        remove(labels.remove(key));
                        remove(buttons.remove(key));
                        refresh();
                    }
                }
            });
            c.gridy++;
            add(delete, c);
            add(politician, c);
        }
    }
}

This is a slightly better solution as it maps the politician name directly to the buttons and labels, making it more difficult for the lists to become unsynced.

Upvotes: 1

Jack
Jack

Reputation: 133619

You need to alter the structure of the JPanel itself, otherwise you ask for revalidate() but nothing has changed.

You should factor out the part of code which adds the entries and button to the JPanel so that you can call it in the beginning and then in the ActionListener by first removing elements:

this.removeAll();
this.addEntriesAccordingtoList();
this.revalidate();

Upvotes: 3

Related Questions