我正在為我的 Tic Tac Toe 專案撰寫一個 GUI,我很高興玩弄像下面這樣的小視覺效果。每次用戶設定 CPU 播放器并單擊完成按鈕忘記設定 CPU 強度級別時,我都會以與下面的代碼示例相同的方式顯示一條警告訊息。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TestingStuff implements ActionListener {
JLabel myLabel;
JFrame myFrame;
JButton myButton;
JPanel myPanel;
public TestingStuff() {
myFrame = new JFrame("Hello");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
myPanel.setBackground(Color.DARK_GRAY);
myFrame.add(myPanel, BorderLayout.CENTER);
myLabel = new JLabel("Hi dear stackoverflow coders!");
myLabel.setFont(new Font("MV Boli", Font.BOLD, 15));
myLabel.setForeground(Color.GREEN);
myPanel.add(myLabel);
myButton = new JButton("Click me like there's no tomorrow!");
myButton.addActionListener(this);
myFrame.add(myButton, BorderLayout.SOUTH);
myFrame.pack();
myFrame.setLocationRelativeTo(null);
myFrame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
int timerDelay = 1;
Timer blinkTimer = new Timer(timerDelay, new ActionListener() {
private int count = 0;
private int maxTime = 30;
private String hello = myLabel.getText();
private int len = hello.length();
private String s;
public void actionPerformed(ActionEvent e) {
if (count * timerDelay >= maxTime) {
((Timer) e.getSource()).stop();
} else {
myLabel.setVisible(true);
if (count < len) {
s = hello.substring(0, count 1);
myLabel.setText(s);
}
count ;
}
}
});
blinkTimer.start();
}
public static void main(String[] args) {
TestingStuff foo = new TestingStuff();
}
}
嘗試反復點擊按鈕。
點擊前: 
點擊后: 
至少在我的機器上。由于用戶沒有理由重復點擊完成按鈕,我并不太擔心,但仍然......我想我最終會禁用用戶在那個短影片期間可以點擊的每個按鈕以避免意外行為。我的問題:誰能解釋一下發生了什么,以及為什么我在快速點擊 7 到 8 次后就能看到被截斷的文本?
uj5u.com熱心網友回復:
更新之間的延遲設定為1毫秒(幸運的是它是如此準確??),所以整個影片在大約 30 毫秒內完成。
相反,嘗試將其設定為 30 毫秒(大約 1 秒的運行時間)
我也會廢除maxTime, 你只想繼續回圈直到你得到所有的文本,否則它有點毫無意義(恕我直言)
也許像...
int timerDelay = 30;
Timer blinkTimer = new Timer(timerDelay, new ActionListener() {
private int count = 0;
private String hello = myLabel.getText();
private String s;
public void actionPerformed(ActionEvent e) {
if (count >= hello.length()) {
System.out.println("Done");
((Timer) e.getSource()).stop();
} else {
System.out.println("Hello");
myLabel.setVisible(true);
s = hello.substring(0, count 1);
myLabel.setText(s);
count ;
}
}
});
blinkTimer.start();
基于時間的影片
現在,如果您更喜歡基于時間的影片,它可能看起來像這樣。
這設定為運行 1 秒,它將使用“進度”計算來確定應顯示多少文本
Timer blinkTimer = new Timer(5, new ActionListener() {
private String title = myLabel.getText();
private Duration runtime = Duration.ofSeconds(1);
private Instant startTime;
public void actionPerformed(ActionEvent e) {
if (startTime == null) {
startTime = Instant.now();
}
Duration between = Duration.between(startTime, Instant.now());
double progress = between.toMillis() / (double)runtime.toMillis();
if (progress >= 1.0) {
((Timer) e.getSource()).stop();
// Just make sure the text is up-to-date
myLabel.setText(title);
} else {
int count = (int)(title.length() * progress);
String text = title.substring(0, count);
myLabel.setText(text);
}
}
});
blinkTimer.start();
“順便說一句,嘗試使用您的代碼并反復單擊按鈕:我仍然得到相同的結果”
你不斷地創造新的Timers,它們會相互補充。相反,要么禁用按鈕要么停止當前運行Timer,例如...
禁用按鈕...
@Override
public void actionPerformed(ActionEvent e) {
myButton.setEnabled(false);
Timer blinkTimer = new Timer(5, new ActionListener() {
private String title = myLabel.getText();
private Duration runtime = Duration.ofSeconds(1);
private Instant startTime;
public void actionPerformed(ActionEvent e) {
if (startTime == null) {
startTime = Instant.now();
}
Duration between = Duration.between(startTime, Instant.now());
double progress = between.toMillis() / (double) runtime.toMillis();
if (progress >= 1.0) {
((Timer) e.getSource()).stop();
// Just make sure the text is up-to-date
myLabel.setText(title);
myButton.setEnabled(true);
} else {
int count = (int) (title.length() * progress);
String text = title.substring(0, count);
myLabel.setText(text);
}
}
});
blinkTimer.start();
}
取消活動定時器
private Timer blinkTimer;
@Override
public void actionPerformed(ActionEvent e) {
if (blinkTimer != null) {
blinkTimer.stop();
blinkTimer = null;
}
blinkTimer = new Timer(5, new ActionListener() {
private String title = myLabel.getText();
private Duration runtime = Duration.ofSeconds(1);
private Instant startTime;
public void actionPerformed(ActionEvent e) {
if (startTime == null) {
startTime = Instant.now();
}
Duration between = Duration.between(startTime, Instant.now());
double progress = between.toMillis() / (double) runtime.toMillis();
if (progress >= 1.0) {
((Timer) e.getSource()).stop();
// Just make sure the text is up-to-date
myLabel.setText(title);
myButton.setEnabled(true);
} else {
int count = (int) (title.length() * progress);
String text = title.substring(0, count);
myLabel.setText(text);
}
}
});
blinkTimer.start();
}
和...
哦???♂? - 不要使用標簽文本作為標簽顯示的初始文本 - 使用你可以控制的東西,否則你會將不完整的文本重新植入影片中
private String greetingText = "Hi dear stackoverflow coders!";
private Timer blinkTimer;
@Override
public void actionPerformed(ActionEvent e) {
if (blinkTimer != null) {
blinkTimer.stop();
blinkTimer = null;
}
blinkTimer = new Timer(5, new ActionListener() {
private String title = greetingText;
private Duration runtime = Duration.ofSeconds(5);
private Instant startTime;
public void actionPerformed(ActionEvent e) {
if (startTime == null) {
startTime = Instant.now();
}
Duration between = Duration.between(startTime, Instant.now());
double progress = between.toMillis() / (double) runtime.toMillis();
System.out.println(hashCode() " " progress);
if (progress >= 1.0) {
((Timer) e.getSource()).stop();
// Just make sure the text is up-to-date
myLabel.setText(title);
myButton.setEnabled(true);
} else {
int count = (int) (title.length() * progress);
String text = title.substring(0, count);
myLabel.setText(text);
}
}
});
blinkTimer.start();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/379651.html
