2013-09-23 3 views
0

Я пытаюсь удалить несколько строк (например, пять из пятидесяти) в Jtable, но я могу удалить их только по одному (я использую несколько интервалов выбора, прежде чем вы спросите!), И я чувствую, что Jtable немного замерзает. Моя кнопка удаления:Удаление нескольких строк freeze JTable

deleteButton.addActionListener(new java.awt.event.ActionListener() { 
public void actionPerformed(java.awt.event.ActionEvent e){          
SwingUtilities.invokeLater(new Runnable() { 
    public void run(){ 
int[] selectedRow = jTable.getSelectedRows(); 
for(int j=0; j<selectedRow.length; j++){ 
        Boolean state= (Boolean)jTable.getValueAt(selectedRow[j],10); 
        if(state==true){//deleta the row 
         User u=model.getUsers(selectedRow[j]); 
         new UserDao().delete(u); 
         model.remove(selectedRow[j]); 
         numberField.setText(String.valueOf(model.getRowCount())); 
        } 
       } 
        } 
    });    
} 
}); 

Мой удалить:

public void remove(int row) { 
this.userlist.remove(row); 
this.fireTableDataChanged(); 
} 

Что я делаю неправильно?

+1

Если она замерзает, возьмите нить дамп и посмотреть, что на самом деле блокирование или происходит – Robin

+0

Пожалуйста, измените свой вопрос включать [sscce] (http://sscce.org/), который показывает метод 'remove()' вашей модели. – trashgod

+0

Это freezes minory.If я выбираю пять флажков и нажимаю кнопку DEL, только первый выбранный удаляется, а остальные остаются отмеченными. В моем коде выше некоторая ошибка? Как вы берете дамп потока в eclipse, если у меня нет any stacktrace? Best Wishes, – PaulHB

ответ

2

Давайте повнимательнее посмотрим на код ...

deleteButton.addActionListener(new java.awt.event.ActionListener() { 
    public void actionPerformed(java.awt.event.ActionEvent e){  
     // Don't know why you need to use invokeLater 
     // The event should be trigged within the EDT if the user 
     // clicked the button. This may introduce a small "pause" 
     // depending on what else is in the EDT... 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run(){ 
       // Get the indices of the selected rows...okay 
       int[] selectedRow = jTable.getSelectedRows(); 
       // Loop through the selected rows...good... 
       for(int j=0; j<selectedRow.length; j++){ 
        // Get the "state" of the row...okay 
        Boolean state= (Boolean)jTable.getValueAt(selectedRow[j],10); 
        // Long winded if, but okay... 
        if(state==true){//deleta the row 
         // Don't know what's going on here, 
         // But I assume you are trying to delete 
         // something from some kind of database 
         // THIS is likely to chew up some time... 
         User u=model.getUsers(selectedRow[j]); 
         new UserDao().delete(u); 
         // Uh oh... 
         // If you remove a row from the model, the list of indices you 
         // have is now invalid, as they no longer point 
         // to the correct rows in the model 
         model.remove(selectedRow[j]); 
         numberField.setText(String.valueOf(model.getRowCount())); 
        } 
       } 
      } 
     });    
    } 
}); 

Зв Две проблемы.

  1. Вы, кажется, называть какие-то функции управления в пределах контекста EDT, функциональности, что «выглядит» как он собирается вызвать EDT, чтобы замедлить/помедлил даже небольшое количество времени ...
  2. Вы полагаетесь на устаревшую информацию ...

Лучшим решением было бы использовать какой-то фоновый процесс для выполнения удаление пользователя и предоставлять средства в рамках модели для просмотра User сам объект и удалите его из модели. Это устраняет возможность изменения индексов под вами.

A SwingWorker предоставляет средства, с помощью которых мы можем выполнять операции в фоновом режиме, от Диспетчерского потока событий, предоставляя средства для повторной синхронизации требуемых действий (например, изменения модели таблицы) обратно на EDT, когда это необходимо ...

Например ...

public class DeleteUsersWorker extends SwingWorker<List<User>, User> { 

    private UserTableModel model; 
    private List<User> users; 

    public DeleteUsersWorker(UserTableModel model, List<User> users) { 
     this.model = model; 
     this.users = users; 
    } 

    protected List<User> doInBackground() { 
     UserDao dao = new UserDao(); 
     for (User user : users) { 
      dao.delete(user); 
      publish(user); 
     } 
     return users; 
    } 

    protected void process(List<User> users) { 
     for (User user : users) { 
      model.remove(user); 
     } 
    } 
} 

И содержание метода actionPerformed ...

int[] selectedRow = jTable.getSelectedRows(); 
List<User> usersToBeRemoved = new ArrayList<>(selectedRow.length); 
for(int row : selectedRow){ 
    // Is state part of the User object?? 
    Boolean state = (Boolean)jTable.getValueAt(row,10); 
    if(state){ 
     usersToBeRemoved.add(model.getUsers(row)); 
    } 
} 
DeleteUsersWorker worker = new DeleteUsersWorker(model, users); 
worker.execute(); 

Это, вероятно, потребует добавить некоторые дополнительные функциональные возможности в модель таблицы для поддержки удаления объекта User из модели, но у меня нет вашей модели, поэтому сложно делать предложения ...

Посмотрите на Concurrency in Swing для получения более подробной информации ...

Лучшим решением может быть прослушивание вашего dao API, который мог бы предоставлять уведомления об обновлениях, таким образом модель могла бы обновлять себя, но опять же, недостаточно контекста для определения;)

Обновлено с комментариями TrashGod

