[英]SwingWorker locks GUI on (unsuccessful) JLabel Icon updating
[英]Updating of JLabel not behaving properly inside SwingWorker thread
我試圖更新JLabel的一些預期行為,如 -
COND 1:JLabel應該顯示5秒鍾,然后它應該在接下來的3秒內不可見,然后它應該可見5秒鍾,依此類推。
COND 2:JLabel應該顯示0.5秒,然后對於接下來的3個secons應該是不可見的。
任何排列組合的種類,行為應該有效。 以下是示例代碼 -
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class Main
{
static CounterTask task;
public static void main ( String[] args )
{
final JLabel label = new JLabel( "TEST ME " );
JButton startButton = new JButton( "Start" );
startButton.addActionListener( new ActionListener()
{
public void actionPerformed ( ActionEvent e )
{
task = new CounterTask( label );
task.execute();
}
} );
JButton cancelButton = new JButton( "Cancel" );
cancelButton.addActionListener( new ActionListener()
{
public void actionPerformed ( ActionEvent e )
{
task.cancel( true );
}
} );
JPanel buttonPanel = new JPanel();
buttonPanel.add( startButton );
buttonPanel.add( cancelButton );
JPanel cp = new JPanel();
LayoutManager layout = new BoxLayout( cp, BoxLayout.Y_AXIS );
cp.setLayout( layout );
cp.add( buttonPanel );
cp.add( label );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setContentPane( cp );
frame.pack();
frame.setVisible( true );
}
}
class CounterTask
extends SwingWorker< Integer, Integer >
{
int DELAY = 3000;
JLabel label;
int WAIT = 5000;
public CounterTask ( JLabel label )
{
this.label = label;
}
@Override
protected Integer doInBackground () throws Exception
{
int i = 0;
int count = 1000;
while ( !isCancelled() && i < count )
{
i++;
publish( new Integer[] { i } );
label.setVisible( false );
Thread.sleep( DELAY );
}
return count;
}
protected void process ( List< Integer > chunks )
{
Integer strContent = chunks.get( chunks.size() - 1 );
label.setVisible( true );
label.validate();
label.setText( "DISPLAYING " + strContent );
try
{
Thread.sleep( WAIT );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
@Override
protected void done ()
{
if ( isCancelled() )
System.out.println( "Cancelled !" );
else
System.out.println( "Done !" );
}
}
我肯定做錯了,因為這種組合適用於某些數據,並且大多數JLabel在整個過程中變得不可見,但是如果我放置SOP,我會在適當的延遲和等待時間獲得適當的數據。
上面的Swing worker代碼有兩個變量WAIT,DELAY。 WAIT使JLabel可見X秒,DELAY使JLAbel在Y秒內不可見。 但如果嘗試不同的燙發和梳理,你會發現JLabel的可見性不能按預期工作。 這可能是因為標簽的EDT更新或與重繪有關的事情。 不確定根本原因。
預期:
- 想要使代碼像SOP一樣工作或理想情況下工作。
- 需要知道不正常行為的原因。
SwingWorker只是一個閃爍的標簽是一種矯枉過正。 嘗試以下基於計時器的方法,它根本不需要線程魔術:
public class Main {
private static Timer setVisibleTimer;
private static Timer setInvisibleTimer;
public static void main(String[] args) {
final JLabel label = new JLabel("TEST ME ");
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisibleTimer = new Timer(8000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setVisible(true);
}
});
setInvisibleTimer = new Timer(5000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setVisible(false);
}
});
setVisibleTimer.start();
setInvisibleTimer.start();
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setVisible(true);
if (setVisibleTimer != null){
setInvisibleTimer.stop();
setVisibleTimer.stop();
}
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(startButton);
buttonPanel.add(cancelButton);
JPanel cp = new JPanel();
LayoutManager layout = new BoxLayout(cp, BoxLayout.Y_AXIS);
cp.setLayout(layout);
cp.add(buttonPanel);
cp.add(label);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(cp);
frame.pack();
frame.setVisible(true);
}
}
不,你永遠不會在EDT上等待:而是將所有邏輯放入doInBackground,並發布標簽狀態
用一些代碼充實我的評論(可以在Timer中完成,但實際上我喜歡工人:)
static class LabelState {
int count;
boolean visible;
public LabelState(boolean visible, int count) {
this.count = count;
this.visible = visible;
}
}
static class CounterTask extends SwingWorker<Void, LabelState> {
int DELAY = 3000;
JLabel label;
int WAIT = 5000;
public CounterTask(JLabel label) {
this.label = label;
}
@Override
protected Void doInBackground() throws Exception {
int i = 0;
int count = 1000;
while (!isCancelled() && i < count) {
i++;
publish(new LabelState(false, i));
Thread.sleep(DELAY);
i++;
publish(new LabelState(true, i));
Thread.sleep(WAIT);
}
return null;
}
protected void process(List<LabelState> chunks) {
LabelState strContent = chunks.get(chunks.size() - 1);
label.setVisible(strContent.visible);
label.validate();
label.setText("DISPLAYING " + strContent.count);
}
@Override
protected void done() {
if (isCancelled())
System.out.println("Cancelled !");
else
System.out.println("Done !");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.