JTabbedPane自定义选项卡外观

时间:2011-10-22 11:04:39

标签: java swing jtabbedpane

我想在JTabbedPane中自定义选项卡的外观 我想从最简单和最简洁的行为开始:没有边界,纯色 问题是仍然存在不稳定性:标签略有重叠边缘。

enter image description here

您会看到,自从选择了第二个标签后,它就会“脱颖而出”。 这是通过略微的边缘重叠来实现的。 是否有(非常棘手的)方法来禁用此行为?

简单,可测试(只是修复导入)代码:

public class TabbedPane_LookStudy extends JFrame{

public static void main(String [] args) throws UnsupportedLookAndFeelException {
    UIManager.setLookAndFeel(new NimbusLookAndFeel());
    new TabbedPane_LookStudy().setVisible(true);
}

public TabbedPane_LookStudy() {
    JTabbedPane tp = new JTabbedPane();
    tp.setUI(new MyTabbedPaneUI());
    add(tp);

    tp.addTab("first",new JPanel());
    tp.addTab("second", new JPanel());
    tp.addTab("third", new JPanel());

    setPreferredSize(new Dimension(180,100));
    pack();
}

public static class MyTabbedPaneUI extends javax.swing.plaf.basic.BasicTabbedPaneUI {

    @Override
    protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, 
               int tabIndex, Rectangle iconRect, Rectangle textRect) {
        Color savedColor = g.getColor();
        g.setColor(Color.PINK);
        g.fillRect(rects[tabIndex].x, rects[tabIndex].y, 
               rects[tabIndex].width, rects[tabIndex].height);
        g.setColor(Color.BLUE);
        g.drawRect(rects[tabIndex].x, rects[tabIndex].y, 
               rects[tabIndex].width, rects[tabIndex].height);
        g.setColor(savedColor);
    }
 }

}

4 个答案:

答案 0 :(得分:4)

正确的方法是仅实施Custom Look & Feel。但是,如果您想使用XxxTabbedPaneUI,那么this post可以帮助您。

Nimbus

最好检查aephyr代码库

答案 1 :(得分:2)

第一(部分)解决方案。 我找到了“定位”代码。
它是calculateTabRects中的方法TabbedPaneLayout,是BasicTabbedPaneUI的内部类。这种方法非常复杂,但好的新方法是“在前面提升”标签的部分在其自己的可覆盖方法中得到很好的评论和绝缘!它是padSelectedTab
创建一个不执行任何操作而不是提升组件的类就像这样简单:

    protected class MyTabbedPaneLayout extends TabbedPaneLayout {
        @Override
        protected void padSelectedTab(int tabPlacement, int selectedIndex) {
            //do nothing!
            //super.padSelectedTab(tabPlacement, selectedIndex);
        }
    }

请注意,它必须是MyTabbedPane的内部类。它必须通过重写MyTabbedPane.createLayoutManager:

来实例化
@Override
    protected LayoutManager createLayoutManager() {
        //return super.createLayoutManager();
         return new MyTabbedPaneLayout();
    }

非常容易并且实际工作......除了案例。 如果tabLayoutPolicy是WRAP_TAB_LAYOUT,则createLayoutManager实例化TabbedPaneLayout,但如果tabLayoutPolicy是SCROLL_TAB_LAYOUT,则实例化TabbedPanelScrollLayout。后者有私有而且没有受保护的访问权限,因此不可能将其子类化!
我的createLayoutManager implmentation失去了可滚动的行为。

答案 2 :(得分:1)

您可以在MyTabbedPaneUI中覆盖paintContentBorderTopEdge,以便它不会认为选择了任何选项卡。这不是一个很好的解决方案,但是根据我的经验,黑客用户界面很少适合用于其中一个:)

@Override
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
                       int selectedIndex, int x, int y, int w, int h) {
    super.paintContentBorderTopEdge(g, tabPlacement, -1, x, y, w, h);
}

答案 3 :(得分:1)

您可以将Html标记放入第一个参数中,如下所示:

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