Вы также должны опасаться, что индексы представления не всегда отображаются непосредственно в индексы модели. Это происходит, когда таблица сортируется или фильтруется. Хотя вы можете утверждать, что ваша таблица не сортируется или фильтруется, хорошая практика никогда не делать такие предположения ...

При выборе индекса строки из таблицы вы должны позвонить JTable#convertRowIndexToModel(int), который вернет вам индекс точка в модели

Посмотрите на Sorting and Filtering для получения более подробной информации ...

Обновления с работоспособным например

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingWorker; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.table.AbstractTableModel; 

public class TableDeleteRowsTest { 

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

    public TableDeleteRowsTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       final UserTableModel model = new UserTableModel(
         new User("Kermit"), 
         new User("Fozzie"), 
         new User("Animal"), 
         new User("Miss Piggy"), 
         new User("Gonzo"), 
         new User("Beaker"), 
         new User("Crazy Harry"), 
         new User("Floyd Pepper"), 
         new User("Sweetums")); 

       final JTable table = new JTable(model); 

       JButton delete = new JButton("Delete"); 
       delete.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         int[] selectedRows = table.getSelectedRows(); 
         if (selectedRows.length > 0) { 
          List<User> users = new ArrayList<>(selectedRows.length); 
          for (int row : selectedRows) { 
           int modelRow = table.convertRowIndexToModel(row); 
           Boolean selected = (Boolean) model.getValueAt(modelRow, 1); 
           if (selected) { 
            users.add(model.getUser(modelRow)); 
           } 
          } 
          if (users.size() > 0) { 
           new DeleteUserWorker(users, model).execute(); 
          } 
         } 
        } 
       }); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(table)); 
       frame.add(delete, BorderLayout.SOUTH); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class DeleteUserWorker extends SwingWorker<List<User>, User> { 

     private List<User> users; 
     private UserTableModel model; 

     public DeleteUserWorker(List<User> users, UserTableModel model) { 
      this.users = users; 
      this.model = model; 
     } 

     @Override 
     protected void process(List<User> chunks) { 
      for (User user : users) { 
       model.remove(user); 
      } 
     } 

     @Override 
     protected List<User> doInBackground() throws Exception { 
      for (User user : users) { 
       // Simulated delay 
       Thread.sleep(250); 
       publish(user); 
      } 
      return users; 
     } 

    } 

    public class UserTableModel extends AbstractTableModel { 

     private List<User> users; 
     private List<Boolean> selected; 

     public UserTableModel(User... users) { 
      this.users = new ArrayList<>(Arrays.asList(users)); 
      selected = new ArrayList<>(this.users.size()); 
      for (User user : this.users) { 
       selected.add(new Boolean(false)); 
      } 
     } 

     public User getUser(int row) { 
      return users.get(row); 
     } 

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

     @Override 
     public int getColumnCount() { 
      return 2; 
     } 

     @Override 
     public String getColumnName(int column) { 
      String name = "?"; 
      switch (column) { 
       case 0: 
        name = "User"; 
        break; 
       case 1: 
        name = ""; 
        break; 
      } 
      return name; 
     } 

     @Override 
     public Class getColumnClass(int column) { 
      Class type = String.class; 
      switch (column) { 
       case 0: 
        type = String.class; 
        break; 
       case 1: 
        type = Boolean.class; 
        break; 
      } 
      return type; 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      Object value = null; 
      switch (columnIndex) { 
       case 0: 
        value = users.get(rowIndex).getName(); 
        break; 
       case 1: 
        value = selected.get(rowIndex); 
        break; 
      } 
      return value; 
     } 

     @Override 
     public boolean isCellEditable(int rowIndex, int columnIndex) { 
      return columnIndex == 1; 
     } 

     @Override 
     public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
      switch (columnIndex) { 
       case 1: 
        if (aValue instanceof Boolean) { 
         selected.set(rowIndex, (Boolean) aValue); 
         fireTableCellUpdated(rowIndex, columnIndex); 
        } 
        break; 
      } 
     } 

     public void remove(User user) { 
      int index = users.indexOf(user); 
      if (index >= 0) { 
       selected.remove(index); 
       users.remove(user); 
       fireTableRowsDeleted(index, index); 
      } 
     } 
    } 

    public class User { 

     private String name; 

     public User(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 
    } 
} 

обновлением с дополнительным примером

В приведенном выше примере будет удалить только строки, которые помечены и выбраны. Для того, чтобы удалить все отмеченные строки, то вам нужно что-то больше, как ...

JButton delete = new JButton("Delete"); 
delete.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     List<User> users = new ArrayList<>(selectedRows.length); 
     for (int row = 0; row < table.getRowCount(); row++) { 
      int modelRow = table.convertRowIndexToModel(row); 
      Boolean selected = (Boolean) model.getValueAt(modelRow, 1); 
      if (selected) { 
       users.add(model.getUser(modelRow)); 
      } 
     } 
     if (users.size() > 0) { 
      new DeleteUserWorker(users, model).execute(); 
     }    
    } 
}); 
+0

И [конвертировать координаты модели просмотра] (http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting) по мере необходимости. – trashgod

+1

@trashgod Да, подумал об упоминании об этом, но, хотя я мог бы просто добавить к путанице плохого OP ... – MadProgrammer

+0

MadProgrammer, я просто попробовал invokeLater, чтобы увидеть, что-то происходит, но ничего не изменило ... ваш метод выглядит smooth.I просто не получить его model.remove (пользователь) ... мой Пользователь только бобов с последним поле булевым, потому что его флажок в моей таблицеmodel, где я получаю каждый user.i использовать remove (int position) потому что я получаю его/удаляю из списка . С наилучшими пожеланиями. – PaulHB

Смежные вопросы