1

I am trying to code a checklist style program and am using a JTabbedPane inside another JTabbedPane. Everything was fine until I tried adding another set of tabs under one tab. Then the bounds of the overall JTabbedPane started increasing and going off screen. Below is the pane before the extra tab. 1

And below here is the pane after the extra tab. 2

I'm wondering if there is possibly a limit of some sort to how many tabs I can do. Only thing is I have other top tabs with way more right tabs so that doesn't make too much sense.

Here is the code for setting up the components and tabs

private void init() {
        e4cPanel = new JPanel();
        e4cPanel.setBackground(back);

        gceaScroll = new JScrollPane();
        gceaScroll.setBackground(back);
        gceaScroll.setBorder(null);
        gceaScroll.setHorizontalScrollBar(null);
        gceaScroll.setVerticalScrollBar(new JCustomScrollBar());
        gceaScroll.getVerticalScrollBar().setUnitIncrement(25);
        gceaPanel = new JPanel();
        gceaPanel.setBackground(back);
        gceaScroll.setViewportView(gceaPanel);

        formScroll = new JScrollPane();
        formScroll.setBackground(back);
        formScroll.setBorder(null);
        formScroll.setHorizontalScrollBar(null);
        formScroll.setVerticalScrollBar(new JCustomScrollBar());
        formScroll.getVerticalScrollBar().setUnitIncrement(25);
        formPanel = new JPanel();
        formPanel.setBackground(back);
        formScroll.setViewportView(formPanel);

        legScroll = new JScrollPane();
        legScroll.setBackground(back);
        legScroll.setBorder(null);
        legScroll.setHorizontalScrollBar(null);
        legScroll.setVerticalScrollBar(new JCustomScrollBar());
        legScroll.getVerticalScrollBar().setUnitIncrement(25);
        legPanel = new JPanel();
        legPanel.setBackground(back);
        legScroll.setViewportView(legPanel);

        mytScroll = new JScrollPane();
        mytScroll.setBackground(back);
        mytScroll.setBorder(null);
        mytScroll.setHorizontalScrollBar(null);
        mytScroll.setVerticalScrollBar(new JCustomScrollBar());
        mytScroll.getVerticalScrollBar().setUnitIncrement(25);
        mytPanel = new JPanel();
        mytPanel.setBackground(back);
        mytScroll.setViewportView(mytPanel);

        giftScroll = new JScrollPane();
        giftScroll.setBackground(back);
        giftScroll.setBorder(null);
        giftScroll.setHorizontalScrollBar(null);
        giftScroll.setVerticalScrollBar(new JCustomScrollBar());
        giftScroll.getVerticalScrollBar().setUnitIncrement(25);
        giftPanel = new JPanel();
        giftPanel.setBackground(back);
        giftScroll.setViewportView(giftPanel);

        colScroll = new JScrollPane();
        colScroll.setBackground(back);
        colScroll.setBorder(null);
        colScroll.setHorizontalScrollBar(null);
        colScroll.setVerticalScrollBar(new JCustomScrollBar());
        colScroll.getVerticalScrollBar().setUnitIncrement(25);
        colPanel = new JPanel();
        colPanel.setBackground(back);
        colScroll.setViewportView(colPanel);

        upgScroll = new JScrollPane();
        upgScroll.setBackground(back);
        upgScroll.setBorder(null);
        upgScroll.setHorizontalScrollBar(null);
        upgScroll.setVerticalScrollBar(new JCustomScrollBar());
        upgScroll.getVerticalScrollBar().setUnitIncrement(25);
        upgPanel = new JPanel();
        upgPanel.setBackground(back);
        upgScroll.setViewportView(upgPanel);

        batScroll = new JScrollPane();
        batScroll.setBackground(back);
        batScroll.setBorder(null);
        batScroll.setHorizontalScrollBar(null);
        batScroll.setVerticalScrollBar(new JCustomScrollBar());
        batScroll.getVerticalScrollBar().setUnitIncrement(25);
        batPanel = new JPanel();
        batPanel.setBackground(back);
        batScroll.setViewportView(batPanel);

        tmScroll = new JScrollPane();
        tmScroll.setBackground(back);
        tmScroll.setBorder(null);
        tmScroll.setHorizontalScrollBar(null);
        tmScroll.setVerticalScrollBar(new JCustomScrollBar());
        tmScroll.getVerticalScrollBar().setUnitIncrement(25);
        tmPanel = new JPanel();
        tmPanel.setBackground(back);
        tmScroll.setViewportView(tmPanel);

        hmPanel = new JPanel();
        hmPanel.setBackground(back);

        berryScroll = new JScrollPane();
        berryScroll.setBackground(back);
        berryScroll.setBorder(null);
        berryScroll.setHorizontalScrollBar(null);
        berryScroll.setVerticalScrollBar(new JCustomScrollBar());
        berryScroll.getVerticalScrollBar().setUnitIncrement(25);
        berryPanel = new JPanel();
        berryPanel.setBackground(back);
        berryScroll.setViewportView(berryPanel);

        setTabPlacement(JTabbedPane.RIGHT);
        addTab("Elite 4/Champion", e4cPanel);
        addTab("Gotta Catch 'Em All", gceaScroll);
        addTab("Forms", formScroll);
        addTab("Legendaries", legScroll);
        addTab("Mythicals", mytScroll);
        addTab("Mystery Gifts", giftScroll);
        addTab("Collectables", colScroll);
        addTab("Upgrades", upgScroll);
        addTab("Battle", batScroll);
//      addTab("TM's", tmScroll);
//      addTab("HM's", hmPanel);
//      addTab("Berries", berryScroll);
}

