在使用super.paint(g)之后有没有重新绘制图形的方法?

h4cxqtbf  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(338)

所以我有一个问题,假设我用paint方法在java中创建了一个矩形,经过100毫秒的延迟,我做了super.paint(g),这会清除前面显示的矩形,有没有办法让它重新出现?
谢谢!
下面是我所说的例子,这个程序的目的是每当我按下鼠标按钮1时,它会创建一个向下的矩形,然后在鼠标按钮1关闭后消失。问题是每当我再次按下鼠标按钮1时,矩形就不会出现。
头等舱:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;

import javax.swing.JFrame;
import javax.swing.Timer;

public class RecoilHelper extends JFrame {

static Timer rs;
static int recoil = 540;
static boolean clearRectangle = false;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    JNativehookRecoilHelp.main(null);
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                RecoilHelper frame = new RecoilHelper();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public RecoilHelper() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {

    setBounds(0, 0, 1920, 1080);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setUndecorated(true);
    setBackground(new Color(1.0f,1.0f,1.0f,0.0f));
    setAlwaysOnTop(true);

    rs = new Timer(10,(ActionEvent e)->{
        repaint();

        recoil += 12;

        if (recoil>600) {

            rs.stop();
        }

    });

}

public void paint(Graphics g) { 

    Rectangle r = new Rectangle(960, recoil, 4, 4);
    System.out.println(recoil);
    super.paintComponents(g);
    g.fillRect(
       (int)r.getX(),
       (int)r.getY(),
       (int)r.getWidth(),
       (int)r.getHeight()
    );  
    if (clearRectangle) {
        super.paint(g);
    } 

}

}

第二类(使用jnativehook跟踪鼠标按钮1事件):

import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;

public class JNativehookRecoilHelp implements NativeMouseInputListener {

@Override
public void nativeMouseClicked(NativeMouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void nativeMousePressed(NativeMouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("Pressed");
    RecoilHelper.recoil = 540;
    RecoilHelper.rs.start();

}

@Override
public void nativeMouseReleased(NativeMouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("Released");
    RecoilHelper.clearRectangle=true;

}

@Override
public void nativeMouseDragged(NativeMouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void nativeMouseMoved(NativeMouseEvent arg0) {
    // TODO Auto-generated method stub

}
public static void main(String[] args) {
    GlobalScreen.addNativeMouseListener(new JNativehookRecoilHelp());
    LogManager.getLogManager().reset();

    // Get the logger for "org.jnativehook" and set the level to off.
    Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
    logger.setLevel(Level.OFF);

    try {
        GlobalScreen.registerNativeHook();
    }
    catch (NativeHookException ex) {

        System.exit(1);
    }
}

}
kkbh8khc

kkbh8khc1#

当前您正在尝试覆盖jframe的paint方法,这有两个问题,第一个问题是jframe是一个重量级组件(它有一个标题栏和一些需要考虑的相关内容),因此您可能会遇到无休止的问题,第二个问题是您需要覆盖 paintComponent 要对其执行自定义绘制的组件的方法。
这里的解决方案是在jframe中放置一个jpanel,并重写jpanel的paintcomponent方法。
下面是一个工作示例,它创建一个新矩形并每隔半秒将其添加到框架中,但也通过将现有矩形添加到列表并在每次重新绘制时绘制列表中的每个矩形来保留现有矩形。
主类很简单,只是将customjpanel添加到jframe中:

public class PaintExample extends JFrame
{
    private CustomJPanel customJpanel;

    public PaintExample()
    {
        //Create and add the custom panel to the JFrame
        setPreferredSize(new Dimension(400, 300));
        customJpanel = new CustomJPanel();
        getContentPane().add(customJpanel, java.awt.BorderLayout.CENTER);
        pack();
    }

    public static void main(String args[])
    {
        //Show the JFrame:
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new PaintExample().setVisible(true);
            }
        });
    }
}

以及完成我们绘画的定制面板类:

public class CustomJPanel extends JPanel
{
    int x = 0;
    int y = 0;
    boolean clearRectangle = true;
    //This is a list that we use to keep track of all the rectangles to draw/update
    ArrayList<Rectangle> rectangleList = new ArrayList<>();

    //Start a timer when the panel is created that will update the rectangle location every half second (500ms).
    //In your case you would use your recoil timer instead
    public CustomJPanel(){
        //Create event action
        ActionListener taskPerformer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                add a new rectangle in a different location
                x+= 5;
                y+= 5;
                rectangleList.add(new Rectangle(x,y,10,10));
                //Update the panel
                repaint();
            }
        };
        //Create and start a repeating event
        Timer timer = new Timer(500, taskPerformer);
        timer.setRepeats(true);
        timer.start();
    }

    //Here is where it all happens:
    @Override
    protected void paintComponent(Graphics g)
    {
        //Call super first to perform normal component painting
        super.paintComponent(g);
        //Now do your custom painting
        if (clearRectangle)
        {
            //Draw each rectangle in the list
            for (Iterator<Rectangle> iterator = rectangleList.iterator(); iterator.hasNext();)
            {
                Rectangle r = iterator.next();
                g.drawRect(r.x, r.y, r.width, r.height);
            }
        }
    }
}

几秒钟后,窗口看起来是这样的,注意它是如何保持所有先前的矩形的:

相关问题