Обновление модели JTable не отображается во время фильтрации TableRowSorter

У меня есть JDialog для редактирования цвета, где пользователь может добавлять / удалять / редактировать цвет. Цвета отображаются в Jtable, который заполняется из БД. Пользовательский интерфейс содержит txtField, который позволяет выполнять фильтрацию благодаря TableRowSorter. Jtable использует defaultTableModel, и после того, как пользователь решит удалить строку, например, я делаю model.removeRow(tableau.getSelectedRow()), чтобы обновить модель.

Моя проблема заключается в следующем: когда пользователь не использует сортировщик и нажимает на удаление, все идет хорошо, и JTable немедленно обновляется для представления этого действия, то есть соответствующая строка удаляется из JTable, но когда он делает то же самое вещь с введенным фильтром (TableRowSorter выполняет свою фильтрацию), визуальная обратная связь в Jtable не происходит, то есть удаленная строка все еще видна.

1) Нет фильтрации: я выбираю строку с FooColor7

введите описание изображения здесь

2) Затем я нажимаю кнопку удаления: строка с FooColor7 удаляется, и JTable показывает это.

введите описание изображения здесь

Теперь "глючит" поведение:

3) Фильтрация по: я выбираю строку с FooColor3

введите описание изображения здесь

4) Затем я нажимаю кнопку удаления: нет изменений в пользовательском интерфейсе, даже если строка правильно удалена из БД...

введите описание изображения здесь

И вот что-то вроде SSCCE (вроде как потому, что не работает без зависимостей, которые здесь слишком долго помещать):

public class DialogEditColors extends JDialog implements ActionListener, KeyListener
{
 final TableRowSorter<TableModel> sorter;
 private JTable                table        = null;
 private DefaultTableModel     model        = null;
 private JPanel                panelBoutons = null;
 private JTextField            txtFieldSearch;
 private JLabel                lblTitle;
 private JButton               btnAdd   , btnDelete, btnEdit;
 private JButton               btnCancel, btnSave;
 private JScrollPane           scroller;
 private ColorDao              colorDao= new ColorDao(Share.connection);

 public DialogEditColors()
 {
  super();
  setSize(439, 313);
  setTitle("  Edition couleurs");
  getContentPane().setLayout(null);
  setModal(true);
  setResizable(false);
  setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  setLocationRelativeTo(null);

  btnSave = new JButton("Enregistrer");
  btnSave.setBounds(317, 247, 89, 26);
  btnSave.addActionListener(this);

  btnCancel = new JButton("Annuler");
  btnCancel.setBounds(214, 247, 89, 26);
  btnCancel.addActionListener(this);

  btnAdd = new JButton("");
  btnAdd.setBounds(new Rectangle(10, 8, 33, 26));
  btnAdd.addActionListener(this);

  btnDelete = new JButton("");
  btnDelete.setBounds(new Rectangle(53, 8, 33, 26));
  btnDelete.addActionListener(this);

  btnEdit = new JButton("");
  btnEdit.setBounds(new Rectangle(96, 8, 33, 26));
  btnEdit.addActionListener(this);

  panelBoutons = new JPanel();
  panelBoutons.setBorder(new LineBorder(Color.GRAY));
  panelBoutons.setBounds(27, 11, 378, 43);
  panelBoutons.setLayout(null);

  txtFieldSearch = new JTextField("", 10);
  txtFieldSearch.setBounds(193, 9, 175, 24);
  panelBoutons.add(txtFieldSearch);
  txtFieldSearch.addKeyListener(this);

  Object[][] data = new Object[colorDao.findAll().size()][2];
  String[] title = { "Couleur", "Description" };

  int i = 0;
  for (Couleur coul : colorDao.findAll())
   {
      data[i][0] = coul.getNom();
      data[i][1] = coul.getDescription();
      i++;
   }

  model = new DefaultTableModel(data, title);
  table = new JTable(model)
  {//THIS ALLOWS TO ALTERNATE THE BACKGROUND COLOR OF ROWS
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
    {
      Component returnComp = super.prepareRenderer(renderer, row, column);
      Color alternateColor = new Color(242, 242, 242);
      Color whiteColor = Color.WHITE;
      if ( !returnComp.getBackground().equals(getSelectionBackground()) )
      {
        Color bg = (row % 2 == 0 ? alternateColor : whiteColor);
        returnComp.setBackground(bg);
        bg = null;
      }
      return returnComp;
     };
   };

  table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  table.setCellSelectionEnabled(true);
  table.setColumnSelectionAllowed(true);
  sorter = new TableRowSorter<TableModel>(model);
  table.setRowSorter(sorter);

  scroller = new JScrollPane(table);
  scroller.setBounds(27, 65, 378, 171);
  addComponents();
  setVisible(true);
  }//END OF CONSTRUCTOR

  private void addComponents()
  {
   getContentPane().add(scroller);
   getContentPane().add(btnSave);
   getContentPane().add(btnCancel);
   panelBoutons.add(btnAdd);
   panelBoutons.add(btnDelete);
   panelBoutons.add(btnEdit);
   getContentPane().add(panelBoutons);
  }////END OF METHOD

  public void actionPerformed(ActionEvent e)
  {
   if ( e.getSource() == btnDelete )
   {
    if ( table.getSelectedRowCount() != 0 ) 
    {//THERE IS A CHOSEN ROW IN JTABLE
      String selectedColor = (table.getValueAt(table.getSelectedRow(),     table.getSelectedColumn())).toString();
      //TEST THE READONLY ATTRIBUTE OF THE COLOR
      if ( colorDao.findByNom(selectedColor).get(0).getReadOnly() == true )
      {//THE COLOR'S READONLY ATTRIBUTE IS TRUE
       JOptionPane.showMessageDialog(this, "This item is readOnly: impossible to delete it!");
      }
      else
      {//THE COLOR'S READONLY ATTRIBUTE IS FALSE
       int response = JOptionPane.showConfirmDialog(this, "Are you sure you
       want to delete this color?", "Confirmation", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);

       if ( response == 0 ) //CONFIRMED
       {//FIRST DELETE THE COLOR FROM DB
        colorDao.delete(colorDao.findByNom(selectedColor).get(0));
        //THEN REFRESH JTABLE TO TAKE DELETION INTO ACCOUNT
        model.removeRow(table.getSelectedRow());
        table.repaint();
       }
     }
    }
    else
    {//NO CHOSEN COLOR
      JOptionPane.showMessageDialog(this, "No chosen color!");
    }
   }

   else if ( e.getSource() == btnCancel )
   {
    this.dispose();
   }
  }//END OF METHOD

  public void keyReleased(KeyEvent e)
  {
   if ( e.getSource() == txtFieldSearch )
   {
     String text = txtFieldSearch.getText();
     if ( text.length() == 0 )
     {
      sorter.setRowFilter(null);
     }
     else
     {
      sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
     }
     ((AbstractTableModel) table.getModel()).fireTableDataChanged();
   }
  }//END OF METHOD
}////END OF CLASS

Любая идея?

1 ответ

Решение

model.removeRow(table.getSelectedRow()); table.repaint();

  1. нет необходимости перекрашивать. TableModel уведомит таблицу, когда данные будут изменены, и таблица перекрасится сама

  2. Поскольку вы сортируете свои данные, возможно, вы удаляете неправильную строку из TableModel. Сначала вам нужно преобразовать индекс вида в модельный индекс:

Например:

int modelIndex = table.convertRowIndexToModel( table.getSelectedIndex() );
model.removeRow( modelIndex );
Другие вопросы по тегам