[英]Painting inside Swing Timer not working
我之前從未使用過Timer
,所以我的問題可能真的很愚蠢。 我的程序繪制一個紅色的圓圈,隨機秒后圓圈應將其顏色更改為綠色。 我剛剛制作了一個擺動計時器,你可以在下面的代碼中看到。 它進入actionPerformed()
方法,但它不會改變顏色。 你能幫我改變一下顏色嗎?
我的代碼:
package igrica;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ChangingCircle implements ActionListener{
JFrame frame;
Timer timer;
Random r;
public static void main(String[] args) {
ChangingCircle gui = new ChangingCircle();
gui.go();
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillOval(100, 100, 100, 100);
Random r = new Random();
Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.println("Timer out");
g.setColor(Color.green);
g.fillOval(100, 100, 100, 100);
}
});
timer.start();
}
}
}
你的代碼中有很多混亂。 試試這個:
public class ChangingCircle {
Color color = Color.RED;
MyPanel panel = new MyPanel();
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
ChangingCircle gui = new ChangingCircle();
gui.go();
});
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
Random r = new Random();
Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.println("Timer");
color = Color.GREEN;
panel.repaint();
}
});
timer.setRepeats(false);
timer.start();
}
class MyPanel extends JPanel {
private int size = 100, loc = 100;
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillOval(loc, loc, size, size);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(size + loc, size + loc);
}
}
}
這個想法是計時器只改變要繪制的形狀的屬性,然后調用repaint()
來反映變化。 只要需要,就會調用paintComponent
,即使是快速連續也應該快速返回。
具體說明:
paintComponent
外部創建並啟動計時器,因為它被多次調用並且將創建並啟動許多計時器。 super.paintComponent(g);
作為paintComponent
內部的第一件事。 ActionListener
。 一般提示:
@Override
注釋。 pack()
而不是手動設置其大小,並@Override
您繪制的組件的getPreferredSize
方法。 根據您繪制的內容返回有意義的大小。 add(component, location)
而不是相反(不建議使用)。 Random r
)。 Color.RED
而不是Color.red
)。 不要在paintComponent方法中啟動Timer。 此方法僅適用於繪畫和繪畫。 而是在構造函數中啟動Timer並在Timer的actionPerromed中調用repaint()
,更改類的字段的狀態,並使用paintComponent中的該信息使用該字段來繪制任何新信息。
例如
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ChangingCircle {
JFrame frame;
public static void main(String[] args) {
ChangingCircle gui = new ChangingCircle();
gui.go();
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
class MyPanel extends JPanel {
private Random r = new Random();
private boolean draw = false;
public MyPanel() {
Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
draw = true;
repaint();
}
});
timer.setRepeats(false);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (draw) {
g.setColor(Color.red);
g.fillOval(100, 100, 100, 100);
}
}
}
}
另外,不要忘記在覆蓋中調用super的paintComponent方法。
如果你需要改變顏色,給JPanel一個Color字段,比如叫做color
並從Timer中改變它的值,然后調用repaint()
。 同樣在paintComponent中,使用該字段的值來繪制橢圓。 同樣在這種情況下,Timer 應該重復,所以在那種情況下擺脫timer.setRepeats(false)
。
計時器異步工作, paintComponent
在完成計時器工作之前完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.