Home > database >  Can`t dynamic refresh JTable
Can`t dynamic refresh JTable

Time:06-25

First of all i'm new with Java. I make an Gui with 4 pannels (MainProgram).

image

In centerPanel is JTable which shows data from database. In topPanel i put button that open new class / window - (ADD CUSTUMER) with some input fields. After click save button data is saved into database, and dispose(). The data is saved correctly into database. The question is how to refresh table in MainProgram after saving? Thanks in advance.

There is some code:

MainProgram.java

    public class MainProgram extends JFrame {
    Connection connection = MysqlConnect.dbConnector();

    private static final long serialVersionUID = 1L;

    public JPanel contentPane;
    public String selectedRowIndex;

    
    Object[][] data;
    String columns[];

    public JPanel centerPanel;

    public JScrollPane  pane;

    private JTable table;

    

    public MainProgram() throws IOException {

        setTitle("Main Program");
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        setBounds(100, 100, 1086, 501);
        setLocationRelativeTo(null);

        // setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);

        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));
        addWindowListener((WindowListener) new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent we) {
                String ObjButtons[] = { "Yes", "No" };
                int PromptResult = JOptionPane.showOptionDialog(null, "Are you sure you want to exit?", "SkladModule",
                        JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, ObjButtons, ObjButtons[1]);
                if (PromptResult == 0) {
                    System.exit(0);
                }
            }
        });

        // left panel
        JPanel leftPanel = new JPanel();
        contentPane.add(leftPanel, BorderLayout.WEST);

        // center panel
        centerPanel = new JPanel(new GridLayout());
        centerPanel.setBorder(new TitledBorder(
                new EtchedBorder(EtchedBorder.LOWERED, new Color(255, 255, 255), new Color(160, 160, 160)), "INFO",
                TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        contentPane.add(centerPanel, BorderLayout.CENTER);

        try {
            int count = 0;
            String query = "SELECT * FROM vehicles";
            String queryRow = "select count(*) from vehicles";

            Statement stm = connection.createStatement();

            ResultSet rows = stm.executeQuery(queryRow);

            if (rows.next()) {
                count = rows.getInt(1);
                rows.close();
            }

            ResultSet res = stm.executeQuery(query);

            // client_id, plate, make, model, year, engine_cc, color, vehicle_owner,
            // vehicle_owner_contact, mechanic, in_garage, service_start, service_end,
            // service_cost, parts_cost, service_paid, notes
            columns = new String[] { "ID", "Plate", "Make", "Model", "Year", "Engine", "Color", "Owner", "Owner Tel.",
                    "In Garage", "Service Paid", "Notes" };
            data = new Object[count][12];
            int i = 0;
            while (res.next()) {
                int id = res.getInt("client_id");

                data[i][0] = id   "";
                data[i][1] = res.getString("plate");
                data[i][2] = res.getString("make");
                data[i][3] = res.getString("model");
                data[i][4] = res.getString("year");
                data[i][5] = res.getString("engine_cc");
                data[i][6] = res.getString("color");
                data[i][7] = res.getString("vehicle_owner");
                data[i][8] = res.getString("vehicle_owner_contact");
                data[i][9] = res.getString("in_garage");
                data[i][10] = res.getString("service_paid");
                data[i][11] = res.getString("notes");

                i  ;
            }
            table = new JTable();
            TableModel model = new DefaultTableModel(data, columns);

            table.setModel(model);

            // JTable table = new JTable(data, columns);

            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            final TableColumnModel columnModel = table.getColumnModel();
            for (int column = 0; column < table.getColumnCount(); column  ) {
                int width = 15; // Min width
                for (int row = 0; row < table.getRowCount(); row  ) {
                    TableCellRenderer renderer = table.getCellRenderer(row, column);
                    Component comp = table.prepareRenderer(renderer, row, column);
                    width = Math.max(comp.getPreferredSize().width   10, width);
                }
                width = Math.max(width, table.getColumnModel().getColumn(column).getPreferredWidth());
                if (width > 300)

                    width = 300;
                columnModel.getColumn(column).setPreferredWidth(width);
            }

            table.setFocusable(false);
            table.setRowSelectionAllowed(true);

            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            table.setDefaultEditor(Object.class, null);
            table.setShowGrid(true);
            table.setShowVerticalLines(true);
            pane = new JScrollPane(table);
            centerPanel.add(pane);

            table.addMouseListener(new MouseListener() {
                public void mouseReleased(MouseEvent e) {
                }

                public void mousePressed(MouseEvent e) {

                    selectedRowIndex = table.getModel().getValueAt(table.getSelectedRow(), 0).toString();

                }

                public void mouseExited(MouseEvent e) {
                }

                public void mouseEntered(MouseEvent e) {
                }

                public void mouseClicked(MouseEvent e) {
                }
            });

            JButton btnNewButton = new JButton("New button");
            btnNewButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {

                    if (selectedRowIndex != null) {

                        int rowID = Integer.parseInt(selectedRowIndex);

                        System.out.println(rowID);

                    } else {

                        JOptionPane.showMessageDialog(null, "Please select row!", "No selected vehicle",
                                JOptionPane.INFORMATION_MESSAGE);
                    }

                }
            });
            leftPanel.add(btnNewButton);

        } catch (SQLException e) {
            e.printStackTrace();
        }

        // bottom panel
        // create the status bar panel and shove it down the bottom of the frame
        JPanel statusPanel = new JPanel();
        statusPanel.setBorder((Border) new BevelBorder(BevelBorder.LOWERED));
        contentPane.add(statusPanel, BorderLayout.SOUTH);
        statusPanel.setPreferredSize(new Dimension(contentPane.getWidth(), 20));
        statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
        JLabel statusLabel = new JLabel("");
        statusLabel.setHorizontalAlignment(SwingConstants.LEFT);
        statusPanel.add(statusLabel);
        contentPane.setVisible(true);

        // add username from login to statusbar
        String username = Login.uname;

        statusLabel.setText("Logged user: "   username);

        JPanel topPanel = new JPanel();
        contentPane.add(topPanel, BorderLayout.NORTH);

        BufferedImage buttonIcon = ImageIO
                .read(new File("C:\\Users\\User\\eclipse-workspace\\SkladModule\\images\\plus.png"));
        JButton btnAddCustumer = new JButton(new ImageIcon(buttonIcon));
        btnAddCustumer.setText("ADD");
        // btnAddCustumer.setBorder(null);
        btnAddCustumer.setContentAreaFilled(false);
        btnAddCustumer.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                AddCustumer addCustumer;
                try {
                    addCustumer = new AddCustumer();
                    addCustumer.setVisible(true);
                } catch (IOException e1) {

                    e1.printStackTrace();
                }

            }
        });

        topPanel.add(btnAddCustumer);

        JButton btnNewButton_1 = new JButton("New button");
        topPanel.add(btnNewButton_1);

    }

    public void refresh() {
        TableModel model =new DefaultTableModel(data, columns);
        model.insertRow(res.getRow() - 1, row);
        model.addRow(row);
    }
    
    

}

