PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [SWT] Countdown-Label -> SWTException



nul
07-05-2005, 11:56
Ich versuch schon seit laengerem einen Countdown fuer eine SWT Application zu schreiben, was mir aber nicht so recht gelingen will. Ich erhalte immer nur die Fehlermeldung, dass ein SWT-Label nicht in einem Thread veraendert werden darf.
Hab deshalb schon so einiges probiert, ff. ist mein letzter versuch:

/*
* Created on May 7, 2005
*/
package label;

import java.util.Observable;
import java.util.Observer;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

import counter.Countdown;
import counter.Time;

public class TestLabel implements Observer {

private Display display = null;
private Shell guiShell = null;
private Label label = null;

private Countdown countdown = null;
private Time time = null;

public TestLabel() {
this.display = Display.getDefault();

this.createGuiShell() ;
this.guiShell.open();

while (!this.guiShell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep ();
}
display.dispose();
}

private void createGuiShell() {
this.guiShell = new Shell();
this.guiShell.setSize(new Point(200,200));
this.guiShell.setText("Counter Spike Label Test");

this.createLabel();
}

private void createLabel() {
this.label = new Label( this.guiShell, SWT.CENTER );
this.label.setBounds( new Rectangle( 0, 0, 200, 200 ));
this.label.setBackground( Display.getCurrent().getSystemColor( SWT.COLOR_BLACK ));
this.label.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WHITE ));

this.time = new Time( 10000 );
this.time.addObserver( this );
this.time.setLimit( 0 );
this.time.setWarnLimit( 5000 );

this.label.setText( time.toString() );

this.countdown = new Countdown( this.time );
}

public void update(Observable o, Object arg) {
System.out.println( "update " + o + " " + arg );
this.label.setText( ((Long)arg).toString() );
}

/**
* @param args
*/
public static void main(String[] args) {
new TestLabel();
}
}

/*
* Created on May 7, 2005
*/
package counter;

import java.util.Observable;

public class Time extends Observable {

public long time = 0;
public long limit = 0;
public long warnLimit = -1;

public Time( long time ) {
this.time = time;
}

public void setLimit( long limit ) {
this.limit = limit;
}

public void setTime( long i ) {
this.time += i;
this.setChanged();
this.notifyObservers( new Long( this.time ) );
}

public String toString() {
return new Long( this.time).toString();
}

public void setWarnLimit(int warnLimit) {
this.warnLimit = warnLimit;
}
}

/*
* Created on May 7, 2005
*/
package counter;

public class Countdown implements Runnable {

Thread thread = null;
Time time = null;

public Countdown( Time time ) {
this.time = time;
this.thread = new Thread( this );
this.thread.start();
}


public void run() {
while ( true ) {

this.time.setTime( -1 );
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {}
}
}
}
Erhalte aber wie gesagt die Meldung

update 9999 9999
Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:2860)
at org.eclipse.swt.SWT.error(SWT.java:2783)
at org.eclipse.swt.SWT.error(SWT.java:2754)
at org.eclipse.swt.widgets.Widget.error(Widget.java:4 02)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget. java:339)
at org.eclipse.swt.widgets.Label.setText(Label.java:4 91)
at label.TestLabel.update(TestLabel.java:66)
at java.util.Observable.notifyObservers(Observable.ja va:142)
at counter.Time.setTime(Time.java:25)
at counter.Countdown.run(Countdown.java:21)
at java.lang.Thread.run(Thread.java:595)
Hat jemand einen Tipp fuer mich wie man in SWT einen Counter korrekt implementieren kann? Bin fuer jeden Tipp dankbar!

mfg nul

peschmae
07-05-2005, 14:04
In das Problem läuft so ziemlich jeder rein der was mit SWT machen will. Deshalb guck mal da: http://www.mrunix.de/forums/archive/index.php/t-38304.html

MfG Peschmä

nul
07-05-2005, 14:52
Meinst du so was:

package test_label_thread;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class TestClass {

Display display = null;
Shell guiShell = null;
Label label = null;
boolean started = false;

/**
*
*/
public TestClass() {
this.display = Display.getDefault();

this.createGuiShell() ;
this.guiShell.open();

while (!this.guiShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep ();
if ( !started ) {
System.out.println( "Thread started" );
this.startCountDown();
this.started = true;
}
}
}
display.dispose();
}

private void createGuiShell() {
this.guiShell = new Shell();
this.guiShell.setSize(new Point(200,200));
this.guiShell.setText("Counter Spike Label Test");

this.createLabel();
}

private void createLabel() {
this.label = new Label( this.guiShell, SWT.CENTER );
this.label.setBounds( new Rectangle( 0, 0, 200, 200 ));
this.label.setBackground( Display.getCurrent().getSystemColor( SWT.COLOR_BLACK ));
this.label.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WHITE ));
this.label.setText( "fucking label" );
}

public void startCountDown() {
this.display.syncExec( new Runnable() {
public void run() {
int i = 0;
while ( true ) {
label.setText( new Integer( i ).toString() );
i++;
System.out.println( "Thread: " + i );
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {}
}
}
} );
}

/**
* @param args
*/
public static void main(String[] args) {
new TestClass();
}

}
Ja, sowas hab ich auch schon versucht, fuehrt aber dazu dass dann das Label/der Display blockiert ist.

P.S.: probiert hab ichs auch mit timerExec, bringt aber immer das selbe Ergebnis. Ich schlag mich mit dem Problem schon ueber eine Woche rum, und langsam wird es laestig. (Ich glaube das versteht jeder :( )

peschmae
07-05-2005, 21:03
Nein. Ich meine dass du ein Runnable machen sollst ausschliesslich um den Text zu setzen. Das was du machst ist *alles* - auch das sleep im Hauptthread ausführen lassen - also genau wie wenn du keinen eigenen Thread hättest.



public void startCountDown() {
(new Runnable() {
public void run() {
int i = 0;
while ( true ) {

display.syncExec(new Runnable() {
public void run() {
label.setText( new Integer( i ).toString() );
}
}

i++;
System.out.println( "Thread: " + i );
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {}
}
}
} ).run(); //geht wohl nicht so, aber ich glaube du siehst was ich meine - bin gerade saumüde
}


MfG Peschmä

nul
08-05-2005, 00:57
Hm, manchmal denkt man vollkommen in die falsche Richtung, danke, jetzt hab ichs so ziemlich herausen, muss nur noch den Fehler beseitigen, der beim Beenden des Progs entsteht. :)

P.S.: Nun ist das auch geloest, danke fuer die Hilfe!!!