使用 wait() 动态更改组件背景颜色
Changing Component Background color dynamically with wait()
我正在尝试做一个有趣的 JFrame
所以当鼠标离开 window 时,它会将面板 Background
颜色更改为一些随机颜色(以引起用户注意):
wnd.addMouseListener(new MouseAdapter(){
@Override
public synchronized void mouseExited(MouseEvent e){
cond = true;
while(cond){
try{
wnd.getContentPane().setBackground(Color.getHSBColor((cont+=0.05), 1, 1));
wnd.setTitle("Num: "+cont);
wnd.getContentPane().repaint(); //With or without it doesn't work either
wait(100);
}
catch(InterruptedException ex){ Thread.currentThread().interrupt(); }
}
}
});
问题是 Background
颜色没有改变...它向我显示了 window 标题中 cont 的值,但颜色没有改变。如果我删除循环并将鼠标移动到面板内外,它会发生变化......但我想让它在鼠标离开 window 时自动更改颜色,直到鼠标回到它.某种癫痫症 (?)
我不知道为什么如果我循环它并用 wait()
延迟它不起作用。
Swing 是一个单线程框架,这意味着任何阻塞事件调度线程的东西都会阻止它处理事件队列(包括重绘请求)并导致应用程序显示为已挂起,因为它有.
切勿在 EDT 上下文中执行长 运行 或阻塞操作。
相反,在这种情况下,您应该使用 Swing Timer
来安排定期回调。这样做的好处是回调是从 EDT 的上下文中执行的,因此可以安全地用于更新 UI(因为 Swing 也不是线程安全的)。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer updateTimer;
public TestPane() {
updateTimer = new Timer(100, new ActionListener() {
private float cont = 0;
@Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.getHSBColor((cont += 0.05), 1, 1));
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
updateTimer.start();
}
@Override
public void mouseEntered(MouseEvent e) {
updateTimer.stop();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
查看 Concurrency in Swing and How to use Swing Timers 了解更多详情
我正在尝试做一个有趣的 JFrame
所以当鼠标离开 window 时,它会将面板 Background
颜色更改为一些随机颜色(以引起用户注意):
wnd.addMouseListener(new MouseAdapter(){
@Override
public synchronized void mouseExited(MouseEvent e){
cond = true;
while(cond){
try{
wnd.getContentPane().setBackground(Color.getHSBColor((cont+=0.05), 1, 1));
wnd.setTitle("Num: "+cont);
wnd.getContentPane().repaint(); //With or without it doesn't work either
wait(100);
}
catch(InterruptedException ex){ Thread.currentThread().interrupt(); }
}
}
});
问题是 Background
颜色没有改变...它向我显示了 window 标题中 cont 的值,但颜色没有改变。如果我删除循环并将鼠标移动到面板内外,它会发生变化......但我想让它在鼠标离开 window 时自动更改颜色,直到鼠标回到它.某种癫痫症 (?)
我不知道为什么如果我循环它并用 wait()
延迟它不起作用。
Swing 是一个单线程框架,这意味着任何阻塞事件调度线程的东西都会阻止它处理事件队列(包括重绘请求)并导致应用程序显示为已挂起,因为它有.
切勿在 EDT 上下文中执行长 运行 或阻塞操作。
相反,在这种情况下,您应该使用 Swing Timer
来安排定期回调。这样做的好处是回调是从 EDT 的上下文中执行的,因此可以安全地用于更新 UI(因为 Swing 也不是线程安全的)。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer updateTimer;
public TestPane() {
updateTimer = new Timer(100, new ActionListener() {
private float cont = 0;
@Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.getHSBColor((cont += 0.05), 1, 1));
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
updateTimer.start();
}
@Override
public void mouseEntered(MouseEvent e) {
updateTimer.stop();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
查看 Concurrency in Swing and How to use Swing Timers 了解更多详情