Случайно у нас возникает такая же ошибка в нашей среде, но действительно спорадическая, поэтому я не смог ее воспроизвести. Но ваш пример идеален, и я смог воспроизвести мою ошибку. См. Код ниже.
Я изменил свой ответ во время расследования. Старые комментарии не отражают последний код.
Ваша ошибка, о которой сообщают: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8068824
А вот решение, основанное на обходе ошибки:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class BasicExample extends JFrame {
private JTable t;
private DefaultTableModel dtm;
public BasicExample() {
init();
}
private void init() {
dtm = new DefaultTableModel(new String[][] { { "a", "b" }, { "c", "d" } },
new String[] { "A", "B" });
t = new JTable(dtm);
t.getTableHeader().setComponentPopupMenu(new PopupMenu(t));
this.setLayout(new BorderLayout());
add(t.getTableHeader(), BorderLayout.NORTH);
add(t, BorderLayout.CENTER);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class PopupMenu extends JPopupMenu {
private JTable table;
public PopupMenu(JTable table) {
this.table = table;
init();
}
private void init() {
for (int i = 0; i < table.getModel().getColumnCount(); i++) {
String columnName = table.getModel().getColumnName(i);
JMenuItem item = new JMenuItem(columnName);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TableColumn tc = table.getColumn(columnName);
t.getTableHeader().setDraggedColumn(null);
table.getColumnModel().removeColumn(tc);
}
});
this.add(item);
}
}
}
public static void main(String[] args) {
BasicExample be = new BasicExample();
}
}
Просто установите draggedColumn в null перед удалением.
Я продолжал копать , потому что это не объясняло, почему в нашей среде ошибка происходила действительно редко и только в QA. :)
Вот как выглядит код в нашей среде (еще раз спасибо за действительно хороший небольшой пример).
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class BasicExample extends JFrame {
private JTable t;
private DefaultTableModel dtm;
public BasicExample() {
init();
}
private void init() {
dtm = new DefaultTableModel(new String[][] { { "a", "b" }, { "c", "d" } },
new String[] { "A", "B" });
t = new JTable(dtm);
PopupMenu lPopupMenu = new PopupMenu(t);
// t.getTableHeader().setComponentPopupMenu(new PopupMenu(t));
t.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent pE) {
lPopupMenu.show(pE.getComponent(), pE.getX(), pE.getY());
}
});
this.setLayout(new BorderLayout());
add(t.getTableHeader(), BorderLayout.NORTH);
add(t, BorderLayout.CENTER);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class PopupMenu extends JPopupMenu {
private JTable table;
public PopupMenu(JTable table) {
this.table = table;
init();
}
private void init() {
for (int i = 0; i < table.getModel().getColumnCount(); i++) {
String columnName = table.getModel().getColumnName(i);
JMenuItem item = new JMenuItem(columnName);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TableColumn tc = table.getColumn(columnName);
// t.getTableHeader().setDraggedColumn(null);
table.getColumnModel().removeColumn(tc);
}
});
this.add(item);
}
}
}
public static void main(String[] args) {
BasicExample be = new BasicExample();
}
}
Разница с вашим кодом в том, что мы не используем setComponentPopupMenu (), но покажи PopupMenu вручную. И ваш вариант использования не создает исключения с нашим кодом. Почему? Хороший вопрос, и у меня нет ответа. Каким-то образом с вашим кодом JPopupMenu потребляют события мыши. А с нашим кодом JPopupMenu распространяет события мыши на базовый компонент. Вы можете увидеть это, если замените пользовательский интерфейс на заголовок таблицы. И вот как я воспроизвел исключение с помощью нашего кода: нажмите правую кнопку мыши на заголовке, но не отпускайте его и продолжайте перемещать мышь над всплывающим меню вниз от заголовка. Отпустите правую кнопку, когда указатель будет удален от заголовка (чтобы заголовок не обрабатывал событие MOUSE_RELEASED). Получите исключение.