自定义JButton paintComponent方法可视地修改形状?不是实际的按钮形状?

时间:2014-01-14 12:34:45

标签: java swing jbutton paintcomponent

我正在尝试创建一个包含地图的应用程序(Java)。每个县或州,都需要拥有自己的鼠标悬停,mouseClicked方法等。

我尝试这样做的方法是覆盖扩展JButton的自定义类中的paintComponent和paintBorder方法。代码和结果截图:

public class CustomButton extends JButton implements MouseListener {


 private Polygon shape;
 private boolean isMouseOver;
 private Color buttonColor = new Color(100,100,100);


    public CustomButton (Polygon shape,Color buttonColor) {
        //this.setText(text);
        this.buttonColor = buttonColor;
        this.shape = shape;
        setContentAreaFilled(false);
        addMouseListener(this);
    }


    @Override
    public Dimension getPreferredSize() {
        return (new Dimension(120, 120));
    }

    // Hit detection
    public boolean contains(int x, int y) {
        return shape.contains(x, y);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);


        if (isMouseOver && isEnabled()) { 
            g.setColor(new Color(buttonColor.getRed()+50,buttonColor.getGreen()+50,buttonColor.getBlue()+50));
        }else{
            g.setColor(buttonColor);    
        }
        g.fillPolygon(shape); 


    }

    protected void paintBorder(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setStroke(new BasicStroke(2));

        if (isMouseOver && isEnabled()) {            
            g2d.setColor(new Color(buttonColor.getRed()-50,buttonColor.getGreen()-50,buttonColor.getBlue()-50));             
        }else{
        g2d.setColor(new Color(buttonColor.getRed()-100,buttonColor.getGreen()-100,buttonColor.getBlue()-100));
        }
        g2d.drawPolygon(shape);

    }

结果:

http://s9.postimg.org/cr8t6uym7/ss1.png

我想要实现的目标(在油漆中编辑):

http://s23.postimg.org/aabdtin6z/ss2.png

我认为这是因为即使我重写了paintComponent方法。这个 只修改JButton内部绘制的内容?所以JButton的边界 长方形?有没有办法来解决这个问题?或者我应该努力实现这一目标 以完全不同的方式?

任何帮助都会很棒!我甚至在OpenGL中看过这个编程。我非常喜欢 经验不多!而且它永远消失!

非常感谢

3 个答案:

答案 0 :(得分:0)

你可以借助null LayoutManager来实现这一点:

  1. 删除getPreferredSize()方法。
  2. 将null布局设置为按钮容器(setLayout(null);)。
  3. 为您的按钮设置相同的边界,如下一个:

    b1.setBounds(0,0,80,80); b2.setBounds(0,0,80,80);

  4. enter image description here

    同样对于实施按钮点击,您需要使用ActionListener而不是MouseListener

答案 1 :(得分:0)

我认为您不能(轻松地)使用多个组件执行此操作。

相反,您应该只使用包含地图图像的单个JLabel。然后,您需要创建一个要在地图上绘制的形状列表,以表示您所在国家/地区的轮廓。所以你需要

  1. 覆盖标签的paintComponent()方法,以在地图上绘制每个Shape。
  2. 实现您在Mouse List中迭代的MouseListener代码,以确定鼠标当前正在使用哪种形状。

答案 2 :(得分:0)

如何使用OverlayLayout:http://java-swing-tips.blogspot.jp/2012/12/combine-five-jbuttons-to-make.html

enter image description here

import java.awt.*;
import javax.swing.*;

public class CompoundButtonTest {
  public JComponent makeUI() {
    JPanel p = new JPanel();
    p.add(new JButton("JButton"));
    p.add(makeCompoundButton(120, 80));
    return p;
  }
  private static JComponent makeCompoundButton(int w, int h) {
    final Dimension d = new Dimension(w, h);
    JPanel p = new JPanel() {
      @Override public Dimension getPreferredSize() {
        return d;
      }
    };
    p.setLayout(new OverlayLayout(p));
    p.add(new CustomButton(TriangleType.A, d, new Color(0x6464C8)));
    p.add(new CustomButton(TriangleType.B, d, new Color(0x64C864)));
    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 CompoundButtonTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

enum TriangleType {A, B}

class CustomButton extends JButton {
  private final Color buttonColor;
  private final TriangleType type;
  private final Dimension dim;
  private Shape shape;
  private int stroke = 3;
  public CustomButton(TriangleType type, Dimension d, Color color) {
    super();
    this.type = type;
    this.dim = d;
    this.buttonColor = color;
    setContentAreaFilled(false);
    setBorder(BorderFactory.createEmptyBorder());
    setIcon(new Icon() {
      @Override public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2 = (Graphics2D)g.create();
        if(getModel().isArmed()) {
          g2.setColor(buttonColor.darker());
        } else if(isRolloverEnabled() && getModel().isRollover()) {
          g2.setColor(buttonColor.brighter());
        } else {
          g2.setColor(buttonColor);
        }
        g2.translate(x, y);
        g2.fill(shape);
        g2.setColor(buttonColor.darker());
        g2.setStroke(new BasicStroke((float)stroke));
        g2.draw(shape);
        g2.dispose();
      }
      @Override public int getIconWidth()  {
        return dim.width;
      }
      @Override public int getIconHeight() {
        return dim.height;
      }
    });
  }
  private Rectangle rect;
  @Override public void paintComponent(Graphics g) {
    Rectangle r = getBounds();
    if(!r.equals(rect)) {
      int v = 8;
      int s = stroke/2;
      int w = r.width  - s;
      int h = r.height - s;
      if(TriangleType.A==type) {
        w -= v;
        h -= v;
        shape = new Polygon(new int[] {s,w,s}, new int[] {s,s,h}, 3);
      } else {
        w -= s;
        h -= s;
        shape = new Polygon(new int[] {w,w,v}, new int[] {v,h,h}, 3);
      }
      rect = r;
    }
    super.paintComponent(g);
  }
  @Override public boolean contains(int x, int y) {
    return shape.contains(x, y);
  }
}