AddCustumer.java

public class AddCustumer extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTextField plateField;
    private JTextField makeField;
    private JTextField modelField;
    private JTextField yearField;
    private JTextField engineField;
    private JTextField colorField;
    private JTextField ownerField;
    private JTextField ownerPhoneField;

    Connection connection = null;

    public AddCustumer() throws IOException {
        setResizable(false);
        setType(Type.POPUP);
        setTitle("ADD CUSTUMER");
        setBounds(100, 100, 700, 300);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout(0, 0));
        addWindowListener((WindowListener) new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent we) {
                String ObjButtons[] = { "Yes", "No" };
                int PromptResult = JOptionPane.showOptionDialog(null, "Are you sure you want to exit?", "SkladModule",
                        JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, ObjButtons, ObjButtons[1]);
                if (PromptResult == 0) {
                    dispose();
                }
            }
        });
        JPanel leftPanel = new JPanel();
        leftPanel.setBorder(BorderFactory.createTitledBorder(" CAR INFO "));
        getContentPane().add(leftPanel, BorderLayout.WEST);
        leftPanel.setLayout(new MigLayout("", "[left][][grow,left]", "[][][][][][][][][]"));
        JLabel lblPlate = new JLabel("Plate: *");
        leftPanel.add(lblPlate, "cell 0 1,alignx trailing");

        plateField = new JTextField();
        leftPanel.add(plateField, "cell 2 1,growx");
        plateField.setColumns(10);

        JLabel lblMake = new JLabel("Make: *");
        leftPanel.add(lblMake, "cell 0 2,alignx trailing");

        makeField = new JTextField();
        leftPanel.add(makeField, "cell 2 2,growx");
        makeField.setColumns(10);

        JLabel lblModel = new JLabel("Model: *");
        leftPanel.add(lblModel, "cell 0 3,alignx trailing");

        modelField = new JTextField();
        leftPanel.add(modelField, "cell 2 3,growx");
        modelField.setColumns(10);

        JLabel lblYear = new JLabel("Year: *");
        leftPanel.add(lblYear, "cell 0 4,alignx trailing");

        yearField = new JTextField();
        leftPanel.add(yearField, "cell 2 4,growx");
        yearField.setColumns(10);

        JLabel lblEngCC = new JLabel("Engine size (cc): *");
        leftPanel.add(lblEngCC, "cell 0 5,alignx trailing");

        engineField = new JTextField();
        leftPanel.add(engineField, "cell 2 5,growx");
        engineField.setColumns(10);

        JLabel lblColor = new JLabel("Color: *");
        leftPanel.add(lblColor, "cell 0 6,alignx trailing");

        colorField = new JTextField();
        leftPanel.add(colorField, "cell 2 6,growx");
        colorField.setColumns(10);

        JLabel lblNewLabel = new JLabel("*  Required fields");
        leftPanel.add(lblNewLabel, "cell 2 8");

        JPanel rightPanel = new JPanel();
        rightPanel.setBorder(BorderFactory.createTitledBorder(" CLIENT INFO "));
        getContentPane().add(rightPanel, BorderLayout.CENTER);
        rightPanel.setLayout(new MigLayout("", "[100px:n,trailing][250px:300px:500,trailing]", "[][][][][grow]"));

        JLabel lblOwnerName = new JLabel("Car owner names: *");
        rightPanel.add(lblOwnerName, "cell 0 1,alignx trailing");

        ownerField = new JTextField();
        rightPanel.add(ownerField, "cell 1 1,growx");
        ownerField.setColumns(10);

        JLabel lblOwnerPhone = new JLabel("Car owner telephone: *");
        rightPanel.add(lblOwnerPhone, "cell 0 2,alignx trailing");

        ownerPhoneField = new JTextField();
        rightPanel.add(ownerPhoneField, "cell 1 2,growx");
        ownerPhoneField.setColumns(10);

        JLabel lblNotes = new JLabel("Notes: ");
        rightPanel.add(lblNotes, "cell 0 3,alignx trailing,aligny top");

        JTextArea notesField = new JTextArea(16, 58);
        notesField.setWrapStyleWord(true);
        notesField.setLineWrap(true);
        notesField.setBorder(BorderFactory.createLineBorder(Color.lightGray));
        JScrollPane scrollNotes = new JScrollPane(notesField);
        scrollNotes.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        rightPanel.add(scrollNotes, "cell 1 3,grow");

        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        getContentPane().add(bottomPanel, BorderLayout.SOUTH);

        BufferedImage saveButtonIcon = ImageIO
                .read(new File("C:\\Users\\User\\eclipse-workspace\\SkladModule\\images\\accept.png"));
        JButton save_btn = new JButton(new ImageIcon(saveButtonIcon));
        save_btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                /*
                 * if (plateField.getText().isBlank() || makeField.getText().isBlank() ||
                 * modelField.getText().isBlank() || yearField.getText().isBlank() ||
                 * engineField.getText().isBlank() || colorField.getText().isBlank() ||
                 * ownerField.getText().isBlank() || ownerPhoneField.getText().isBlank()) {
                 * 
                 * JOptionPane.showMessageDialog(null, "* required fields incomplete. Please
                 * review and resubmit", "Incomplete data", JOptionPane.WARNING_MESSAGE);
                 * 
                 * } else {
                 */

                connection = MysqlConnect.dbConnector();

                try {

                    String query = "INSERT INTO vehicles (plate, make, model, year, engine_cc, color, vehicle_owner, vehicle_owner_contact, notes) VALUES ('"
                              plateField.getText()   "','"   makeField.getText()   "','"   modelField.getText()   "','"
                              yearField.getText()   "','"   engineField.getText()   "','"   colorField.getText()   "','"
                              ownerField.getText()   "','"   ownerPhoneField.getText()   "','"   notesField.getText()
                              "')";

                    PreparedStatement pst = connection.prepareStatement(query);
                    pst.executeUpdate(query);
                    MainProgram main = new MainProgram();
                    main.refresh();
                    JOptionPane.showMessageDialog(null, "Data was saved", "SUCCESS", JOptionPane.INFORMATION_MESSAGE);
                    dispose();
                    

                } catch (Exception e1) {
                    JOptionPane.showMessageDialog(null, "SQLException: "   e1.getMessage(), "ERROR",
                            JOptionPane.ERROR_MESSAGE);

                }

                /* } */

            }
        });
        save_btn.setText("SAVE");
        save_btn.setBorder(null);
        save_btn.setContentAreaFilled(true);
        save_btn.setToolTipText("SAVE");
        bottomPanel.add(save_btn);

        Component horizontalStrut = Box.createHorizontalStrut(25);
        bottomPanel.add(horizontalStrut);

        BufferedImage cancelButtonIcon = ImageIO
                .read(new File("C:\\Users\\User\\eclipse-workspace\\SkladModule\\images\\remove.png"));
        JButton cancel_btn = new JButton(new ImageIcon(cancelButtonIcon));
        cancel_btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        cancel_btn.setText("CANCEL");
        cancel_btn.setBorder(null);
        cancel_btn.setContentAreaFilled(false);
        cancel_btn.setToolTipText("CANCEL");
        cancel_btn.setHorizontalAlignment(SwingConstants.RIGHT);
        bottomPanel.add(cancel_btn);

        Component horizontalStrut_1 = Box.createHorizontalStrut(20);
        bottomPanel.add(horizontalStrut_1);

    }

}

