2

I have 3 tabs in my JTabbedPane and I want to have them next to each other, like this: How it should looked, tabs next to each other

However, I didn't find how to automaticly set the width of the JTabbedPane, so that the tabs would fit next to each other, so I just set the width by tabs.setPreferredSize(new Dimension(210, 300));

This has of course many problems, mainly it doesn't even work on all systems: How it shouldn't look, tabs in 2 rows

Not to mention problems with renaming or adding/removing tabs.

So, is there a good way to calcuate the width of the tab names, to then pass into the setPrefferedSize() method, or better yet, some setWidthToFitTabs() method?

EDIT: minimal complete example:

SwingUtilities.invokeLater(() -> {

    JFrame frame = new JFrame("Tabs text");
    JTabbedPane tabs = new JTabbedPane();

    tabs.addTab("Tab1", new JLabel("Content1"));
    tabs.addTab("Tab2", new JLabel("Content2"));
    tabs.addTab("Tab3", new JLabel("Content3"));
    tabs.addTab("Tab4", new JLabel("Content4"));

    for (int i = 0; i < tabs.getTabCount(); i++) {
        System.out.println(tabs.getUI().getTabBounds(tabs, i));
    }

    frame.add(tabs);

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

});

Result:

java.awt.Rectangle[x=2,y=59,width=-8,height=19]
java.awt.Rectangle[x=2,y=40,width=-8,height=19]
java.awt.Rectangle[x=2,y=21,width=-8,height=19]
java.awt.Rectangle[x=2,y=2,width=49,height=19]

Tabs in the small, reproducable example

kajacx
  • 12,361
  • 5
  • 43
  • 70
  • 1
    See if this topic helps : http://stackoverflow.com/questions/9636601/tabs-at-fixed-positions-in-jtabbedpane-or-in-one-row – Arnaud Mar 01 '17 at 13:49
  • Thanks for the link, a viable solution for the worst-case scenario. BTW I have tried `pane.getUI().getTabBounds(pane, i).width`, but it returns `-8` for the first 2 tabs. Only the third tab has correct width of `65`. – kajacx Mar 01 '17 at 14:34
  • Please post your [mcve] that demonstrates your issue. See [Should I avoid the use of setPreferred|Maximum|MinimumSize in Java Swing?](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi), The general consensus says yes. I think this is either a layout issue (or a null layout issue maybe) – Frakcool Mar 01 '17 at 15:05
  • 1
    Oh boy, the "dont use `setPrefferedSize`" post that says you should extend a `JComponent` and override the `getPrefferedSize` method to return a cached copy of your desired `Dimension`, which is exactly what the default getPreffedSize does anyway. I'll add the example in a bit. – kajacx Mar 01 '17 at 15:20
  • Now that I think about it, I could always get the width of the lastly added tab, since the last tab always has correct width. This doesn't account for the padding (if any) and what not and is clucky as f*ck, but at least it would work, maybe. – kajacx Mar 01 '17 at 15:31

1 Answers1

4

but it returns -8 for the first 2 tabs. Only the third tab has correct width of 65.

Seems like a bit of a bug to me. In my code below I got around this by invoking pack() twice.

Here is my implementation that overrides the getPreferredSize() method (with the above hack):

import java.awt.*;
import javax.swing.*;

public class Main
{
    public static void main(String[] args) throws Exception
    {
        SwingUtilities.invokeLater(() ->
        {

            JFrame frame = new JFrame("Tabs text");
            JTabbedPane tabs = new JTabbedPane()
            {
                @Override
                public Dimension getPreferredSize()
                {
                    int tabsWidth = 0;

                    for (int i = 0; i < getTabCount(); i++) {
                        tabsWidth += getBoundsAt(i).width;
                    }

                    Dimension preferred = super.getPreferredSize();

                    preferred.width = Math.max(preferred.width, tabsWidth);

                    return preferred;
                }
            };

            tabs.addTab("Tab1", new JLabel("Content1"));
            tabs.addTab("Tab2", new JLabel("Content2"));
            tabs.addTab("Tab3", new JLabel("Content3"));
            tabs.addTab("Tab4", new JLabel("Content4"));


            frame.add(tabs);

            frame.pack();
            frame.pack();
            frame.setVisible(true);
        });
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks, the widths are correct after calling `pack()`, so calling the second `pack()` will register the correct sizes. – kajacx Mar 01 '17 at 22:10
  • @kajacx, glad the suggestion helped. Don't forget to "accept" the answer by clicking on the checkmark so people know the problem has been solved. – camickr Mar 02 '17 at 02:47
  • Ah, sorry, forgot to accept after I implemented this in my real application. – kajacx Mar 02 '17 at 13:24