Search code examples
javaswinglayoutindexoutofboundsexception

ArrayIndexErrorException when inserting dynamically a JPanel into a TabbedPanel


I'm trying to implement a JFrame with a JTabbedPane as main component (this is the only component of the JFrame). At the beginning, the tabbed panel should not contain any tab. Latter are added when an event occurs. Each the tab contains a JPanel with a BorderLayout. This is the piece of code where I get some problems. Effectively, when adding the tab, I get an ArrayIndexOutOfBoundException. I have identified the line of code where the error is produced, and it happens when I add the second element to the panel. Does someone know how to fix this error ? I tried to catch the error but it doesn't work. This the implementation I have right now :

This is the code of the main frame

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public class MyFrame extends JFrame {

    static JTabbedPane main;

    public MyFrame() {
        main = new JTabbedPane();
        this.add(main);
        this.setMinimumSize(new Dimension(600, 800));
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.pack();
    }

    public static JPanel addTab(String title) {
        MyPanel panel = new MyPanel();
        main.addTab(title, panel);
        return panel;
    }
}

This is the class of the panel inside a tabbed panel :

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneLayout;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class MyPanel extends JPanel {
    private JPanel scrollPanel;
    private JTextArea textArea;
    private JButton button;
    public MessageTo panel;

    public MyPanel() {

        JScrollPane scrollPane = new JScrollPane(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setLayout(new ScrollPaneLayout());
        scrollPanel = new JPanel();
        scrollPane.setViewportView(scrollPanel);
        scrollPanel.setLayout(new BoxLayout(scrollPanel, BoxLayout.Y_AXIS));

        textArea = new JTextArea();
        Border roundedBorder = new LineBorder(Color.black, 1, true);
        textArea.setBorder(roundedBorder);

        button = new JButton("Send");
        JPanel panel1 = new JPanel();
        panel1.setBorder(new EmptyBorder(0, 10, 0, 0));
        panel1.add(button);

        JPanel inner_panel = new JPanel();
        inner_panel.setLayout(new BorderLayout());
        inner_panel.add(panel1, BorderLayout.EAST);
        inner_panel.add(textArea, BorderLayout.CENTER);
        inner_panel.setBorder(new EmptyBorder(10, 10, 10, 10));

        this.setLayout(new BorderLayout());
        this.add(scrollPane, BorderLayout.CENTER);
        this.add(inner_panel, BorderLayout.SOUTH); // This line produces the error
    }
}

And this is the error I have :

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(BasicTabbedPaneUI.java:1506)
at javax.swing.plaf.basic.BasicTabbedPaneUI.setRolloverTab(BasicTabbedPaneUI.java:575)
at javax.swing.plaf.basic.BasicTabbedPaneUI.access$2000(BasicTabbedPaneUI.java:54)
at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.mouseEntered(BasicTabbedPaneUI.java:3626)
at java.awt.Component.processMouseEvent(Component.java:6525)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4620)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4474)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:747)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:720)
at java.awt.EventQueue$4.run(EventQueue.java:718)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:717)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Thank you !

EDIT :

This is the code you can use to test my code :

public class Main {

    public static MyFrame frame;

    public static void main(String[] args)   {

        frame = new MyFrame();
        new Thread() {
            public void run() {
                frame.addTab("Test");
            }
        }.start();
    }

}

Solution

  • As Kiheru suggest, by the modification of frame from another thread must be done in this way :

    public class Main {
    
        public static MyFrame frame;
    
        public static void main(String[] args) throws InterruptedException,
                ExecutionException, UnknownHostException, IOException {
    
            frame = new MyFrame();
            new Thread() {
                public void run() {
                    SwingUtilities.invokeLater(new Runnable() {
    
                        @Override
                        public void run() {
                            frame.addTab("Test");
                        }
                    });
                    try {
                        this.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    SwingUtilities.invokeLater(new Runnable() {
    
                        @Override
                        public void run() {
                            frame.addTab("Test2");
                        }
                    });
                }
            }.start();
        }
    }