Reputation: 333
In a JTabbedPane
, the order of the tabs is from bottom to top:
I would like it to be top to bottom, meaning tab0 would be at the top row, and tab60 at the bottom row.
Code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
public class Class1 {
public static JTabbedPane jtp;
public static void main(String[] args) {
JFrame window = new JFrame();
window.setTitle("Parent frame");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
jtp = new JTabbedPane();
window.add(jtp);
/*WindowsTabbedPaneUI btpui = new WindowsTabbedPaneUI() {
@Override protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
int tabCount = tabPane.getTabCount();
Rectangle iconRect = new Rectangle(),
textRect = new Rectangle();
Rectangle clipRect = g.getClipBounds();
// Paint tabRuns of tabs from front to back
for (int i = 0; i < runCount; i++) {
int start = tabRuns[i];
int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1: tabCount - 1);
for (int j = start; j <= end; j++) {
if (j != selectedIndex && rects[j].intersects(clipRect)) {
paintTab(g, tabPlacement, rects, j, iconRect, textRect);
}
}
}
// Paint selected tab if its in the front run
// since it may overlap other tabs
if (selectedIndex >= 0 && rects[selectedIndex].intersects(clipRect)) {
paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect);
}
}
};
jtp.setUI(btpui);*/
//jtp.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
for (int i = 0; i <= 60; i++) {
jtp.addTab("tab"+i, new JPanel());
}
window.setVisible(true);
}
}
I have tried overriding the paintTabArea()
method in WindowsTabbedPaneUI
to paint from top to bottom, but it doesn't seem to do anything.
I have found 2 workarounds:
Put the tabs at the bottom so that they are aligned in the correct way (but I'd like to keep them on top)
Order the tabs in reverse order, then put the component in Right-To-Left alignment. However, this creates visual glitches: the tabs at the left are too close to the border, there is a space between the tabs at the left and the others, and the tabs at the right make a dent on the border. I would also have to override the addTab()
method, and put in LTR when there is only one line, which feels like a hack.
Is there any way to do this without glitches? I guess I have to override some method from BasicTabbedPaneUI
, but I can't find which one.
Upvotes: 0
Views: 465
Reputation: 4569
You could achieve it easier by extending BasicTabbedPaneUI
and overriding createLayoutManager
, and in there return TabbedPaneLayout
that override a necessary method.
Upvotes: -1
Reputation: 333
I finally found a solution.
As @Joe Coder said, you have to override the calculateTabRects()
method. However, this method is in an inner class. There is no way to extend the BasicTabbedPaneUI
, or the inner class, because there are just too many protected and private fields. The solution is to recreate the relevant classes by copy-pasting all their code.
The source code is from here.
The relevant modification is in the calculateTabRects()
method, more specifically in that for loop:
// Step through runs from back to front to calculate
// tab y locations and to pad runs appropriately
for (i = runCount - 1; i >= 0; i--) {
//...
}
Simply iterating in reverse does the trick: for (i = 0; i < runCount; i++) {...}
Now, if you copy-paste the code of the BasicTabbedPaneUI
, you'll find that you need to also copy-paste LazyActionMap
and BasicGraphicsUtils
.
For convenience, here is all the code you need to copy-paste. Make sure not to override the package, if it's not in the package javax.swing.plaf.basic
it won't work.
FixedTabbedPaneUI.java: https://pastebin.com/W8RBD4vg
LazyActionMap2.java: https://pastebin.com/RKtDgJB5
BasicGraphicsUtils2.java: https://pastebin.com/Au4hcSyp
But, in my case, I need a WindowsTabbedPaneUI
. So here's WindowsTabbedPaneUI2.java: https://pastebin.com/89UedgbQ
..XPStyle2.java: https://pastebin.com/xCsm8DZc
..and AnimationController2.java: https://pastebin.com/7Pm0s5eG
The OOP hell finishes here, but in the current state, the lines between "runs" (tab lines) disappear:
The solution is to put the following after choosing the UI with UIManager.setLookAndFeel()
:
UIManager.getDefaults().put("TabbedPane.tabRunOverlay", 0);
UIManager.getDefaults().put("TabbedPane.focus", new Color(0, 0, 0, 0));
The result:
Upvotes: 2