java - 自定义 JTabbedPane 中的选项卡渲染顺序

标签 java swing tabs rendering jtabbedpane

大家好,新年快乐,这是我 2017 年的第一篇文章! :)

问题解释

我目前正在编写自定义 JTabbedPane 并且一切正常,但是在呈现选项卡时我遇到了一个意想不到的(对我来说)设计问题。

问题是所有未选择的选项卡从左到右呈现,并且由于我使用 GeneralPath 类自定义的形状超出了默认选项卡边界,因此呈现的每个选项卡都与左侧的部分选项卡重叠.您可以在下图中查看:

enter image description here

如您所见,选定的选项卡与右侧的任何选项卡重叠,但未选定的选项卡,如名为“CustomPanel2”的选项卡,会在下一个选项卡之前呈现,等等。

问题

我看到一篇文章谈到重写 BasicTabbedPaneUI 类中的 paintTab 方法,这是我正在使用的一个,但我不知道该怎么做,所以我会喜欢你向我展示呈现标签的正确方法,以便在 Google Chrome 中获得类似标签的内容,如下所示:

enter image description here

提前谢谢你,祝你有美好的一天! ;)

PD:我认为没有相关代码可以添加。如果您需要,请找我。

最佳答案

尝试将未选中的选项卡塑造成五边形怎么样?

pentagon

screenshot

注意:当 JTabbedPane#setTabLayoutPolicy (JTabbedPane.WRAP_TAB_LAYOUT)JTabbedPane#setTabPlacement (JTabbedPane.BOTTOM) 设置时,此示例不测试:

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class TabsOverlapTest {
  private JComponent makeUI() {
    Color selectedTabColor = UIManager.getColor("TabbedPane.selected");
    Color tabBackgroundColor = Color.LIGHT_GRAY;
    Color tabBorderColor = Color.GRAY;
    UIManager.put("TabbedPane.highlight", tabBorderColor);

    JTabbedPane tabs = new JTabbedPane();
    tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    tabs.setUI(new BasicTabbedPaneUI() {
      @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) {
      }
      @Override protected void paintContentBorderTopEdge(
          Graphics g, int tabPlacement, int selectedIndex,
          int x, int y, int w, int h) {
        super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
        Rectangle selRect = getTabBounds(selectedIndex, calcRect);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(selectedTabColor);
        g2.drawLine(selRect.x - 2, y, selRect.x + selRect.width + 2, y);
        g2.dispose();
      }
      @Override protected void paintTabBackground(
          Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h,
          boolean isSelected) {

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int a = isSelected ? 0 : 1;

        GeneralPath shape = new GeneralPath();
        shape.moveTo(x - 3, y + h);
        shape.lineTo(x + 3, y + a);
        shape.lineTo(x + w - 3, y + a);
        shape.lineTo(x + w + 3, y + h);
        shape.closePath();
        g2.setColor(isSelected ? selectedTabColor : tabBackgroundColor);
        g2.fill(shape);

        GeneralPath border = new GeneralPath();
        if (isSelected || tabIndex == 0) {
          border.moveTo(x - 3, y + h - 1);
        } else {
          border.moveTo(x + 3, y + h - 1);
          border.lineTo(x, (y + h - 1) / 2);
        }
        border.lineTo(x + 3, y + a);
        border.lineTo(x + w - 3, y + a);
        border.lineTo(x + w + 3, y + h - 1);

        g2.setColor(tabBorderColor);
        g2.draw(border);

        g2.dispose();
      }
    });
    tabs.addTab("JTextArea",  new JScrollPane(new JTextArea()));
    tabs.addTab("JTree",      new JScrollPane(new JTree()));
    tabs.addTab("JButton",    new JButton("button"));
    tabs.addTab("JSplitPane", new JSplitPane());
    return tabs;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TabsOverlapTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

关于java - 自定义 JTabbedPane 中的选项卡渲染顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41566659/

相关文章:

Ubuntu 中的 Bash 控制台选项卡完成

android - 突出显示抽屉导航中相对于选项卡布局中的 fragment 的项目

java - 为什么我在蓝牙 connect() 上得到 “java.io.IOException: read failed, socket might closed or timeout, read ret: -1”?

java - 在卡片布局中定位组件

java - 如何在 Windows 上启动 JBoss AS 7.1.1?

java - 简单的 Java 2D 图形 : draw a rectangle?

java - 根据数据库查询返回的字符串,为 JTable 列中的所有单元格设置不同的背景颜色

javascript - 我被困在 javascript 中,隐藏/激活选定的选项卡

java - 不同系统上的 SWT

java - 等待输入字符 10 秒,还是在按下某个键时提前继续?