【问题标题】:JTabbedPane customize tab lookJTabbedPane 自定义选项卡外观
【发布时间】:2011-12-13 03:04:46
【问题描述】:

我想自定义 JTabbedPane 中选项卡的外观。
我想从最简单、最朴素的行为开始:没有边框,纯色。
问题是仍然存在不规则性:标签页边距略有重叠。

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

简单、可测试(仅修复导入)代码:

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);
    }
 }

}

【问题讨论】:

    标签: java swing jtabbedpane


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      第一个(部分)解决方案。 我找到了“定位”代码。
      它是BasicTabbedPaneUI的内部类TabbedPaneLayout中的方法calculateTabRects。该方法非常复杂,但好消息是“在前面抬起”选项卡的部分在其自己的可覆盖方法中得到了很好的注释和绝缘!是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。后者具有 private 且不受保护的访问权限,因此不可能对其进行子类化!
      我的 createLayoutManager 实现失去了可滚动行为。

      【讨论】:

        【解决方案3】:

        您可以在 MyTabbedPaneUI 中覆盖paintContentBorderTopEdge,这样它就不会认为任何选项卡被选中。这不是一个很好的解决方案,但根据我的经验,破解 UI 类很少适合自己:)

        @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);
        }
        

        【讨论】:

          【解决方案4】:

          正确的方法是只实现Custom Look & Feel。但是如果你想和XxxTabbedPaneUI一起玩,那么this post也许可以帮助你。

          对于Nimbus 最好检查aephyr 代码库

          【讨论】:

          • 我从那篇文章开始。但是在那个 UI 实现中,只有paintXXX 方法和calculateTabWidth 和calculateTabHeight,而不是选项卡放置。所以我坚持标签放置逻辑必须包含在其他地方。
          • NOT tab placement 是什么,您可以从顶部通过边框...到底部进行绘制,Tab 间隔在顶部?
          • 对不起,mKorbel,我不明白。你能解释一下吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-31
          • 1970-01-01
          • 1970-01-01
          • 2017-01-05
          • 2017-03-09
          • 2021-03-20
          相关资源
          最近更新 更多