[英]How to repaint JComponent once after several repaint()?
我的程序在 JButton 列表上循環。 對於每個 JButton,它每秒重新繪制它:
public class a {
static JFrame frame = new JFrame();
static Set<MyButton> components = new HashSet<MyButton>();
public static void main(String[] args) {
JPanel lPanel = new JPanel(new GridLayout(0,18));
for (int i = 0; i < 500; i++) {
MyButton lButton = new MyButton("Hello" + i);
lPanel.add(lButton);
components.add(lButton);
}
frame.add(lPanel);
frame.pack();
frame.setVisible(true);
blinking();
}
public static void blinking() {
Timer blinkTimer = new Timer(500, new ActionListener() {
boolean on = false;
public void actionPerformed(ActionEvent e) {
for (MyButton lButton : components) {
lButton.blink(on);
}
on = !on;
}
});
blinkTimer.start();
}
}
public class MyButton extends JButton {
public MyButton(String text) {
super(text);
}
public void blink(boolean on) {
setBackground(on ? Color.DARK_GRAY : Color.LIGHT_GRAY);
setForeground(on ? Color.WHITE : Color.BLACK);
}
}
我想確保所有按鈕同時更新它們的背景和前景色。
JButton extends JComponent
, JComponent.setBackground
調用repaint()
,以及JComponent.setForeground
。
因此,我的程序每秒為每個按鈕調用兩次repaint()
,並且顏色並不總是同時更新。
如何確保所有按鈕的顏色同時更新? 我認為解決方案是只調用一個repaint()
,也許在按鈕容器上,但我該怎么做?
按鈕是否都在面板的同一層? 那么為什么不使用該圖層的背景而不是按鈕的背景呢?
例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
private static JButton newButton() {
final JButton b = new JButton("x");
b.setContentAreaFilled(false);
//b.setOpaque(false); //Do not make this call, because setContentAreaFilled documentation says so.
return b;
}
public static void main(final String[] args) {
final JButton tester = newButton();
final Dimension testerDim = tester.getPreferredSize();
final Dimension maxDim = new Dimension(1200, 700);
final int rows = maxDim.width / testerDim.width,
cols = maxDim.height / testerDim.height;
final JPanel buttonPanel = new JPanel(new GridLayout(0, cols));
final int n = rows * cols;
buttonPanel.add(tester);
for (int i = 1; i < n; ++i)
buttonPanel.add(newButton());
final JFrame frame = new JFrame("Button grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buttonPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
final Color bg = buttonPanel.getBackground();
final Timer timer = new Timer(500, new ActionListener() {
private boolean on = false;
@Override
public void actionPerformed(final ActionEvent e) {
buttonPanel.setBackground(on? bg: bg.darker());
on = !on;
}
});
timer.setRepeats(true);
timer.start();
}
}
我認為這是單核/線程所能做的最好的事情。
此外,如果您想要按鈕之間的其他組件,它們的背景與圖層的背景不同,那么只需使它們不透明( setOpaque(true)
),如果它們還沒有。
解決方案:使用setIgnoreRepaint()
並僅重繪框架:
frame.setIgnoreRepaint(true);
for (JButton lButton : components) {
// blink the buttons background on and off
lButton.blink(on);
}
frame.setIgnoreRepaint(false);
frame.repaint();
on = !on;
setIgnoreRepaint 文檔有點誤導,因為它說要暫停系統事件的重繪。 所以我們正在考慮操作系統可以發送的事件。 但實際上它忽略了重繪(隱式或顯式),並且不會直接忽略組件上的方法調用(paint /paintImmediately ...所有這些)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.