As you can see, I'm also using a custom UI tabbed pane so here is the code for that incase it might be in there.

package customs.tabs;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
import org.jdesktop.animation.timing.Animator;
import org.jdesktop.animation.timing.TimingTarget;
import org.jdesktop.animation.timing.interpolation.PropertySetter;

@SuppressWarnings("serial")
public class MaterialTabbed extends JTabbedPane {
    private final int orientation;

    public MaterialTabbed(int orientation) {
        this.orientation = orientation;
        MaterialTabbedUI ui = new MaterialTabbedUI();
        setTabPlacement(orientation);
        setUI(ui);
    }

    public class MaterialTabbedUI extends MetalTabbedPaneUI {
        private Animator animator;
        private Rectangle currentRectangle;
        private TimingTarget target;

        public void setCurrentRectangle(Rectangle currentRectangle) {
            this.currentRectangle = currentRectangle;
            repaint();
        }

        public MaterialTabbedUI() {
        }

        @Override
        public void installUI(JComponent jc) {
            super.installUI(jc);
            animator = new Animator(500);
            animator.setResolution(0);
            animator.setAcceleration(.5f);
            animator.setDeceleration(.5f);
            tabPane.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent ce) {
                    int selected = tabPane.getSelectedIndex();
                    if (selected != -1) {
                        if (currentRectangle != null) {
                            if (animator.isRunning()) {
                                animator.stop();
                            }
                            animator.removeTarget(target);
                            target = new PropertySetter(MaterialTabbedUI.this, "currentRectangle", currentRectangle, getTabBounds(selected, calcRect));
                            animator.addTarget(target);
                            animator.start();
                        }
                    }
                }
            });
        }

        @Override
        protected Insets getTabInsets(int i, int i1) {
            if(orientation == 1 || orientation == 3) {
                return new Insets(10, 20, 10, 20);
            } else if(orientation == 2 || orientation == 4) {
                return new Insets(7, 10, 7, 10);
            } else {
                return new Insets(10, 10, 10, 10);
            }
        }

        @Override
        protected void paintTabBorder(Graphics grphcs, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
            Graphics2D g2 = (Graphics2D) grphcs.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(new Color(3, 155, 216));
            if (currentRectangle == null || !animator.isRunning()) {
                if (isSelected) {
                    currentRectangle = new Rectangle(x, y, w, h);
                }
            }
            if (currentRectangle != null) {
                if (tabPlacement == TOP) {
                    g2.fillRect(currentRectangle.x, currentRectangle.y + currentRectangle.height - 3, currentRectangle.width, 3);
                } else if (tabPlacement == BOTTOM) {
                    g2.fillRect(currentRectangle.x, currentRectangle.y, currentRectangle.width, 3);
                } else if (tabPlacement == LEFT) {
                    g2.fillRect(currentRectangle.x + currentRectangle.width - 3, currentRectangle.y, 3, currentRectangle.height);
                } else if (tabPlacement == RIGHT) {
                    g2.fillRect(currentRectangle.x, currentRectangle.y, 3, currentRectangle.height);
                }
            }
            g2.dispose();
        }

        @Override
        protected void paintContentBorder(Graphics grphcs, int tabPlacement, int selectedIndex) {
            Graphics2D g2 = (Graphics2D) grphcs.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(new Color(200, 200, 200));
            Insets insets = getTabAreaInsets(tabPlacement);
            int width = tabPane.getWidth();
            int height = tabPane.getHeight();
            if (tabPlacement == TOP) {
                int tabHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
                g2.drawLine(insets.left, tabHeight, width - insets.right - 1, tabHeight);
            } else if (tabPlacement == BOTTOM) {
                int tabHeight = height - calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
                g2.drawLine(insets.left, tabHeight, width - insets.right - 1, tabHeight);
            } else if (tabPlacement == LEFT) {
                int tabWidth = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
                g2.drawLine(tabWidth, insets.top, tabWidth, height - insets.bottom - 1);
            } else if (tabPlacement == RIGHT) {
                int tabWidth = width - calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth) - 1;
                g2.drawLine(tabWidth, insets.top, tabWidth, height - insets.bottom - 1);
            }
            g2.dispose();
        }

        @Override
        protected void paintFocusIndicator(Graphics grphcs, int i, Rectangle[] rctngls, int i1, Rectangle rctngl, Rectangle rctngl1, boolean bln) {

        }

        @Override
        protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
            if (tabPane.isOpaque()) {
                super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
            }
        }
    }
}
  • 3
    The code you're not showing us, the `JFrame`, the `JFrame` layout manager, and the other `JPanels`, all have an effect on how the `JFrame` is arranged. Create a simple [mre] with a `JFrame`, a `JTabbedPane`, and an inner `JTabbedPane` that we can compile and test in our IDEs that demonstrates the problem. – Gilbert Le Blanc Jul 02 '23 at 17:47
  • 2
    A non-pretty functional GUI is better than a pretty non-functional GUI. – Gilbert Le Blanc Jul 02 '23 at 17:50
  • 3
    *I'm also using a custom UI tabbed* - so first test with the default UI. I'm guessing it will work as expected. Then make one change at a time for your custom UI and retest. When it stops working you know what code you just changed. – camickr Jul 02 '23 at 20:40

