使用 TimerTask 移动 JPanel
Moving JPanels using TimerTask
所以我已经设置了一个 Java GUI,如下图所示(为可怕的绘画游戏道歉):
Java GUI 的布局
所有 JPanel 的大小都相同(未在图中很好地显示)。我想要做的是,当我用进度条做某事时(即读取一些文本文件),JPanels 将循环通过。红色的会往下走,橙色的会往上走,如此循环往复。我希望它们每半秒更改一次,并在程序打开后等待 2 秒开始移动。我还希望它们在其中一个进度条达到 100% 时停止。
读了一些书后,我认为 Java TimerTask class 很适合这个,但我没有这方面的经验,也不太确定我将如何着手做某事像这样。
任何有关如何进行此操作的提示或想法将不胜感激!
保留颜色模型(和文本,如果 'Red JPanel' 是用户看到的内容的一部分)并简单地更改现有面板的 BG 颜色以适合用作计数器的颜色会简单得多这些颜色(/文本)组合的数组的索引。
如@MadProgrammer 所述,Swing Timer
会更合适,因为 Swing 计时器可确保在 EDT 上进行更新。或者更确切地说是两个计时器。第一个是延迟两秒的单发计时器。第二个会循环颜色。
像这样(根据需要调整颜色和数字):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class ColorCycler {
private JComponent ui = null;
Color[] colors = {
Color.RED,
Color.ORANGE,
Color.YELLOW,
Color.GREEN,
Color.CYAN.darker(),
Color.MAGENTA.darker(),
Color.MAGENTA.darker().darker()
};
int counter = 0;
JPanel[] panels = new JPanel[colors.length];
ColorCycler() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
ui.setBackground(Color.CYAN);
ui.add(new JLabel(
"Clock", SwingConstants.CENTER), BorderLayout.PAGE_START);
ui.add(new JLabel(
"Progress Bars", SwingConstants.CENTER), BorderLayout.PAGE_END);
JPanel colorPanel = new JPanel(new GridLayout(0, 1));
Border border = new EmptyBorder(new Insets(10, 200, 10, 200));
for (int ii=0; ii<colors.length; ii++) {
JPanel p = new JPanel();
p.setBorder(border);
panels[ii] = p;
colorPanel.add(p);
}
ui.add(colorPanel, BorderLayout.CENTER);
ActionListener colorListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter++;
setColors();
}
};
final Timer colorCycleTimer = new Timer(50, colorListener);
ActionListener delayListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
colorCycleTimer.start();
}
};
Timer delayTimer = new Timer(2000, delayListener);
delayTimer.setRepeats(false);
delayTimer.start();
setColors();
}
private void setColors() {
for (int ii=0; ii<colors.length; ii++) {
panels[(counter+ii)%colors.length].setBackground(colors[ii]);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ColorCycler o = new ColorCycler();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
所以我已经设置了一个 Java GUI,如下图所示(为可怕的绘画游戏道歉):
Java GUI 的布局
所有 JPanel 的大小都相同(未在图中很好地显示)。我想要做的是,当我用进度条做某事时(即读取一些文本文件),JPanels 将循环通过。红色的会往下走,橙色的会往上走,如此循环往复。我希望它们每半秒更改一次,并在程序打开后等待 2 秒开始移动。我还希望它们在其中一个进度条达到 100% 时停止。
读了一些书后,我认为 Java TimerTask class 很适合这个,但我没有这方面的经验,也不太确定我将如何着手做某事像这样。
任何有关如何进行此操作的提示或想法将不胜感激!
保留颜色模型(和文本,如果 'Red JPanel' 是用户看到的内容的一部分)并简单地更改现有面板的 BG 颜色以适合用作计数器的颜色会简单得多这些颜色(/文本)组合的数组的索引。
如@MadProgrammer 所述,Swing Timer
会更合适,因为 Swing 计时器可确保在 EDT 上进行更新。或者更确切地说是两个计时器。第一个是延迟两秒的单发计时器。第二个会循环颜色。
像这样(根据需要调整颜色和数字):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class ColorCycler {
private JComponent ui = null;
Color[] colors = {
Color.RED,
Color.ORANGE,
Color.YELLOW,
Color.GREEN,
Color.CYAN.darker(),
Color.MAGENTA.darker(),
Color.MAGENTA.darker().darker()
};
int counter = 0;
JPanel[] panels = new JPanel[colors.length];
ColorCycler() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
ui.setBackground(Color.CYAN);
ui.add(new JLabel(
"Clock", SwingConstants.CENTER), BorderLayout.PAGE_START);
ui.add(new JLabel(
"Progress Bars", SwingConstants.CENTER), BorderLayout.PAGE_END);
JPanel colorPanel = new JPanel(new GridLayout(0, 1));
Border border = new EmptyBorder(new Insets(10, 200, 10, 200));
for (int ii=0; ii<colors.length; ii++) {
JPanel p = new JPanel();
p.setBorder(border);
panels[ii] = p;
colorPanel.add(p);
}
ui.add(colorPanel, BorderLayout.CENTER);
ActionListener colorListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter++;
setColors();
}
};
final Timer colorCycleTimer = new Timer(50, colorListener);
ActionListener delayListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
colorCycleTimer.start();
}
};
Timer delayTimer = new Timer(2000, delayListener);
delayTimer.setRepeats(false);
delayTimer.start();
setColors();
}
private void setColors() {
for (int ii=0; ii<colors.length; ii++) {
panels[(counter+ii)%colors.length].setBackground(colors[ii]);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ColorCycler o = new ColorCycler();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}