gpt4 book ai didi

java - 在程序运行时使JPanel中的Timer保持 Activity 状态

转载 作者:行者123 更新时间:2023-12-03 12:59:30 25 4
gpt4 key购买 nike

我在名为MainFrame的类中创建了一个GUI。 GUI的JPanel之一以秒为单位显示当前时间和日期。当用户决定使用GUI分析数据时,它将调用一个处理数据的类。发生数据处理时,计时器暂停,然后在数据处理结束时恢复计时。即使程序正在运行,如何使计时器连续运行?计时器是它自己的线程,但是我不知道在哪里为JPanel启动线程。
这是一些代码片段

App.java(用于启动整个GUI的应用程序)

public class App {

public static void main(String[] args) {

try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {

public void run() {
new MainFrame();
}
});
}

}

MainFrame(处理JPanels和dataprocess impl的类)
public class MainFrame extends JFrame {

private DataProcess dataProcess = null;
...
...
private StatusPanel statusPanel;
...
...
public MainFrame() {
...
setJMenuBar(createFrameMenu());

initializeVariables();
constructLayout();
createFileChooser();
constructAppWindow();
}

private void initializeVariables() {

this.dataProcess = new DataProcess();
...
this.statusPanel = new StatusPanel();
...
}
private void constructLayout() {
JPanel layoutPanel = new JPanel();
layoutPanel.setLayout(new GridLayout(0, 3));
layoutPanel.add(dataControlsPanel());

setLayout(new BorderLayout());
add(layoutPanel, BorderLayout.CENTER);
add(statusPanel, BorderLayout.PAGE_END);
}

StatusPanel(显示计时器等的面板)
public class StatusPanel extends JPanel {

private static final long serialVersionUID = 1L;
private JLabel statusLabel;
private JLabel timeLabel;

private Timer timer;

public StatusPanel() {
initializeVariables();
constructLayout();
startTimer();
}

private void constructLayout() {
setLayout(new FlowLayout(FlowLayout.CENTER));
add(statusLabel);// , FlowLayout.CENTER
add(timeLabel);
}

public void startTimer() {
this.timer.start();
}

public void stopTimer() {
this.timer.setRunning(false);
}

private void initializeVariables() {
this.statusLabel = new JLabel();
this.timeLabel = new JLabel();
this.statusLabel.setText(StringConstants.STATUS_PANEL_TEXT);
this.timer = new Timer(timeLabel);
}

}

Timer.java(StatusPanel中使用的计时器)
public class Timer extends Thread {

private boolean isRunning;
private JLabel timeLabel;
private SimpleDateFormat timeFormat;

public Timer(JLabel timeLabel) {
initializeVariables(timeLabel);
}

private void initializeVariables(JLabel timeLabel) {
this.timeLabel = timeLabel;
this.timeFormat = new SimpleDateFormat("HH:mm:ss dd-MM-yyyy");
this.isRunning = true;
}

@Override
public void run() {
while (isRunning) {
Calendar calendar = Calendar.getInstance();
Date currentTime = calendar.getTime();
timeLabel.setText(timeFormat.format(currentTime));

try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}

public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}

}

数据处理是通过使用 Action 监听器在dataControlsPanel中完成的。

最佳答案

When the user decides to use the GUI to analyze data, it invokes a class that processes data. When the data process is happening, the timer pauses, then resumes when the dataprocess is over. How can I have the timer continuously run even if the program is running



首先,您的计时器应该是 javax.swing.Timer或“Swing”计时器。这是专门为在Swing事件线程上运行而设计的,因此应避免当前代码显示的许多Swing线程问题(例如,在此处: timeLabel.setText(timeFormat.format(currentTime));),这会从后台线程进行Swing调用,这是危险代码。下一个
处理代码应该输入到SwingWorker中。当工作程序执行时,您可以通过在计时器上调用 stop()来暂停Swing计时器,或者干脆让计时器继续运行。当SwingWorker完成 Action 后-我通常会在添加到SwingWorker的PropertyChangeListener上监听某些内容,监听其 state属性更改为 SwingWorker.StateValue.DONE,在worker上调用 get()以提取其持有的所有数据,更重要的是捕获任何异常可能会抛出。

例如:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyApp extends JPanel {
// display the date/time
private static final String DATE_FORMAT = "HH:mm:ss dd-MM-yyyy";
private static final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);

// timer updates measures seconds, but updates every 0.2 sec's to be sure
private static final int TIMER_DELAY = 200;

// JLabel that shows the date/time
private JLabel timeLabel = new JLabel("", SwingConstants.CENTER);

// JButton's Action / listener. This starts long-running data processing
private Action dataProcessAction = new DataProcessAction("Process Data");

// the SwingWorker that the above Action executes:
private LongRunningSwProcess longRunningProcess;

// label to display the count coming from the process above
private JLabel countLabel = new JLabel("00");

public MyApp() {
// create a simple GUI
JPanel dataProcessingPanel = new JPanel();
dataProcessingPanel.add(new JButton(dataProcessAction)); // button that starts process
dataProcessingPanel.add(new JLabel("Count:"));
dataProcessingPanel.add(countLabel);

setLayout(new BorderLayout());
add(timeLabel, BorderLayout.PAGE_START);
add(dataProcessingPanel);
showTimeLabelCurrentTime();
// create and start Swing Timer
new Timer(TIMER_DELAY, new TimerListener()).start();
}

// display count from swing worker
public void setCount(int newValue) {
countLabel.setText(String.format("%02d", newValue));
}

// clean up code after SwingWorker finishes
public void longRunningProcessDone() {
// re-enable JButton's action
dataProcessAction.setEnabled(true);
if (longRunningProcess != null) {
try {
// handle any exceptions that might get thrown from the SW
longRunningProcess.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

// display the current time in our timeLabel JLabel
private void showTimeLabelCurrentTime() {
long currentTime = System.currentTimeMillis();
Date date = new Date(currentTime);
timeLabel.setText(dateFormat.format(date));
}

// Timer's ActionListener is simple -- display the current time in the timeLabel
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
showTimeLabelCurrentTime();
}
}

// JButton's action. This starts the long-running SwingWorker
private class DataProcessAction extends AbstractAction {

public DataProcessAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}

@Override
public void actionPerformed(ActionEvent e) {
setEnabled(false); // first disable the button's action
countLabel.setText("00"); // reset count label

// then create SwingWorker and listen to its changes
longRunningProcess = new LongRunningSwProcess();
longRunningProcess.addPropertyChangeListener(new DataProcessListener());

// execute the swingworker
longRunningProcess.execute();
}
}

// listen for state changes in our SwingWorker
private class DataProcessListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(LongRunningSwProcess.COUNT)) {
setCount((int)evt.getNewValue());
} else if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
longRunningProcessDone();
}
}
}

private static void createAndShowGui() {
JFrame frame = new JFrame("My App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyApp());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// mock up of SwingWorker for long-running action
class LongRunningSwProcess extends SwingWorker<Void, Integer> {
public static final String COUNT = "count";
private static final int MIN_TIME_OUT = 5;
private static final int MAX_TIME_OUT = 10;
private int count = 0;

@Override
protected Void doInBackground() throws Exception {
// all this mock up does is increment a count field
// every second until timeOut reached
int timeOut = MIN_TIME_OUT + (int) (Math.random() * (MAX_TIME_OUT - MIN_TIME_OUT));
for (int i = 0; i < timeOut; i++) {
setCount(i);
TimeUnit.SECONDS.sleep(1);
}
return null;
}

// make count a "bounded" property -- one that will notify listeners if changed
public void setCount(int count) {
int oldValue = this.count;
int newValue = count;
this.count = newValue;
firePropertyChange(COUNT, oldValue, newValue);
}

public int getCount() {
return count;
}
}

关于java - 在程序运行时使JPanel中的Timer保持 Activity 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44663163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com