JFrame的repaint()方法存在问题 - Java

7
我希望能够使用Java的paint()在JFrame上绘制。当我点击JFrame时(现在是任何地方),我希望JFrame被重新绘制,显示出点击的坐标,类似于这个Java小程序http://www.realapplets.com/tutorial/MouseClickExample.html 目前已经完成的部分:
  • 一开始就绘制了所有内容,并且JFrame也正确地显示了。
还未完成的部分:
  • JFrame没有重绘和更新,即使调用了repaint()方法。
以下是我的代码 - 请尽可能严格地审查它 - 我想提高我的Java编程技术,所以(如果您有时间的话)请指出我可以改进的每个方面。
非常感谢您的帮助。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class AreaForText extends JPanel implements MouseListener {

int xpos; 
int ypos;

JFrame myJFrame = new JFrame();

public void setJFrame() {

    myJFrame.setSize(300, 150);
    myJFrame.setTitle("Bigger Text!");
    myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    myJFrame.setVisible(true);
    myJFrame.getContentPane().add(new AreaForText());
    myJFrame.addMouseListener(new AreaForText());

}

public void mouseClicked(MouseEvent me) {
    //Save the coordinates of the click lke this. 
    xpos = MouseInfo.getPointerInfo().getLocation().x; 
    ypos = MouseInfo.getPointerInfo().getLocation().y;
    System.out.print("Click" + "  x: " + xpos + "  y: " + ypos);
    myJFrame.invalidate();
    repaint();
    revalidate();
}


public void mouseEntered(MouseEvent e){
}

public void mouseReleased(MouseEvent e) { 
}

public void mousePressed(MouseEvent e) {
}

public void mouseExited(MouseEvent e) { 
}

public void paint(Graphics g) {

    System.out.print("hello");
    g.drawString("Hello World", 30, 80);
    g.fillRect(20,20,20,20);        
    g.drawString("("+xpos+","+ypos+")",xpos,ypos);

    }
}

class EnlargeText {

    public static void main(String args[]) {

       AreaForText test = new AreaForText();

       test.setJFrame();

    }

 } 

3
你的第一个问题包含了一个可工作的代码示例,格式也很规范,做得非常好! - wolfcastle
1
代码中不需要使用invalidate()和revalidate()。 - camickr
2个回答

7
您创建了两个AreaForText实例,这不是您想要的。其中一个被添加到JFrame中,另一个被添加到监听器中。因此,实际上接收鼠标事件并调用repaint的对象与显示的对象不同。
您的一些代码组织方式不是最好的。您有一个JPanel子类,它构建自己的JFrame并将自己放入面板中。如果您确实需要它,应该只传递JFrame。下面我做了一些更改。
编辑。我修复了一些鼠标监听器的问题,您获取的X/Y坐标是错误的。而且,您应该直接将监听器添加到面板中,而不是添加到JFrame中,这样您就不必转换坐标。
编辑。我将paint方法更改为paintComponent,这是优先重写的方法。请查看Swing Paint Tutorial以获取更多信息。
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

class AreaForText extends JPanel implements MouseListener {

    private int xpos;
    private int ypos;


    public AreaForText() {
        super();
        this.addMouseListener(this);
    }

    public void mouseClicked(MouseEvent me) {
        // Save the coordinates of the click lke this.
        xpos = me.getX();
        ypos = me.getY();
        System.out.print("Click" + "  x: " + xpos + "  y: " + ypos);
        repaint();
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.print("hello");
        g.drawString("Hello World", 30, 80);
        g.fillRect(20, 20, 20, 20);
        g.drawString("(" + xpos + "," + ypos + ")", xpos, ypos);

    }
}

class EnlargeText {

    public static void main(String args[]) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame myJFrame = new JFrame("Bigger Text!");
                myJFrame.setSize(300, 150);
                myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                myJFrame.getContentPane().add(new AreaForText());
                myJFrame.setVisible(true);
            }
        });
    }

}

此外,如果您想要这两个类(EnlargeText和AreaForText),您应该将它们拆分成单独的文件,或将其作为嵌套静态类的一个部分。 - wolfcastle
1
如果您对EventQueue.invokeLater感到困惑,请查看此处 - vehk
2
太棒了!感谢您帮我 a) 解决问题和 b) 改进我的整体技术 - 我一定要确保阅读有关 EventQueue.invokeLater 的内容。Stack Overflow 是一个多么出色的网站,可以找到帮助:D - Mr Tickle
2
@Mr Tickle 还要记得将帮助你的答案标记为正确的解决方案 :) - vehk

0

你没有调用JFrames的repaint()方法,而是调用了JPanel的重绘方法(即你所在的类)

尝试:

myJFrame.repaint();

不幸的是,这似乎仍然无法重绘我的JFrame。 我想,如果它被重绘了,那么在我的paint方法中它会输出“Hello”(在控制台中)。我一直在监视控制台,但很遗憾没有看到“hello”。 - Mr Tickle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接