0

Below is a system i'm setting up to track the amount of panels added to an arraylist, and delete those panels when no longer needed. Bascially the portion I need help with is using both the Item/Actionlistener of the JButton and JCheckBox together. I've managed to store dynamically created rowpanels that contains textfield and checkboxes in the arraylist, but applying it to either itemlistener or actionlistener is slightly confusing. I want the delete button to only delete the checked checkboxes, but since the checkitem variable is out of its scope I get a null pointer exception. I feel if I can find a way around this which I believe is passing a local variable as a argument, I feel my delete button would work. Also I am aware that the rowPanel being a global variable is another factor throwing all my references off, but removing it, and making it local I end up with the same issue with my delete button. My Itemlistener works because I wanted to ensure it could track which checkboxes are checked and print out the size of the array. However another question I have is do I have to choose which specific listener to use as I've read I can't combine the two methods into eachother?

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

public class UI extends JFrame implements ItemListener {

    JPanel mainPanel, infoPanel, txtFldNames, txtFlds, bttn, checkBox, rowPanel;
    JTextField name, checkOutDate, checkInDate, email;
    JButton add, delete;
    JLabel label1, label2, label3, label4, label5;
    JScrollPane scrollBar;
    ArrayList<Component> checkBoxArrLst = new ArrayList<Component>();

    public UI() {

        txtFldNames = new JPanel(new GridLayout(1, 4, 5, 5));
        label1 = new JLabel("Name", SwingConstants.CENTER);
        label2 = new JLabel("Check Out Date", SwingConstants.CENTER);
        label3 = new JLabel("Check In Date", SwingConstants.CENTER);
        label4 = new JLabel("Email", SwingConstants.CENTER);
        label5 = new JLabel("", SwingConstants.CENTER); // empty label used as a
                                                        // place holder for the
                                                        // checkbox
        txtFldNames.add(label1);
        txtFldNames.add(label2);
        txtFldNames.add(label3);
        txtFldNames.add(label4);
        txtFldNames.add(label5);

        add = new JButton("Add");
        add.addActionListener(e -> {
            JPanel rowPanel = new JPanel(new GridLayout(1, 4, 5, 5));
            JCheckBox checkItem = new JCheckBox();
            checkItem.addItemListener(this);
            for (int i = 0; i < 4; i++) {
                rowPanel.add(new JTextField());
            }
            for (int l = 0; l < 1; l++) {
                rowPanel.add(checkItem, BorderLayout.EAST);
            }
            checkBoxArrLst.add(rowPanel);
            infoPanel.add(rowPanel);
            infoPanel.revalidate();
            infoPanel.repaint();
        });

        delete = new JButton("Delete");
        delete.addActionListener(e -> {
            Component[] components = rowPanel.getComponents();
            for (Component c : components) {
                if (c instanceof JCheckBox) {
                    JCheckBox checkItem = (JCheckBox) c;
                    if (((JCheckBox) c).isSelected()) {
                        infoPanel.remove(checkItem);
                    }
                }
            }

            infoPanel.revalidate();
            infoPanel.repaint();

        });

        bttn = new JPanel(new FlowLayout(FlowLayout.CENTER));
        bttn.add(add);
        bttn.add(delete);

        name = new JTextField();
        checkOutDate = new JTextField();
        checkInDate = new JTextField();
        email = new JTextField();

        name.setColumns(20);
        checkOutDate.setColumns(20);
        checkInDate.setColumns(20);
        email.setColumns(20);

        txtFlds = new JPanel(new GridLayout(1, 4, 5, 5));

        infoPanel = new JPanel(new GridLayout(0, 1, 2, 2));
        infoPanel.add(txtFldNames);
        infoPanel.add(txtFlds);

        mainPanel = new JPanel(new BorderLayout(5, 5));
        mainPanel.add(infoPanel, BorderLayout.PAGE_START);
        scrollBar = new JScrollPane(mainPanel);
        scrollBar.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        setTitle("Form 48 Tracker");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(1000, 400));
        this.add(scrollBar, BorderLayout.CENTER);
        this.add(bttn, BorderLayout.PAGE_END);
        this.pack();
        setLocationRelativeTo(null);
        setVisible(true);

    }

    public void itemStateChanged(ItemEvent checkItem) {
        if (checkItem.getStateChange() == ItemEvent.SELECTED) {
            System.out.println(checkBoxArrLst.size());
        }
        infoPanel.revalidate();
        infoPanel.repaint();
    }

    public static void main(String[] args) {

        new UI();

    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    Looks like you want to use a JTable, since you appear to be trying to duplicate its functionality. – Hovercraft Full Of Eels Dec 31 '17 at 19:53
  • And your current problem is not so much a scope issue but rather stems from ***shadowing*** the rowPanel variable (you re-declare it) causing the NPE to be thrown. Don't do this. – Hovercraft Full Of Eels Dec 31 '17 at 19:54
  • Also, don't use an ItemListener at all, and don't listen for the checkbox to be checked. Instead check the state of all the checkboxes from within the ActionListener attached to the delete button. You only care about the state of the checkboxes when delete has been pressed, so that's when you must check it. – Hovercraft Full Of Eels Dec 31 '17 at 19:56
  • @HovercraftFullOfEels Hey and thanks for your replys, the issue wasn't the NPE itself, but from what you said about checking the state of the checkboxes, am I atleast on the right track using and arraylist to store the created panels? – Squirtle_Squad Dec 31 '17 at 21:57
  • Again, if this were my project, I'd use a JTable and DefaultTableModel, but if you have to do things as you're doing them, then a row of your table structure should be represented by a new instance of a separate class, one that extends or creates a JPanel, one that has a public method that allows you to query the state of the JCheckBox that it contains. And yes, you could create an ArrayList of these items, but then would need to take care to synchronize the state of the list and the state of the GUI. – Hovercraft Full Of Eels Dec 31 '17 at 22:00

0 Answers0