微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JTabbedPane 上的 AbstractBorder 绘制

如何解决JTabbedPane 上的 AbstractBorder 绘制

所以我正在使用 Swing 并尝试使用 JTabbedPane 来包含多个 JPanel 和 JScrollPanes 以滚动浏览 JPanel 列表。出现的问题是每当我更改选项卡时,我在滚动窗格内的 JPanels 中的自定义边框功能会导致组件在 JTabbedPane 标题的顶部绘制,我不知道如何解决这个问题:AbstractBorder paints over JTabbedPane header。我提供了模仿我在下面尝试做的事情的代码。要复制该问题,请在一个选项卡上向下滚动一些,直到其中一个勾勒出的面板在顶部一半可见。然后,切换到不同的选项卡,然后返回。然后,再滚动一些,问题就会出现在 JTabbedPane 的顶部

public class Example extends JFrame {
private final JTabbedPane tabbedPane;
public Example() {
    setTitle("MIN Example");
    setSize(600,700);
    setLayout(new BorderLayout());
    setLocationRelativeto(null);
    setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
    setBackground(Color.BLACK);
    setExtendedState(JFrame.MAXIMIZED_BOTH);

    tabbedPane = new JTabbedPane();
    tabbedPane.setBorder(BorderFactory.createEmptyBorder());
    tabbedPane.setFocusable(false);

    add(tabbedPane,BorderLayout.CENTER);
    createTabs();

    setVisible(true);
}

private void createTabs() {
    // Get the list of guilds
    List<String> tabs = new ArrayList<>(Arrays.asList("Tab 1","Tab 2","Tab 3"));

    // Iterate through the tabs and create the tab
    for (String tab : tabs) {
        // Initialize the list JPanel and formatting
        JPanel panelList = new JPanel();
        panelList.setLayout(new GridBagLayout());

        // House the list panel inside a JScrollPane
        JScrollPane listScroll = new JScrollPane(panelList);
        listScroll.setBorder(BorderFactory.createEmptyBorder());

        // Create tab and formatting
        tabbedPane.addTab(tab,listScroll);
        populateList(panelList);
    }
}

private void populateList(JPanel tab) {
    // Create GBC for formatting
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.weightx = 1;
    gbc.weighty = 1;

    // Remove all components from the JPanel
    tab.removeAll();

    // Add filler JPanel
    JPanel filler = new JPanel();
    filler.setopaque(false);
    tab.add(filler,gbc);

    // Update GBC constraints
    gbc.insets = new Insets(10,10,10);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weighty = GridBagConstraints.RELATIVE;

    // Go through the tabs and add JPanels
    for (int i = 10; i >= 0; i--) {
        JPanel tempPanel = new JPanel();
        tempPanel.setBorder(new RoundedBorder(Color.BLACK,6,16));
        tab.add(tempPanel,gbc,0);
        tempPanel.setPreferredSize(new Dimension(0,100));
    }

    // Refresh the console to display updated lists
    validate();
    repaint();
}
}

public class RoundedBorder extends AbstractBorder {
private final Color color;
private final int thickness;
private final int radii;
private final Insets insets;
private final Basicstroke stroke;
private final int strokePad;
RenderingHints hints;

/**
 * Creates the rounded border
 *
 * @param color The color of the border outline
 * @param thickness The thickness of the border outline
 * @param radii The radius of the rounded border
 */
public RoundedBorder(Color color,int thickness,int radii) {
    this.thickness = thickness;
    this.radii = radii;
    this.color = color;

    stroke = new Basicstroke(thickness);
    strokePad = thickness / 2;

    hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

    int pad = radii + strokePad;
    int bottomPad = pad + strokePad;
    insets = new Insets(pad,pad,bottomPad,pad);
}

@Override
public Insets getBorderInsets(Component c) {
    return insets;
}

@Override
public Insets getBorderInsets(Component c,Insets insets) {
    return getBorderInsets(c);
}

@Override
public void paintBorder(Component c,Graphics g,int x,int y,int width,int height) {
    Graphics2D g2 = (Graphics2D) g;

    int bottomLineY = height - thickness;

    RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(strokePad,strokePad,width - thickness,bottomLineY,radii,radii);

    Area area = new Area(bubble);

    g2.setRenderingHints(hints);

    // Paint the background color of the parent
    Component parent  = c.getParent();
    if (parent != null) {
        Color background = parent.getBackground();
        Rectangle rect = new Rectangle(0,width,height);
        Area borderRegion = new Area(rect);
        borderRegion.subtract(area);
        g2.setClip(borderRegion);
        g2.setColor(background);
        g2.fillRect(0,height);
        g2.setClip(null);
    }

    g2.setColor(color);
    g2.setstroke(stroke);
    g2.draw(area);
}
}

我试图解决此问题的唯一方法是更改​​添加 JTabbedPane(在选项卡填充面板之前添加)的顺序,但无济于事。非常感谢您的帮助,谢谢。

解决方法

将来,MRE 应包括:

  1. 导入语句
  2. main() 方法

在原始代码中,Graphics 的“clip”被设置为 null,因此面板的整个 Rectangle 看起来都被绘制了。

我修改了父级的绘制以使用单独的 Graphics 对象,因此原始“剪辑”区域不受影响:

// Paint the background color of the parent
Component parent  = c.getParent();
if (parent != null) {
    Graphics2D g2d = (Graphics2D)g2.create();
    Color background = parent.getBackground();
    //Rectangle rect = new Rectangle(0,width,height);
    Rectangle rect = g2d.getClip().getBounds();
    Area borderRegion = new Area(rect);
    borderRegion.subtract(area);
    g2d.setClip(borderRegion);
    g2d.setColor(background);
    g2d.fillRect(0,height);
    g2d.dispose();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。