CodePudding user response:

There are a number of ways you might achieve this, but they all basically boil down to the same thing, a modal dialog. See How to Make Dialogs for more details.

You should avoid extending from top level containers like JFrame (and JDialog). You're not adding any new functionality to the class and are locking yourself into a single use case.

The following examples are intended to show how you ask users for input by using modal dialogs. Through same "black magic", when you show a modal dialog, the code execution will stop while the dialog is visible and resume when it's closed (don't ask, I don't care, it just works).

This means you can present a dialog and then wait till it's closed and then carry on making what ever decisions you need to.

You could...

Make use JOptionPane, which is neat and handy API for making, well, dialogs.

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.AbstractTableModel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class Person {
        private long id;
        private String firstName;
        private String lastName;

        public Person(long id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public long getId() {
            return id;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 37 * hash   (int) (this.id ^ (this.id >>> 32));
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Person other = (Person) obj;
            if (this.id != other.id) {
                return false;
            }
            return true;
        }

    }

    public class PersonPane extends JPanel {
        private Person person;

        private JTextField firstName;
        private JTextField lastName;

        public PersonPane(Person person) {
            this();
            this.person = person;

            if (person == null) {
                return;
            }
            firstName.setText(person.getFirstName());
            lastName.setText(person.getLastName());
        }

        public PersonPane() {
            firstName = new JTextField(10);
            lastName = new JTextField(10);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.LINE_END;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(new JLabel("First name: "), gbc);
            gbc.gridy  ;
            add(new JLabel("Last name: "), gbc);

            gbc.gridx  ;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.LINE_START;

            add(firstName, gbc);
            gbc.gridy  ;
            add(lastName, gbc);
        }

        public Person save() {
            if (person == null) {
                return new Person(System.currentTimeMillis(), firstName.getText(), lastName.getText());
            }
            long id = person.getId();
            return new Person(id, firstName.getText(), lastName.getText());
        }
    }

    public class PersonTableModel extends AbstractTableModel {

        private List<Person> people = new ArrayList<>();
        private List<String> columNames = new ArrayList<>(Arrays.asList(new String[]{"First name", "Last name"}));

        public PersonTableModel() {
        }

        @Override
        public int getRowCount() {
            return people.size();
        }

        @Override
        public int getColumnCount() {
            return columNames.size();
        }

        @Override
        public String getColumnName(int column) {
            return columNames.get(column);
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Person person = people.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return person.getFirstName();
                case 1:
                    return person.getLastName();
            }
            return null;
        }

        public void addOrUpdate(Person person) {
            int index = people.indexOf(person);
            if (index >= 0) {
                people.set(index, person);
                fireTableRowsUpdated(index, index);
            } else {
                int lastIndex = people.size();
                people.add(person);
                fireTableRowsInserted(lastIndex, lastIndex);
            }
        }

        public Person getPersonAtRow(int row) {
            return people.get(row);
        }

    }

    public class MainPane extends JPanel {

        private PersonTableModel model = new PersonTableModel();

        public MainPane() {
            setLayout(new BorderLayout());

            JButton newPersonButton = new JButton("New");
            newPersonButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    PersonPane personPane = new PersonPane();
                    int option = JOptionPane.showConfirmDialog(MainPane.this, personPane, "New Person", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
                    if (option == JOptionPane.OK_OPTION) {
                        Person person = personPane.save();
                        if (person != null) {
                            model.addOrUpdate(person);
                        }
                    }
                }
            });

            JToolBar toolBar = new JToolBar();
            toolBar.add(newPersonButton);

            JTable table = new JTable(model);
            table.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        int rowIndex = table.convertRowIndexToModel(table.getSelectedRow());
                        Person person = model.getPersonAtRow(rowIndex);
                        PersonPane personPane = new PersonPane(person);
                        int option = JOptionPane.showConfirmDialog(MainPane.this, personPane, "Edit Person", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
                        if (option == JOptionPane.OK_OPTION) {
                            person = personPane.save();
                            if (person != null) {
                                model.addOrUpdate(person);
                            }
                        }
                    }
                }
            });

            add(toolBar, BorderLayout.NORTH);
            add(new JScrollPane(table));
        }
    }
}

