个性化 JTabbedPane 水平内的高度选项卡

Personalize Height Tabs inside the JTabbedPane horizontal

我正在编写我的个人外观,现在我想将我的个人高度设置到 JTabbledPane 内的选项卡。 我发现这个 post 用于使用 UIDefauls 设置 Insets,它运行良好,这就是结果

但我注意到垂直标签有一个错误,所以这就是问题所在

这是一个可重现的最小示例

import javax.swing.*;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
import java.awt.*;

/**
 * @author https://github.com/vincenzopalazzo
 */
public class MaterialMain extends JFrame {

    public static MaterialMain SINGLETON = new MaterialMain();

    static {
        try {
            UIManager.setLookAndFeel(new MaterialMain.LookAndFeelTest());
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

    public void init() {
        JMenuBar menuBar = new JMenuBar();
        JMenu file = new JMenu("File");
        menuBar.add(file);
        this.setJMenuBar(menuBar);
        JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT);
        //JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.setUI(new LookAndFeelTest.TestTabbledPaneUI());
        JPanel panel = new JPanel();
        JPanel panelTwo = new JPanel();
        panel.add(new JTextField("Hello guys, this is MaterialLookAndFeel"));
        tabbedPane.add("Test", panel);
        tabbedPane.add("TestTwo", panelTwo);
        setTitle("Look and feel");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(630, 360);
        add(tabbedPane);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SINGLETON.init();
            }
        });
    }

    public static class LookAndFeelTest extends MetalLookAndFeel {

        @Override
        protected void initClassDefaults(UIDefaults table) {
            super.initClassDefaults(table);
        }

        @Override
        protected void initComponentDefaults(UIDefaults table) {
            super.initComponentDefaults(table);

            table.put( "TabbedPane.tabInsets", new Insets(10,10,10,10) );
            table.put( "TabbedPane.selectedTabPadInsets", new Insets(10,10,10,10) );
            table.put( "TabbedPane.linePositionY", 45);
            table.put( "TabbedPane.linePositionX", 0);
            table.put( "TabbedPane.lineWith", 0);

        }

        static class TestTabbledPaneUI extends MetalTabbedPaneUI {

            @Override
            protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
                g.setColor(isSelected ? lightHighlight : tabPane.getBackground());
                g.fillRect(x, y, w, h);
                if (isSelected) {
                    paintLine(g, x, y, w, h);
                }else{
                }
            }

            protected void paintLine(Graphics graphics, int x, int y, int w, int h) {
                if(graphics == null){
                    return;
                }
                graphics.setColor(Color.RED);
                graphics.fillRoundRect(x + UIManager.getInt("TabbedPane.linePositionX"),
                        y + UIManager.getInt("TabbedPane.linePositionY"),
                        w - UIManager.getInt("TabbedPane.lineWith"), 1, 10, 10);
            }

            @Override
            protected LayoutManager createLayoutManager() {
                return new TestTabbedPaneLayout();
            }

            protected class TestTabbedPaneLayout extends BasicTabbedPaneUI.TabbedPaneLayout{

                protected int spacer; // should be non-negative
                protected int indent;

                public TestTabbedPaneLayout() {
                    this.spacer = UIManager.getInt("TabbedPane.spacer");
                    this.indent = UIManager.getInt("TabbedPane.indent");
                }

                @Override
                protected void calculateTabRects(int tabPlacement, int tabCount){
                    if(spacer < 0){
                        throw new IllegalArgumentException("The spacer inside the " +
                                this.getClass().getSimpleName() + " must be a negative value");
                    }

                    super.calculateTabRects(tabPlacement,tabCount);

                    for (int i = 0; i < rects.length; i++){
                        rects[i].x += i * spacer + indent;
                    }
                }
            }
        }
    }
}

我个人画线的方法

protected void paintLine(Graphics graphics, int x, int y, int w, int h) {
                if(graphics == null){
                    return;
                }
                graphics.setColor(Color.RED);
                graphics.fillRoundRect(x + UIManager.getInt("TabbedPane.linePositionX"),
                        y + UIManager.getInt("TabbedPane.linePositionY"),
                        w - UIManager.getInt("TabbedPane.lineWith"), 1, 10, 10);
            }

我的个人布局

protected class TestTabbedPaneLayout extends BasicTabbedPaneUI.TabbedPaneLayout{

                protected int spacer; // should be non-negative
                protected int indent;

                public TestTabbedPaneLayout() {
                    this.spacer = UIManager.getInt("TabbedPane.spacer");
                    this.indent = UIManager.getInt("TabbedPane.indent");
                }

                @Override
                protected void calculateTabRects(int tabPlacement, int tabCount){
                    if(spacer < 0){
                        throw new IllegalArgumentException("The spacer inside the " +
                                this.getClass().getSimpleName() + " must be a negative value");
                    }

                    super.calculateTabRects(tabPlacement,tabCount);

                    for (int i = 0; i < rects.length; i++){
                        rects[i].x += i * spacer + indent;
                    }
                }
            }

我认为错误是在 Layaut 代码中,但我找不到聪明的方法来解决这个问题,因此我向那些比我更了解的人征求意见。

我想添加这个问题的答案。

我的问题与

的错误有关

我已经解决了改变方法的问题,所以我重写了方法paintTabBackground

这是代码

@Override
    protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
        Graphics2D g2D = (Graphics2D) g;
        int xp[];
        int yp[];
        Polygon shape = null;
        Rectangle shapeRect = null;
        //Todo remove the shape and used the shapeRect
        if(tabPlacement == TOP){
            xp = new int[]{x, x, x, x + w, x + w, x + w, x + w, x};
            yp = new int[]{(y + positionYLine + heightLine), y + positionYLine, y + positionYLine, y + positionYLine, y + positionYLine, y + positionYLine, y + positionYLine + heightLine, y + positionYLine + heightLine};
            shape = new Polygon(xp, yp, xp.length);
        }else if(tabPlacement == BOTTOM){
            y += 20;
            xp = new int[]{x, x, x, x + w, x + w, x + w, x + w, x};
            yp = new int[]{(y + heightLine), y, y, y, y, y, y + heightLine, y + heightLine};
            shape = new Polygon(xp, yp, xp.length);
        }else if(tabPlacement == LEFT){
            //xp = new int[]{0, 0, 0, h, h, h, h, 0};
            //yp = new int[]{(y + heightLine), y, y, y, y, y, y + heightLine, y + heightLine};
            shapeRect = new Rectangle(x + heightLine - 2, y + (heightLine), heightLine, w / (tabPane.getTabCount()));
        }else{
            //super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
            shapeRect = new Rectangle(x + w - heightLine, y + (heightLine), heightLine, w / (tabPane.getTabCount()));
        }

        if (isSelected) {
            g2D.setColor(selectedAreaContentBackground);
            g2D.setPaint(selectedAreaContentBackground);
            tabPane.setForegroundAt(tabIndex, selectedForeground);

        } else {
            if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
                g2D.setColor(areaContentBackground);
                g2D.setPaint(areaContentBackground);
            } else {
                g2D.setColor(disableAreaContentBackground);
                g2D.setPaint(disableAreaContentBackground);
            }
            tabPane.setForegroundAt(tabIndex, foreground);
        }
        if(shape != null){
            g2D.fill(shape);
        }else if (shapeRect != null){
            g2D.fill(shapeRect);
        }
    }