【发布时间】:2021-08-17 10:33:18
【问题描述】:
我正在使用 Swing 框架开发 Java GUI 应用程序,我需要在模拟 LCD 显示的 JTextArea 中显示一些文本。
文本的每个字符通过 Swing Timer 每 250 毫秒附加一次,但是,如果我不将鼠标悬停在 JTextArea 上,则更新不是恒定的。
这是我悬停的时候
这是我不悬停的时候
这是一个示例,基于定时器 on this answer
public class App {
public static class LCDisplay extends JTextArea {
public LCDisplay() {
super(1, 20);
setEditable(false);
Font font = new Font(Font.MONOSPACED, Font.PLAIN, 50);
setFont(font);
setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
setForeground(Color.GREEN);
setBackground(Color.BLUE);
}
}
public static void main(String[] args) {
LCDisplay display = new LCDisplay();
display.setText(" ");
display.setBorder(BorderFactory.createLineBorder(Color.BLACK, 10, false));
Function<String, Boolean> setLCDisplayText = text -> {
int displayTextLength = display.getText().length();
try {
display.setText(display.getText(1, displayTextLength - 1));
} catch (BadLocationException e) {
e.printStackTrace();
}
display.append(text);
return display.getText().trim().isEmpty();
};
StringBuilder sb = new StringBuilder("Colore rosso");
for(int i=0; i<20; i++) {sb.append(' ');}
int interval = 250;
AtomicInteger supIndex = new AtomicInteger(0);
AtomicLong expected = new AtomicLong(Instant.now().toEpochMilli() + interval);
Timer slideText = new Timer(0, e -> {
int drift = (int) (Instant.now().toEpochMilli() - expected.get());
boolean exceeded = setLCDisplayText.apply(sb.charAt(supIndex.getAndIncrement()) + "");
if (exceeded) {
supIndex.set(0);
}
Timer thisTimer = (Timer) e.getSource();
expected.addAndGet(interval);
thisTimer.setInitialDelay(Math.max(0, interval - drift));
thisTimer.restart();
});
JFrame frame = new JFrame("app");
frame.add(display);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
slideText.start();
}
}
也许我做错了什么,但我真的不知道如何解决。
提前致谢。
【问题讨论】:
-
为了尽快获得更好的帮助,edit 添加一个minimal reproducible example 或Short, Self Contained, Correct Example(相对于两个或多个无法编译的代码sn-ps)。
-
更新不是恒定的。 - 当我查看您的第二张图片时,在我看来,有时 2 个字符会从左侧显示中删除。我想这就是你所说的不恒定的意思。在 Windows 10 上使用 JDK11 时,我没有看到这种行为。Swing 是单线程的,所有 GUI 代码都应该在 EDT 上执行。从计时器调用的代码在 EDT 上调用,我认为您不需要所有“原子”逻辑。
-
@camickr 看来这是我的 Debian 10 安装的问题:我在 Windows 上进行了测试,没有原子逻辑,它运行良好。无论如何,感谢您的帮助。