Java-如何从 JPanel 中清除图形

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30005331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:57:58  来源:igfitidea点击:

Java- how to clear graphics from a JPanel

javaswingjpaneljava-2d

提问by anonymous noob

I'm creating a simple program where I draw a black oval where I click with my mouse. However I want a new oval to appear and the old one to disappear. How would I go about doing this? I've messed around with the removeAll() method inserted into my mousePressed method, however it isn't working for me. Is the removeAll() method even suitable for this? Or should I use something else? Sorry if the answer is obvious, but I am still new to this and trying to learn. Any advice would be immensely appreciated. Thanks.

我正在创建一个简单的程序,在其中绘制一个黑色椭圆形,然后用鼠标单击。但是,我希望出现一个新的椭圆形,而旧的椭圆形消失。我该怎么做呢?我把 removeAll() 方法插入到我的 mousePressed 方法中,但它对我不起作用。removeAll() 方法甚至适合于此吗?还是我应该使用其他东西?对不起,如果答案是显而易见的,但我仍然是新手,并试图学习。任何建议将不胜感激。谢谢。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class PaintPractice extends JPanel implements MouseListener {

    Random rand = new Random(); 
    int x = rand.nextInt(450);
    int y = rand.nextInt(450);

    public PaintPractice(){
        super();
        addMouseListener(this);
    }

    public static void main(String[] args){

        JFrame frame = new JFrame();
        PaintPractice panel = new PaintPractice();

        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(panel);        
    }

    public void paint(Graphics g){
        g.setColor(Color.BLACK);
        g.fillOval(x, y, 50, 50);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        removeAll();
        repaint();      
    }

    @Override
    public void mouseClicked(MouseEvent e) {        
    }

    @Override
    public void mouseEntered(MouseEvent e) {        
    }

    @Override
    public void mouseExited(MouseEvent e) {     
    }

    @Override
    public void mouseReleased(MouseEvent e) {       
    }
}

采纳答案by MChaker

Immediate solution it to Just call super.paint(g)in the paint(Graphics g)method.

它立即解决只是调用super.paint(g)paint(Graphics g)方法。

public void paint(Graphics g){
        super.paint(g);
        g.setColor(Color.BLACK);
        g.fillOval(x, y, 50, 50);
    }

The Paint Mechanism and why Should i override paintComponent()instead of overriding paint():

绘制机制以及为什么我应该覆盖paintComponent()而不是覆盖paint()

Javadoc explains the Paint Mechanism:

Javadoc 解释了绘制机制

By now you know that the paintComponent method is where all of your painting code should be placed. It is true that this method will be invoked when it is time to paint, but painting actually begins higher up the class heirarchy, with the paint method (defined by java.awt.Component.) This method will be executed by the painting subsystem whenever you component needs to be rendered. Its signature is:

  • public void paint(Graphics g)

javax.swing.JComponent extends this class and further factors the paint method into three separate methods, which are invoked in the following order:

  • protected void paintComponent(Graphics g)
  • protected void paintBorder(Graphics g)
  • protected void paintChildren(Graphics g)

The API does nothing to prevent your code from overriding paintBorder and paintChildren, but generally speaking, there is no reason for you to do so. For all practical purposes paintComponent will be the only method that you will ever need to override.

现在您知道paintComponent 方法是放置所有绘画代码的地方。确实,该方法将在需要绘制时调用,但是绘制实际上是从类层次结构的更高层开始的,即绘制方法(由 java.awt.Component 定义)。该方法将在任何时候由绘制子系统执行你的组件需要被渲染。它的签名是:

  • 公共空心漆(图文g)

javax.swing.JComponent 扩展了这个类,并将paint方法进一步分解为三个单独的方法,它们按以下顺序调用:

  • protected void paintComponent(Graphics g)
  • 受保护的无效paintBorder(图形g)
  • protected void paintChildren(Graphics g)

API 不会阻止您的代码覆盖paintBorder 和paintChildren,但一般来说,您没有理由这样做。出于所有实际目的,paintComponent 将是您需要覆盖的唯一方法

This is why your PaintPracticecode should invoke super.paintComponent(g)instead.

这就是您的PaintPractice代码应该调用的原因super.paintComponent(g)

public void paintComponent(Graphics g) {    
    super.paintComponent(g);       
     g.setColor(Color.BLACK);
     g.fillOval(x, y, 50, 50);
}  

Also you don't need to call removeAll()in the mousePressed(MouseEvent e)method.

此外,您不需要调用removeAll()mousePressed(MouseEvent e)方法。

    @Override
    public void mousePressed(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        repaint();     
    }

回答by Tirupati Rao

just fillOval with the background color of the current drawing surface

只用当前绘图表面的背景颜色填充椭圆

 {
        g.setColor(...);//setColor to  surface background 
        g.fillOval(x, y, 50, 50);
    }

if you want you can clear the area: more at OracleDoc

如果您愿意,您可以清除该区域:OracleDoc 上的更多信息

回答by HiroshiFuu

One possible workaround if u just want to show the newly created oval. Make your frame and panel static, then call frame.setContentPane(panel) in mousePressed.

如果您只想显示新创建的椭圆,一种可能的解决方法。使您的框架和面板保持静态,然后在 mousePressed 中调用 frame.setContentPane(panel)。

Another working method is call g.clearRect(0, 0, getWidth(), getHeight()) in paint, but this will make the whole background whitecolor.

另一种工作方法是在油漆中调用 g.clearRect(0, 0, getWidth(), getHeight()) ,但这会使整个背景变白。

回答by TNT

  1. Since JPanel is a subclass of JComponent, you should override paintComponentinstead of paintand also use super.paintComponent(g)in the paintComponentmethod.

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    
  2. When you use removeAll, all components (buttons, text fields, labels, etc) in the JPanel are removed, if any. However, you don't seem to add any components to the JPanel, so it is not necessary to call this method.

  1. 由于 JPanel 是 JComponent 的子类,因此您应该在方法中覆盖paintComponent代替paint使用super.paintComponent(g)paintComponent

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    
  2. 当您使用 时removeAll,JPanel 中的所有组件(按钮、文本字段、标签等)都将被删除(如果有)。但是,您似乎没有向 JPanel 添加任何组件,因此没有必要调用此方法。