如何更改 JTabbedPane 选项卡的形状?
Posted
技术标签:
【中文标题】如何更改 JTabbedPane 选项卡的形状?【英文标题】:How can I change the shape of a JTabbedPane tab? 【发布时间】:2011-10-26 15:16:24 【问题描述】:我正在尝试更改JTabbedPane
中选项卡的形状。使用setTabComponentAt(0, someComponent);
不会更改选项卡的外部,它是一个具有对角左上角的矩形。可以做些什么来改变形状?
【问题讨论】:
我使用的解决方案是放弃 JTabbedPane,而是创建一行 JPanel,然后重写它们的 paintComponent 方法来创建我想要的任何外观。然后我添加了鼠标侦听器并编写了一些基本逻辑,使其像 JTabbedPane 一样,添加翻转等。这不需要很长时间,并且允许完全的创意控制。 【参考方案1】:正确的方法只是改变Look and Feel,来自Old.Java.Forums.Sun
的好例子
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
public class TabbedPane extends JPanel
private static final long serialVersionUID = 1L;
public TabbedPane()
setLayout(new BorderLayout());
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JTabbedPane tb = new JTabbedPane();
tb.setUI(new CustomTabbedPaneUI());
tb.add("Tab1", new JTextArea(""));
tb.add("Tab2", new JTextArea(""));
tb.add("Tab3", new JTextArea(""));
tb.add("Tab4", new JTextArea(""));
tb.add("Tab5", new JTextArea(""));
jp.add(tb, BorderLayout.CENTER);
add(jp, BorderLayout.CENTER);
tb.setEnabledAt(1, false);
tb.setEnabledAt(3, false);
public static void main(String[] args)
JFrame frame = new JFrame();
frame.getContentPane().add(new TabbedPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setVisible(true);
和
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.View;
public class CustomTabbedPaneUI extends BasicTabbedPaneUI
private Color selectColor;
private Color deSelectColor;
private int inclTab = 4;
private int anchoFocoV = inclTab;
private int anchoFocoH = 4;
private int anchoCarpetas = 18;
private Polygon shape;
public static ComponentUI createUI(JComponent c)
return new CustomTabbedPaneUI();
@Override
protected void installDefaults()
super.installDefaults();
selectColor = new Color(250, 192, 192);
deSelectColor = new Color(197, 193, 168);
tabAreaInsets.right = anchoCarpetas;
@Override
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
if (runCount > 1)
int lines[] = new int[runCount];
for (int i = 0; i < runCount; i++)
lines[i] = rects[tabRuns[i]].y + (tabPlacement == TOP ? maxTabHeight : 0);
Arrays.sort(lines);
if (tabPlacement == TOP)
int fila = runCount;
for (int i = 0; i < lines.length - 1; i++, fila--)
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 2, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + 3);
if (i < lines.length - 2)
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
else
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + rects[selectedIndex].height);
carp.addPoint(0, lines[i] + rects[selectedIndex].height);
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
else
int fila = 0;
for (int i = 0; i < lines.length - 1; i++, fila++)
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i + 1] - 3);
carp.addPoint(tabPane.getWidth() - 2 * fila - 3, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila + 2));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
super.paintTabArea(g, tabPlacement, selectedIndex);
@Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)
Graphics2D g2D = (Graphics2D) g;
GradientPaint gradientShadow;
int xp[] = null; // Para la forma
int yp[] = null;
switch (tabPlacement)
case LEFT:
xp = new int[]x, x, x + w, x + w, x;
yp = new int[]y, y + h - 3, y + h - 3, y, y;
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.ORANGE);
break;
case RIGHT:
xp = new int[]x, x, x + w - 2, x + w - 2, x;
yp = new int[]y, y + h - 3, y + h - 3, y, y;
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, new Color(153, 186, 243));
break;
case BOTTOM:
xp = new int[]x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - 3, x;
yp = new int[]y, y + h - 3, y + h, y + h, y + h - 1, y + h - 3, y, y;
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.BLUE);
break;
case TOP:
default:
xp = new int[]x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - inclTab, x;
yp = new int[]y + h, y + 3, y, y, y + 1, y + 3, y + h, y + h;
gradientShadow = new GradientPaint(0, 0, Color.ORANGE, 0, y + h / 2, new Color(240, 255, 210));
break;
// ;
shape = new Polygon(xp, yp, xp.length);
if (isSelected)
g2D.setColor(selectColor);
g2D.setPaint(gradientShadow);
else
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
g2D.setColor(deSelectColor);
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(255, 255, 200), 0, y + h / 2, new Color(240, 255, 210));
g2D.setPaint(gradientShadowTmp);
else
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(240, 255, 210), 0, y + 15 + h / 2, new Color(204, 204, 204));
g2D.setPaint(gradientShadowTmp);
//selectColor = new Color(255, 255, 200);
//deSelectColor = new Color(240, 255, 210);
g2D.fill(shape);
if (runCount > 1)
g2D.setColor(hazAlfa(getRunForTab(tabPane.getTabCount(), tabIndex) - 1));
g2D.fill(shape);
g2D.fill(shape);
@Override
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected)
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null)
// html
v.paint(g, textRect);
else
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
g.setColor(tabPane.getForegroundAt(tabIndex));
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
else // tab disabled
g.setColor(Color.BLACK);
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1);
/*protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected)
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null)
// html
v.paint(g, textRect);
else
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
Color fg = tabPane.getForegroundAt(tabIndex);
if (isSelected && (fg instanceof UIResource))
Color selectedFG = UIManager.getColor("TabbedPane.selectedForeground");
if (selectedFG != null)
fg = selectedFG;
g.setColor(fg);
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
else // tab disabled
//PAY ATTENTION TO HERE
g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex,
textRect.x - 1, textRect.y + metrics.getAscent() - 1);
*/
@Override
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics)
return 20 + inclTab + super.calculateTabWidth(tabPlacement, tabIndex, metrics);
@Override
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight)
if (tabPlacement == LEFT || tabPlacement == RIGHT)
return super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
else
return anchoFocoH + super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
@Override
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)
@Override
protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect, boolean isSelected)
if (tabPane.hasFocus() && isSelected)
g.setColor(UIManager.getColor("ScrollBar.thumbShadow"));
g.drawPolygon(shape);
protected Color hazAlfa(int fila)
int alfa = 0;
if (fila >= 0)
alfa = 50 + (fila > 7 ? 70 : 10 * fila);
return new Color(0, 0, 0, alfa);
【讨论】:
查看 CustomTabbedUI,似乎使用 Graphics2D 在 JPanel 中绘制自定义选项卡并完全放弃 JTabbedPane 可能更容易。 供参考,TabComponentsDemo
展示了另一种自定义方式。
@maq 标准事件集(鼠标、按键事件)和视觉后遗症(屏幕上发生的事情、时间和方式、绘画集、颜色、字体...)作为定义存储BasicsXxxUI 中的 Swing 对象,对于大多数 JComponents 来说,这些定义可作为 API 中的方法、构造函数等实现者访问,对于 JTabbedPane,这些键(错误、错误或功能)不会出现在 API 中,那么就没有其他方法可以破解基础定义(覆盖是正确的词)【参考方案2】:
该形状位于选项卡式窗格的 UI 委托的保护下,该委托源自 TabbedPaneUI
。 MetalTabbedPaneUI
子类是一个 example,它可以帮助您确定要替换委托的程度。
【讨论】:
我的正确答案,请看我的帖子一切皆有可能,但易碎,我认为 L&F 敏感 +1【参考方案3】:您可以将html标签放入addTab方法的第一个参数中,如下所示:
MyJTabbedPane.addTab("<html><h1 style='padding:20px;'>TEST</h1></html>", new JPanel());
【讨论】:
以上是关于如何更改 JTabbedPane 选项卡的形状?的主要内容,如果未能解决你的问题,请参考以下文章