1 Answers1

0

Since your code wasn't runnable, I went ahead and created the following GUI.

Nested tabs

As you can see, there are outer tabs and inner tabs all shown inside of the bounds of the JFrame.

Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.

Here's the complete, runnable code, otherwise known as a minimal reproducible example.

import java.awt.BorderLayout;
import java.awt.Dimension;

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

public class NestedJTabbedPanes implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new NestedJTabbedPanes());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Nested JTabbedPanes");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createOuterTabbedPane(), BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JTabbedPane createOuterTabbedPane() {
        JTabbedPane tabbedPane = new JTabbedPane();
        JPanel panel = createBlankPanel();
        tabbedPane.addTab("Tab #1", panel);
        JTabbedPane innerPane = createInnerTabbedPane();
        tabbedPane.addTab("Tab #2", innerPane);
        panel = createBlankPanel();
        tabbedPane.addTab("Tab #3", panel);
        panel = createBlankPanel();
        tabbedPane.addTab("Tab #4", panel);

        return tabbedPane;
    }

    private JTabbedPane createInnerTabbedPane() {
        JTabbedPane tabbedPane = new JTabbedPane();
        JPanel panel = createBlankPanel();
        tabbedPane.addTab("Tab #1", panel);
        panel = createBlankPanel();
        tabbedPane.addTab("Tab #2", panel);
        panel = createBlankPanel();
        tabbedPane.addTab("Tab #3", panel);
        panel = createBlankPanel();
        tabbedPane.addTab("Tab #4", panel);

        return tabbedPane;
    }

    private JPanel createBlankPanel() {
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(400, 300));

        return panel;
    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111