Swing - Обновить ярлык
У меня есть метка сообщения и кнопка отправки. Кнопка отправки будет нажата несколько раз, и действие для каждого нажатия может занять до минуты.
Когда кнопка нажата, я хочу, чтобы сообщение было пустым, и после завершения задачи я хочу установить сообщение "Завершить".
private void submitActionPerformed(java.awt.event.ActionEvent evt) {
message = "";
updateMessageLabel();
doTheTask();
/* this update is apply to the label after completion */
message = "Complete";
}
Возможно ли обновить эту метку сообщения до запуска метода submitActionPerformed()
(или в методе), но после нажатия кнопки?
Ответы
Ответ 1
Да, вы можете сделать это с помощью потока SwingWorker
, выполнить все операции pre submitActionPerformed()
, такие как обновление метки, в методе execute()
currentThread
и вызвать doTheTask()
в качестве фонового задания с использованием рабочего Thread
.
Я предлагаю вам ознакомиться с этой документацией для справки о SwingWorker Thread
Ответ 2
Хотя Swing concurrency учебник уже содержит некоторые очень хорошие примеры того, как справляться с concurrency в Swing, найдите ниже пример, который
- содержит флажок, подтверждающий, что пользовательский интерфейс все еще жив
- имеет индикатор выполнения, который обновляется с
SwingWorker
-
имеет метку, которая обновляется после завершения SwingWorker
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class SwingWorkerExample {
private static JProgressBar PROGRESS_BAR;
private static JLabel OUTPUT_LABEL;
private static JFrame createGUI(){
JFrame testFrame = new JFrame( "TestFrame" );
PROGRESS_BAR = new JProgressBar( );
PROGRESS_BAR.setMinimum( 0 );
PROGRESS_BAR.setMaximum( 100 );
OUTPUT_LABEL = new JLabel( "Processing" );
testFrame.getContentPane().add( PROGRESS_BAR, BorderLayout.CENTER );
testFrame.getContentPane().add( OUTPUT_LABEL, BorderLayout.SOUTH );
//add a checkbox as well to proof the UI is still responsive
testFrame.getContentPane().add( new JCheckBox( "Click me to proof UI is responsive" ), BorderLayout.NORTH );
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
return testFrame;
}
public static void main( String[] args ) throws InvocationTargetException, InterruptedException {
EventQueue.invokeAndWait( new Runnable() {
@Override
public void run() {
JFrame frame = createGUI();
frame.pack();
frame.setVisible( true );
}
} );
//start the SwingWorker outside the EDT
MySwingWorker worker = new MySwingWorker( PROGRESS_BAR, OUTPUT_LABEL );
worker.execute();
}
private static class MySwingWorker extends SwingWorker<String, Double>{
private final JProgressBar fProgressBar;
private final JLabel fLabel;
private MySwingWorker( JProgressBar aProgressBar, JLabel aLabel ) {
fProgressBar = aProgressBar;
fLabel = aLabel;
}
@Override
protected String doInBackground() throws Exception {
int maxNumber = 10;
for( int i = 0; i < maxNumber; i++ ){
Thread.sleep( 2000 );//simulate long running process
double factor = ((double)(i+1) / maxNumber);
System.out.println("Intermediate results ready");
publish( factor );//publish the progress
}
return "Finished";
}
@Override
protected void process( List<Double> aDoubles ) {
//update the percentage of the progress bar that is done
int amount = fProgressBar.getMaximum() - fProgressBar.getMinimum();
fProgressBar.setValue( ( int ) (fProgressBar.getMinimum() + ( amount * aDoubles.get( aDoubles.size() - 1 ))) );
}
@Override
protected void done() {
try {
fLabel.setText( get() );
} catch ( InterruptedException e ) {
e.printStackTrace();
} catch ( ExecutionException e ) {
e.printStackTrace();
}
}
}
}