[英]Two ScheduledExecutorService overriding eachother?
我正在嘗試使兩個閃爍的圓圈以不同的速度閃爍。 我在Circle類中使用ScheduledExecutorService來調節閃爍,並且其持續時間由每個Circle中的ms(毫秒)變量設置。
當我單獨制作一輛汽車時,它們以正確的速率閃爍(我將黑色的設置為1000ms,紅色的設置為10ms)。 但是,當我同時創建它們和將它們添加到JLayeredPane時,它們都在較短的時間內閃爍。
我對ScheduledExecutorService的使用不太熟悉,因此,如果有人可以幫助我解決出現的問題,將不勝感激!
import java.awt.Color;
import java.awt.Graphics;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.awt.*;
import javax.swing.*;
public class blinker extends JFrame
{
JLayeredPane lp = new JLayeredPane();
public carlight()
{
lp.setLayout(new BorderLayout());
lp.setPreferredSize(new Dimension(450, 450));
car c1 = new car(new Color(0, 0, 0), "1", 10, 0, 0);
c1.setOpaque(false);
car c2 = new car(new Color(255, 0, 0), "2", 1000, 100, 100);
c2.setOpaque(false);
c1.setBounds(0, 0, 450, 450);
c2.setBounds(0, 0, 450, 450);
lp.add(c2);
lp.add(c1);
add(lp);
setTitle("Carlights");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args)
{
carlight cl = new carlight();
}
}
class Circle extends JPanel
{
private Color color;
private String name;
private long ms;
private int x, y;
private boolean on = true;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
@Override
public void paintComponent(Graphics g)
{
super.paintComponents(g);
if(on)
{
g.setColor(color);
int r = 50;
g.fillOval(x, y, r, r);
on = false;
}
else
{
on = true;
}
}
public car(Color c, String s, long l, int x, int y)
{
color = c;
name = s;
ms = l;
this.x = x;
this.y = y;
this.service.scheduleAtFixedRate(new Runnable()
{
public void run()
{
repaint();
}
}, 0, ms, TimeUnit.MILLISECONDS);
}
}
您的問題是您在paintComponent方法中具有程序邏輯,您可以在其中更改布爾變量的狀態。 您無法完全控制何時或什至將調用此方法,實際上,在調用repaint時將同時調用兩個 paintComponents,這就是您的方向指示燈不起作用的原因。 解決方案:在其他位置更改boolean字段的狀態,從paintComponent方法中獲取邏輯。 另外,您將需要使用Swing計時器來獲得更好的Swing線程。
您還將希望修復布局的使用,包括避免使用setBounds。 與BorderLayout一起使用時,這在您的設置中特別危險且不可預測。 我自己,我不會讓Circle類擴展一個JPanel,而是使其成為一個邏輯類,而不是一個組件類,然后我會擁有一個繪圖組件,一個確實擴展了JPanel的類,保存Circle類的實例,然后將它們繪制在其paintComponent中。 例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class BlinkerEg extends JPanel {
private static final int PREF_W = 450;
private static final int PREF_H = PREF_W;
private List<Circle> circles = new ArrayList<>();
public BlinkerEg() {
circles.add(new Circle(Color.red, 1000, 0, 0, 450, this));
circles.add(new Circle(Color.black, 60, 0, 0, 450, this));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Circle circle : circles) {
circle.paint(g2);
}
}
private static void createAndShowGui() {
BlinkerEg mainPanel = new BlinkerEg();
JFrame frame = new JFrame("BlinkerEg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Circle {
private Color color;
private int x, y;
private int diam;
private JComponent component;
private boolean on = true;
public Circle(Color color, int ms, int x, int y, int diam, JComponent component) {
this.color = color;
this.x = x;
this.y = y;
this.diam = diam;
this.component = component;
new Timer(ms, new TimerListener()).start();
}
public void paint(Graphics g) {
if (on) {
g.setColor(color);
g.fillOval(x, y, diam, diam);
}
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
setOn(!isOn());
component.repaint();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.