You could...

If you need something more flexible or want to more detailed validation, you could roll your own dialog (and validation workflows), but you should have a look at Disable ok button on JOptionPane.dialog until user gives an input, which demonstrates a means by which you could control the enabled state of the buttons and still make use of a JOptionPane.

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.AbstractTableModel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class Person {
        private long id;
        private String firstName;
        private String lastName;

        public Person(long id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public long getId() {
            return id;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 37 * hash   (int) (this.id ^ (this.id >>> 32));
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Person other = (Person) obj;
            if (this.id != other.id) {
                return false;
            }
            return true;
        }

    }

    public static class PersonPane extends JPanel {
        public interface ValidationObserver {
            public void validStateDidChange(PersonPane source, boolean isValid);
        }

        private Person person;

        private JTextField firstName;
        private JTextField lastName;

        private List<ValidationObserver> validationObservers = new ArrayList<>(8);

        public PersonPane(Person person) {
            this();
            this.person = person;

            if (person == null) {
                return;
            }
            firstName.setText(person.getFirstName());
            lastName.setText(person.getLastName());
        }

        public PersonPane() {
            firstName = new JTextField(10);
            lastName = new JTextField(10);

            DocumentListener documentListener = new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    validateForm();
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    validateForm();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    validateForm();
                }
            };

            firstName.getDocument().addDocumentListener(documentListener);
            lastName.getDocument().addDocumentListener(documentListener);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.LINE_END;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(new JLabel("First name: "), gbc);
            gbc.gridy  ;
            add(new JLabel("Last name: "), gbc);

            gbc.gridx  ;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.LINE_START;

            add(firstName, gbc);
            gbc.gridy  ;
            add(lastName, gbc);
        }

        public void addValidationObserver(ValidationObserver observer) {
            validationObservers.add(observer);
        }

        public void removeValidationObserver(ValidationObserver observer) {
            validationObservers.remove(observer);
        }

        protected void fireValidateStateDidChange(boolean isValid) {
            for (ValidationObserver observer : validationObservers) {
                observer.validStateDidChange(this, isValid);
            }
        }

        protected void validateForm() {
            boolean isValid = !firstName.getText().isBlank() && !lastName.getText().isBlank();
            fireValidateStateDidChange(isValid);
        }

        public Person save() {
            if (person == null) {
                return new Person(System.currentTimeMillis(), firstName.getText(), lastName.getText());
            }
            long id = person.getId();
            return new Person(id, firstName.getText(), lastName.getText());
        }

        public static Person createPerson(Component parent) {
            return editPerson(parent, null);
        }

        public static Person editPerson(Component parent, Person person) {
            enum State {
                OKAY, CANCEL
            }

            JPanel actionPane = new JPanel(new GridBagLayout());
            JButton okayButton = new JButton("Okay");
            okayButton.setEnabled(false);
            JButton cancelButton = new JButton("Cancel");

            actionPane.add(okayButton);
            actionPane.add(cancelButton);

            PersonPane personPane = new PersonPane(person);
            personPane.addValidationObserver(new ValidationObserver() {
                @Override
                public void validStateDidChange(PersonPane source, boolean isValid) {
                    okayButton.setEnabled(isValid);
                }
            });

            JDialog dialog = new JDialog(SwingUtilities.windowForComponent(parent));
            dialog.setModal(true);
            dialog.add(personPane);
            dialog.add(actionPane, BorderLayout.SOUTH);

            okayButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    personPane.putClientProperty("state", State.OKAY);
                    dialog.dispose();
                }
            });
            cancelButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    personPane.putClientProperty("state", State.CANCEL);
                    dialog.dispose();
                }
            });

            dialog.pack();
            dialog.setLocationRelativeTo(parent);
            dialog.setVisible(true);

            Object stateValue = personPane.getClientProperty("state");
            if (stateValue instanceof State) {
                State state = (State) stateValue;
                if (state == State.OKAY) {
                    return personPane.save();
                }
            }

            return null;
        }
    }

    public class PersonTableModel extends AbstractTableModel {

        private List<Person> people = new ArrayList<>();
        private List<String> columNames = new ArrayList<>(Arrays.asList(new String[]{"First name", "Last name"}));

        public PersonTableModel() {
        }

        @Override
        public int getRowCount() {
            return people.size();
        }

        @Override
        public int getColumnCount() {
            return columNames.size();
        }

        @Override
        public String getColumnName(int column) {
            return columNames.get(column);
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Person person = people.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return person.getFirstName();
                case 1:
                    return person.getLastName();
            }
            return null;
        }

        public void addOrUpdate(Person person) {
            int index = people.indexOf(person);
            if (index >= 0) {
                people.set(index, person);
                fireTableRowsUpdated(index, index);
            } else {
                int lastIndex = people.size();
                people.add(person);
                fireTableRowsInserted(lastIndex, lastIndex);
            }
        }

        public Person getPersonAtRow(int row) {
            return people.get(row);
        }

    }

    public class MainPane extends JPanel {

        private PersonTableModel model = new PersonTableModel();

        public MainPane() {
            setLayout(new BorderLayout());

            JButton newPersonButton = new JButton("New");
            newPersonButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Person person = PersonPane.createPerson(MainPane.this);
                    if (person != null) {
                        model.addOrUpdate(person);
                    }
                }
            });

            JToolBar toolBar = new JToolBar();
            toolBar.add(newPersonButton);

            JTable table = new JTable(model);
            table.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        int rowIndex = table.convertRowIndexToModel(table.getSelectedRow());
                        Person person = model.getPersonAtRow(rowIndex);
                        person = PersonPane.editPerson(MainPane.this, person);
                        if (person != null) {
                            model.addOrUpdate(person);
                        }
                    }
                }
            });

            add(toolBar, BorderLayout.NORTH);
            add(new JScrollPane(table));
        }
    }
}
  • Related