如何更改 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 委托的保护下,该委托源自 TabbedPaneUIMetalTabbedPaneUI 子类是一个 example,它可以帮助您确定要替换委托的程度。

【讨论】:

我的正确答案,请看我的帖子一切皆有可能,但易碎,我认为 L&F 敏感 +1【参考方案3】:

您可以将html标签放入addTab方法的第一个参数中,如下所示:

MyJTabbedPane.addTab("&lt;html&gt;&lt;h1 style='padding:20px;'&gt;TEST&lt;/h1&gt;&lt;/html&gt;", new JPanel());

【讨论】:

以上是关于如何更改 JTabbedPane 选项卡的形状?的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing:从动态生成的 jTabbedPane 中获取值 [关闭]

arcgis版面视图中怎么修改整张地图背景?

Java - 一个接一个地加载 JTabbedPane

如何更改 TabLayout 选定选项卡的图标颜色?

如何更改特定角度材质选项卡的背景颜色?

如何更改导航选项卡的背景颜色[重复]