SorcerOK
SorcerOK

Reputation: 169

JTable not repainted after deleting a row

AdminFrame.java

package com.sorcerok;

import java.awt.Color;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;

public class AdminFrame extends JFrame {

    private JFrame frame;
    private JPanel panel;
    private JButton delete, change;
    private JTable usersTable;
    private static final int WIDTH = 510;
    private static final int HEIGHT = 300;
    private List<User> list;
    private MyTableModel model;

    public AdminFrame(JFrame frame) {
        super("Просмотр пользователей");
        setResizable(false);
        this.frame = frame;
        frame.setVisible(false);


        panel = new JPanel();
        frame.setResizable(false);
        panel.setLayout(null);

        delete = new JButton("Удалить");
        delete.setBounds(310, 230, 121, 30);
        change = new JButton("Изменить");
        change.setBounds(50, 230, 121, 30);


        list = new ArrayList<>(Authorisation.userMap.values());

        model = new MyTableModel(list);

        usersTable = new JTable(model);
        JTableHeader header = usersTable.getTableHeader();
        header.setForeground(Color.black);
        header.setFont(new Font("Times New Roman", Font.BOLD, 20));
        JScrollPane sp = new JScrollPane(usersTable);

        sp.setBounds(0, 0, 500, 90);

        panel.add(delete);
        panel.add(change);
        panel.add(sp);

        add(panel);
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public void dispose() {
        frame.setVisible(true);
        super.dispose();
    }

    public void deleteFromTable() {

        delete.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int row = usersTable.getSelectedRow();
                if (getSelectedUser(row) != null) {
                    Authorisation.userMap.remove(getSelectedUser(row).getName());
                    list.remove(getSelectedUser(row));
                    System.out.println(list);
                    Registration.writeToFile();

                    model.removeRow(row);
                }
            }
        });

    }

    public User getSelectedUser(int index) {
        index = usersTable.getSelectedRow();
        if (isSelectedUser(index)) {
            String name = (String) usersTable.getValueAt(index, 1);
            return getUser(name);
        } else {
            return null;
        }
    }

    public boolean isSelectedUser(int index) {
        if (index < 0) {
            return false;
        } else {
            return true;
        }
    }

    public User getUser(String name) {
        for (User u : list) {
            if (name.equals(u.getName())) {
                return u;
            }
        }
        return null;
    }

    public class MyTableModel extends AbstractTableModel {

        private List<User> list;

        private MyTableModel(List<User> list) {
            this.list = list;
        }

        public void addTableModelListener(TableModelListener listener) {
        }

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

        public int getColumnCount() {
            return 3;
        }

        public String getColumnName(int columnIndex) {

            switch (columnIndex) {
                case 0:
                    return "№";
                case 1:
                    return "Логин";
                case 2:
                    return "Пароль";
            }
            return "";
        }

        public int getRowCount() {
            return list.size();
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            User user = list.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return ++rowIndex;
                case 1:
                    return user.getName();
                case 2:
                    return user.getPassword();

            }
            return "";
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public void removeTableModelListener(TableModelListener listener) {
        }

        public void setValueAt(Object value, int rowIndex, int columnIndex) {
        }

        public void removeRow(int row) {

            fireTableRowsDeleted(row, row);
            fireTableStructureChanged();
            System.out.println("Deleted by AbstractTableModel Table Model");

        }
    }
}

And invoked method in other class

AdminFrame af = new AdminFrame(frame);
af.deleteFromTable();

When a lot of elements in the table and there is scrolling, that is, press to delete a row, the row immediately removed from Arralist but not removed from the table, and if you use to scroll, the record immediately disappears. Same functions without this method model.removeRow(row); What's wrang?

Upvotes: 1

Views: 1273

Answers (1)

Peter Walser
Peter Walser

Reputation: 15706

Your table model does not support TableModelListeners, that's why the table can't observe changes on the model.

Your TableModel is supposed to notify the TableModelListeners when it changes (when rows are added, removed or refreshed).
When setting the model on the table, the table will add a TableModelListener to observe the model. Once the model changes, it fires a TableModelEvent (by calling tableChanged(TableModelEvent) on all listeners). The JTable will then receive this notification and revalidate and repaint the table content to adapt to the changes.

In your concrete case: You've overridden the add|removeTableModelListener() methods, so no listeners can be registered. Just remove those two methods on your model, and let the DefaultTableModel's implementation of those methods handle it.

Upvotes: 2

Related Questions