java - 带三角形边框的 JPanel

标签 java swing jpanel border

希望创建一个 JPanel 边框,如下图中以红色突出显示的那样......即一侧或两侧的三角形。我已经使用信息 here 成功实现了圆形 JPanel 边框和 here .有什么想法或提示吗?

enter image description here

最佳答案

您可以使用 FlowLayout:

  • FlowLayout:水平间隙设置为负值。
  • 覆盖 JRadioButton#contains(int, int)
  • 覆盖 JPanel#isOptimizedDrawingEnabled()

enter image description here

import java.awt.*;
import java.awt.geom.*;
import java.io.Serializable;
import java.util.*;
import java.util.List;
import javax.swing.*;

public final class FlowLayoutOverlapTest {
  private static final int BORDER = 1;
  public JComponent makeUI() {
    JPanel p = new JPanel(new GridLayout(0, 1));
    p.setBorder(BorderFactory.createEmptyBorder(20, 2, 20, 2));
    p.add(makeBreadcrumbList(0, Color.PINK,   Arrays.asList("overlap:", "0px", "button")));
    p.add(makeBreadcrumbList(5, Color.CYAN,   Arrays.asList("overlap:", "5px", "button")));
    p.add(makeBreadcrumbList(9, Color.ORANGE, Arrays.asList("overlap:", "9px", "button")));
    return p;
  }
  private static AbstractButton makeButton(String title, Color color) {
    final ToggleButtonBarCellIcon icon = new ToggleButtonBarCellIcon();
    AbstractButton b = new JRadioButton(title) {
      //http://java-swing-tips.blogspot.jp/2008/11/rounded-corner-jbutton.html
      @Override public boolean contains(int x, int y) {
        if (Objects.nonNull(icon) && Objects.nonNull(icon.area)) {
          return icon.area.contains(x, y);
        } else {
          return super.contains(x, y);
        }
      }
    };
    b.setIcon(icon);
    b.setContentAreaFilled(false);
    b.setBorder(BorderFactory.createEmptyBorder());
    b.setHorizontalTextPosition(SwingConstants.CENTER);
    b.setFocusPainted(false);
    b.setOpaque(false);
    b.setBackground(color);
    return b;
  }
  private static JPanel makePanel(int overlap) {
    //http://java-swing-tips.blogspot.com/2013/12/breadcrumb-navigation-with-jradiobutton.html
    JPanel p = new JPanel(new FlowLayout(FlowLayout.LEADING, -overlap, 0)) {
      @Override public boolean isOptimizedDrawingEnabled() {
        return false;
      }
    };
    p.setBorder(BorderFactory.createEmptyBorder(BORDER, overlap + BORDER, BORDER, BORDER));
    p.setOpaque(false);
    return p;
  }
  private static JComponent makeBreadcrumbList(int overlap, Color color, List<String> list) {
    JPanel p = makePanel(overlap + 1);
    ButtonGroup bg = new ButtonGroup();
    for (String title : list) {
      AbstractButton b = makeButton(title, color);
      p.add(b);
      bg.add(b);
    }
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new FlowLayoutOverlapTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

//http://java-swing-tips.blogspot.com/2012/11/make-togglebuttonbar-with-jradiobuttons.html
class ToggleButtonBarCellIcon implements Icon, Serializable {
  private static final long serialVersionUID = 1L;
  private static final int W = 10;
  private static final int H = 21;
  public Shape area;
  public Shape getShape(Container parent, Component c, int x, int y) {
    int w = c.getWidth() - 1;
    int h = c.getHeight() - 1;
    int h2 = (int)(h * .5 + .5);
    int w2 = W;
    Path2D.Float p = new Path2D.Float();
    p.moveTo(0,      0);
    p.lineTo(w - w2, 0);
    p.lineTo(w,      h2);
    p.lineTo(w - w2, h);
    p.lineTo(0,      h);
    if (c != parent.getComponent(0)) {
      p.lineTo(w2, h2);
    }
    p.closePath();
    return AffineTransform.getTranslateInstance(x, y).createTransformedShape(p);
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Container parent = c.getParent();
    if (Objects.isNull(parent)) {
      return;
    }
    area = getShape(parent, c, x, y);

    Color bgc = parent.getBackground();
    Color borderColor = Color.GRAY.brighter();
    if (c instanceof AbstractButton) {
      ButtonModel m = ((AbstractButton) c).getModel();
      if (m.isSelected() || m.isRollover()) {
        bgc = c.getBackground();
        borderColor = Color.GRAY;
      }
    }
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(bgc);
    g2.fill(area);
    g2.setPaint(borderColor);
    g2.draw(area);
    g2.dispose();
  }
  @Override public int getIconWidth() {
    return 100;
  }
  @Override public int getIconHeight() {
    return H;
  }
}

关于java - 带三角形边框的 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29847066/

相关文章:

java - 比较Jhipster中的两个集合

java - 机器人 DialogFragment 机器人 :onClick ="buttonCancel" causes IllegalStateException could not find a method

java - 在 javascript 函数中使用 scriplet

java - Toolkit.getDefaultToolkit().createImage() 与 ImageIO.read()

java - Java中jpanel添加动态按钮

java - 从父类(super class)中调用超方法

java - JFrame 中随机输出图像

java - 如何在 JPanel 的 mouselistener 类中注册两个点?

java - 按下按钮时使其他类框架设置可见(假)

java - JPanel 大小在开始时未知