Wiele czytałem na temat Swing, threading, invokeLater(), SwingWorker, itp., Ale po prostu nie mogę tego zrozumieć, więc starałem się stworzyć naprawdę prosty program do zilustrowania . Przyjrzałem się wielu przykładom, ale żaden z nich nie pokazuje, co próbuję zrobić. Minęło sporo czasu, odkąd programowałem w Javie (ja naprawdę nie zrobiłem nic w Javie odkąd wziąłem AP Computer Science w liceum w 2003 roku), więc proszę o mnie.Czy aktualizuję komponent Swing poza EDT?
Oto, co próbuję zrobić w moim przykładzie. Mam przycisk i etykietę, a kiedy kliknę przycisk, chcę, aby program zatrzymał się na 3 sekundy przed dodaniem kropki do tekstu etykiety. Przez te 3 sekundy chcę, aby interfejs graficzny wyglądał normalnie i nadal odpowiadał na dodatkowe kliknięcia. Oto co napisał:
import javax.swing.SwingWorker;
public class NewJFrame extends javax.swing.JFrame
{
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
public NewJFrame()
{
initComponents();
}
private void initComponents()
{
jButton1 = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("Button");
jButton1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
jButton1ActionPerformed(evt);
}
});
getContentPane().add(jButton1, java.awt.BorderLayout.CENTER);
jLabel1.setText("Text");
getContentPane().add(jLabel1, java.awt.BorderLayout.PAGE_END);
pack();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
SwingWorker worker=new SwingWorker()
{
protected Object doInBackground()
{
try{Thread.sleep(3000);}
catch (InterruptedException ex){}
return null;
}
};
worker.execute();
jLabel1.setText(jLabel1.getText()+".");
}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run(){ new NewJFrame().setVisible(true); }
});
}
}
z tego kodu, jeśli kliknę przycisk, okres jest natychmiast dołączone do etykiety, która ma sens dla mnie, ponieważ tworzę i spanie wątek tła, pozostawiając EDT dostępne do natychmiastowej aktualizacji etykiety. Więc próbowałem to:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
Thread thread = new Thread();
try{ thread.sleep(3000);}
catch (InterruptedException ex){}
jLabel1.setText(jLabel1.getText()+".");
}
To prawie działa oprócz który blokuje IT EDT powodując niebieski przycisk, aby włączyć na trzy sekundy przed dołączeniem okres do tekstu etykiety. Nie chcę przycisk, aby wyglądać jak to jest naciskany przez całe trzy sekundy, kiedy to było naprawdę tylko kliknął szybko, więc próbowałem to:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
SwingWorker worker=new SwingWorker()
{
protected Object doInBackground()
{
try{Thread.sleep(3000);}
catch (InterruptedException ex){}
jLabel1.setText(jLabel1.getText()+".");
return null;
}
};
worker.execute();
}
To wydaje się działać, ale nie są mi dzwoni jLabel1 .setText (...) z wątku tła, a nie EDT, a zatem łamiąc regułę "Swing Single Threading Rule?" Jeśli tak, czy istnieje lepszy sposób osiągnięcia pożądanego efektu? Jeśli nie, proszę wyjaśnić, dlaczego?
+1 za wysiłek i badania !! – MadProgrammer