[英]Is there a way to repaint graphics after using super.paint(g)?
所以我有一个问题,假设我使用绘制方法在 Java 中创建了一个矩形,延迟 100 毫秒后我执行 super.paint(g),这会清除之前显示的矩形,有没有办法让它重新出现?
谢谢!
下面是我正在谈论的一个示例,该程序的目的是每当我按住鼠标按钮 1 时,它会创建一个向下的矩形,然后在鼠标按钮 1 关闭后消失。 问题是每当我再次按住鼠标按钮 1 时,矩形都不会出现。
第一个 class:
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);
}
}
}
目前您正在尝试覆盖 JFrame 的绘制方法,这会带来两个问题,首先是 JFrame 是一个重量级组件(它有一个标题栏和许多您需要考虑的相关内容)所以您可能有没完没了的问题,第二个问题是您需要覆盖您希望在其上执行自定义绘画的组件的paintComponent
方法。
这里的解决方案是在 JFrame 中放置一个 JPanel,并覆盖 JPanel 的paintComponent 方法。
下面是一个工作示例,它创建一个新矩形并每半秒将其添加到框架中,但还通过将现有矩形添加到列表中并在每次重新绘制时在列表中绘制每个矩形来保留现有矩形。
主要的class很简单,把我们的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);
}
});
}
}
以及进行我们绘画的自定义面板 class:
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);
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.