2015-04-24 116 views
1

正在尋找創建一個JPanel邊框,就像在下面紅色圖像中突出顯示的那樣..也就是說一邊或兩邊的三角形。我已經使用info herehere成功實現了圓整的JPanel邊框。任何想法或提示?帶三角形邊框的JPanel

enter image description here

+2

不是 「相當」 是相同的,但仍然是一個[很好的示範(http://stackoverflow.com/questions/19835289/java-複雜的「非傳統」組件設計的擺動創建標籤式動態寬度按鈕/ 19851317#19851317)。您還應該查看[AWT和Swing中的繪畫](http://www.oracle.com/technetwork/java/painting-140037.html)和[執行自定義繪畫](http://docs.oracle.com/)。 COM/JavaSE的/教程/ uiswing /畫/) – MadProgrammer

回答

3

你也許能夠使用FlowLayout

  • FlowLayout:設置在水平差距爲負值。
  • Override JRadioButton#contains(int, int)
  • Override 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; 
    } 
} 
2

的主要問題與三角形是,這兩個組件需要彼此重疊,而標準的Java佈局被設計爲防止重疊。

你有3種選擇:

  1. 你要麼需要「假」由具有一個組件繪製三角形的組件左側的重疊。
  2. 或者你也可以創建一個組件來介入兩個矩形組件之間並呈現重疊。
  3. 或者您將需要使用自定義佈局管理器,以期望的方式重疊它們。

無論哪種方式,你也將有問題,點擊重疊區域只會去其中一個按鈕,除非你添加特殊的邏輯來適當地轉發點擊。