[英]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.