0

完成并运行一个简单的程序后,该程序可让您在单击形状时更改形状的颜色:

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

class MyPanel extends JPanel{
    int x = 200,y = 200,r = 50;
    static Color co = Color.BLUE;
    static final JFrame frame = new JFrame();
    public static void main(String[] args){
        frame.setTitle("Color Change with Mouse Click");
        frame.setSize(500,500);
        MyPanel pane = new MyPanel();
        frame.add(pane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pane.setVisible(true);
        }

    public void Panel(){
        addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if(((e.getX() >= (x-r) && e.getX() < (x+r) && e.getY() >= (y-r) && e.getY() < (y+r))) & (co == Color.GREEN)){
                    co = Color.BLUE;
                    repaint();
                };
                if(((e.getX() >= (x-r) && e.getX() < (x+r) && e.getY() >= (y-r) && e.getY() < (y+r))) & (co == Color.BLUE)){
                    co = Color.GREEN;
                    repaint();
                };
            }
        });
    }

    Timer timer = new Timer(1, new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            Panel();
        }
    });

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        timer.start();
        Panel();
        g.setColor(co);
        g.fillOval(x-r, y-r, 2*r, 2*r);
        repaint();
    }
}

我遇到了一个我根本不知道如何解决的问题。JPanel 永远不会在第二次鼠标单击时更新,只会在第一次时更新。我认为添加计时器会解决这个问题,但显然没有。非常感谢您的帮助。

编辑:我根据 Aqua 的建议更改了我的代码:

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

class MyPanel extends JPanel{
    int x = 200,y = 200,r = 50;
    static Color co = Color.BLUE;

    public static void main(String[] args){
        final JFrame frame = new JFrame();
        frame.setTitle("Color Change with Mouse Click");
        MyPanel pane = new MyPanel();
        frame.add(pane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        }

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

    public void panel(){
        addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if(((e.getX() >= (x-r) && e.getX() < (x+r) && e.getY() >= (y-r) && e.getY() < (y+r))) && (co == Color.GREEN)){
                    co = Color.BLUE;
                    repaint();
                }else if(((e.getX() >= (x-r) && e.getX() < (x+r) && e.getY() >= (y-r) && e.getY() < (y+r))) && (co == Color.BLUE)){
                    co = Color.GREEN;
                    repaint();
                }else{
                    repaint();
                };
            }
        });
    }
    public MyPanel(){
        Timer timer = new Timer(20, new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                panel();
            }
        });
        timer.start();
    }
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(co);
        g.fillOval(x-r, y-r, 2*r, 2*r);
        repaint();
    }
}

并且颜色变化现在有效,但是颜色变化有点不可预测。有时它有延迟,有时没有,有时它完全不会改变。这是我的计时器有问题吗?

4

2 回答 2

2

调用Panel()frompaintComponent()会触发导致StackOverflowError异常的无限循环。repaint()最终导致paintComponent()调用.

您应该在面板的初始化中附加一次鼠标侦听器,而不是在每次重绘时。计时器也是如此。但是,尚不清楚此示例中计时器的意图是什么。

发布的代码的其他一些问题:

  1. 调用frame.setVisible(true);而不是pane.setVisible(true);发布的代码不起作用。也不需要JFrame frame在面板中保留静态成员。您可以简单地JFramemain().

  2. paintComponent()仅用于绘画。避免该方法中的复杂逻辑。不要设置定时器或调用其他初始化方法。您几乎无法控制何时paintComponent执行,并且必须快速以获得最佳绘图结果。浏览执行自定义绘画教程。将定时器和鼠标侦听器的初始化移到面板的构造函数中。

  3. 不要使用frame.setSize(500,500);,而是覆盖JPanel.getPreferredSize()。请参阅我应该避免在 Java Swing 中使用 set(Preferred|Maximum|Minimum)Size 方法吗?详情。

  4. 坚持 Java 命名约定。命名的方法Panel()令人困惑。请参阅命名约定

  5. 方法中缺少else语句Panel()。在第二次单击时,您首先进入第一个if语句,将颜色设置为 BLUE,然后,输入第二个 if 语句并将颜色重置为 GREEN。

  6. 正如上面评论中提到的,&并且&&是不同的运营商。请参阅运算符

于 2013-11-13T16:02:00.117 回答
2

定时器的意义何在?计时器用于安排事件。您没有安排任何事件,您正在等待用户单击鼠标。不需要计时器。如果您确实需要计时器,那么:

  1. 您永远不会安排 Timer 每毫秒触发一次,这对机器来说太快了,无法响应。根据要求使用更实际的值。也许是 50 或 100 毫秒。

  2. 您永远不会以绘画方法启动 Timer。您可能会在类的构造函数中启动 Timer。

您的 MouseListener 代码错误。您启动 Timer 并调用 Panel() 方法,该方法调用 addMouseListener() 方法。因此,1 秒后,您将添加 1000 个 MouseListeners 到您的面板中。这显然是错误的。MouseListener 应该添加到您的类的构造函数中。

不需要“co”变量(如果需要它就不是静态的)。所有 Swing 组件都支持 setForeground() 方法来设置绘制文本的颜色。在您的情况下,您正在绘制一个形状,但是当您想要更改颜色时,您仍然可以使用 setForeground() 方法。然后在您的绘画代码中,您只需使用:

//g.setColor(co);
g.setColor(getForeground());

由于您将 MouseListener 添加到面板中,因此无需检查鼠标单击点。该事件只会在您单击面板时生成。所以你需要做的就是使用 setForeground(...) 你想要的颜色。您甚至不需要调用 repaint,因为 Swing 足够聪明,可以在您更改其属性之一时重新绘制自身。

于 2013-11-13T16:35:03.493 回答