3

我刚刚开始使用 Swing 并试图绘制一个具有自定义形状的按钮,在这个例子中是一个三角形。我在下面的代码中将 JButton 子类称为“ShiftingButton”,因为它的行为异常。当鼠标进入它的区域时,它会被重新绘制,并偏离其原始位置。此外,除了原始位置之外,还绘制了移位的偏移版本,以便原始版本和移位版本一起出现。也就是说,当我运行此代码时,按钮显示为沿窗口左边缘的三角形。然后当我在按钮上运行鼠标时,会绘制一个新的三角形(除了旧的),向下和向右移动大约 10 个像素。调整窗口大小会更改幻像按钮与原始按钮的偏移量。

用鼠标点击实验表明只有原始的、正确定位的按钮是活动的。偏移幻象按钮的区域未激活。

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

public class ShiftingButton extends JButton implements ActionListener {
    private Polygon shape;
    public ShiftingButton () {
        initialize();
        addActionListener(this);
    }
    protected void initialize() {
        shape = new Polygon();
        setSize(120, 120);
        shape.addPoint(0, 0);
        shape.addPoint(0, 60); 
        shape.addPoint(90, 0);
        setMinimumSize(getSize());
        setMaximumSize(getSize());
        setPreferredSize(getSize());
    }
    // Hit detection
    public boolean contains(int x, int y) {
        return shape.contains(x, y);
    }
    @Override
    public void paintComponent (Graphics g) {
        System.err.println("paintComponent()");
        g.fillPolygon(shape);
    }
    protected void paintBorder(Graphics g) {
    }
    @Override
    public void actionPerformed (ActionEvent ev) {
        System.out.println("ShiftingButton ActionEvent!");
    }
    public static void main (String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        ShiftingButton button = new ShiftingButton();
        panel.add(button);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}
4

1 回答 1

2

您未能super.paintComponent(g)在被覆盖的paintComponent(...)方法内调用。此外,在覆盖Base类的方法时,始终尽量保持方法的访问说明符相同。在这种情况下它是protected而不是public:-) 现在函数应该是这样的:

@Override
protected void paintComponent (Graphics g) {
    System.err.println("paintComponent()");
    super.paintComponent(g);
    g.fillPolygon(shape);
}

编辑 1:

此外,由于您使用的是要绘制的自定义形状,因此您再次未能为此指定ContentAreaFilled属性JButton,因此在您的构造函数中,您应该编写setContentAreaFilled(false),以使其正常工作。虽然如果这不起作用(由于文档中指定的原因),那么您必须使用普通的旧Opaque属性并将其设置false为此JButton使用setOpaque(false):-)

这是您修改后的代码:

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

public class ShiftingButton extends JButton implements ActionListener {

    private Polygon shape;

    public ShiftingButton () {
        setContentAreaFilled(false);
        initialize();
        addActionListener(this);
    }

    protected void initialize() {
        shape = new Polygon();
        setSize(120, 120);
        shape.addPoint(0, 0);
        shape.addPoint(0, 60); 
        shape.addPoint(90, 0);
    }

    @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) {
        System.err.println("paintComponent()");
        super.paintComponent(g);
        g.fillPolygon(shape);       
    }

    protected void paintBorder(Graphics g) {
    }

    @Override
    public void actionPerformed (ActionEvent ev) {
        System.out.println("ShiftingButton ActionEvent!");
    }

    public static void main (String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        ShiftingButton button = new ShiftingButton();
        panel.add(button);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}
于 2013-08-18T15:44:50.537 回答