У меня есть следующий SSCCE, который берет JTabbedPane
и добавляет к нему 500 вкладок, содержащих CustomJPanel
. Обратите внимание, что компонент CustomJPanel
генерируется «долго», потому что я (намеренно) добавляю к нему 100 JLabel
s.
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class Class1 {
public static void main(String[] args) {
JFrame window = new JFrame();
window.setTitle("Parent frame");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(1200, 800);
window.setLocationRelativeTo(null);
window.setVisible(true);
JTabbedPane jtp = new JTabbedPane();
window.add(jtp);
//new Thread(new Runnable() {
// public void run() {
for (int i = 0; i < 500; i++) {
jtp.addTab("tab"+i, new CustomJPanel());
}
// }
//}).start();
}
}
class CustomJPanel extends JPanel {
public CustomJPanel() {
for (int i = 0; i < 100; i++) {
this.add(new JLabel("test"));
}
}
}
Когда я запускаю этот код, у меня есть высокая вероятность получить следующее исключение:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(Unknown Source)
at javax.swing.plaf.basic.BasicTabbedPaneUI.setRolloverTab(Unknown Source)
at javax.swing.plaf.basic.BasicTabbedPaneUI.access$2100(Unknown Source)
at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.mouseEntered(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEnterExit(Unknown Source)
at java.awt.LightweightDispatcher.trackMouseEnterExit(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Проблема возникает, когда я быстро добавляю компоненты в JTabbedPane
, генерация которых занимает много времени. Если я удаляю цикл for в CustomJPanel
так, чтобы он содержал только один JLabel
, исключение не происходит. Обратите внимание, что, хотя в этом примере исключением всегда является «0», в моем приложении это может быть любое число.
Похоже, что исключение происходит с большей вероятностью, если вкладки добавляются в отдельном потоке.
Единственный способ уменьшить вероятность получения этого исключения - добавить задержку (с Thread.Sleep()
) в несколько десятков мс между добавлением каждой вкладки. Однако время от времени это случается.
Есть ли способ предотвратить возникновение этого исключения или запретить его отображение в консоли? Обратите внимание, что я не могу поймать это, потому что это ничего не указывает на мой код, это все «неизвестный источник».
Редактировать: Я изменил код Class1
для запуска на EDT:
public class Class1 {
public static JFrame window;
public static JTabbedPane jtp;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
window = new JFrame();
window.setTitle("Parent frame");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(1200, 800);
window.setLocationRelativeTo(null);
window.setVisible(true);
jtp = new JTabbedPane();
window.add(jtp);
new SwingWorker<Void, Void>() {
@Override
public Void doInBackground() {
for (int i = 0; i < 500; i++) {
jtp.addTab("tab"+i, new CustomJPanel());
}
return null;
}
@Override
public void done() {}
}.execute();
}
});
}
}
Однако, исключение все еще происходит. Что-то я делаю не так?