Problema Grafica

di il
2 risposte

Problema Grafica

Salve a tutti, ho un problema con la grafica, sto usando un plugin di java per usare Java SWT, il problema è il seguente:
Mi serve usare un countdown nel mio programma, cosi ho scritto un Runnable che lo fa, ed in più modifica una label con il valore di cui necessito, il tutto funziona(uso i metodi syncExec e asyncExec), ma quando avvio il countdown mi si "sputtana tutto" bloccandomi il programma fino a countdown ultimato, cosa può essere, vi lascio i codici delle mie classi.

Classe Clock:
package esercizio.countdown;

import java.util.concurrent.TimeUnit;

import org.eclipse.swt.widgets.Label;

public class Clock implements Runnable{
	private int seconds;
	private Label label;
	
	public Clock(int sec, Label lab){
		seconds=sec;
		label=lab;
	}
	
	public int getSeconds(){
		return seconds;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(seconds>0){
			System.out.println(seconds);
			label.setText(seconds+"");
			try {
				Thread.sleep(TimeUnit.SECONDS.toMillis(1));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			seconds--;
		}
	}

}
Classe Countdown:
package esercizio.countdown;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class Countdown {

	protected Shell shell;
	private Clock c;
	private Label lab;
	private int secondsWait=30;
	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Countdown window = new Countdown();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
	
	private void avviaCountDown(){
		Display.getDefault().syncExec(c);
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(450, 300);
		shell.setText("SWT Application");
		
		Label lblNewLabel = new Label(shell, SWT.NONE);
		lblNewLabel.setFont(SWTResourceManager.getFont("Segoe UI", 28, SWT.NORMAL));
		lblNewLabel.setBounds(48, 61, 209, 78);
		lblNewLabel.setText("30");
		lab=lblNewLabel;
		c=new Clock(secondsWait,lblNewLabel);
		
		Button btnProva = new Button(shell, SWT.NONE);
		btnProva.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				avviaCountDown();
			}
		});
		btnProva.setBounds(76, 157, 75, 25);
		btnProva.setText("Prova");
	}
}
tengo a precisare che il secondo codice, eccetto per le aggiunte tipo listener e del countdown è autogenerato dal plugin

2 Risposte

  • Re: Problema Grafica

    psp300xxx ha scritto:


    ma quando avvio il countdown mi si "sputtana tutto" bloccandomi il programma fino a countdown ultimato
    Premessa: me ne intendo poco di SWT, l'ho usato solo poche volte giusto per qualche prova veloce. Sono invece molto più ferrato su Swing. Ma tra SWT e Swing ci sono molte similitudini riguardo il "threading model", anche se con qualche leggera differenza.

    Ovvero sia in Swing che in SWT esiste un unico e specifico thread per la gestione della interfaccia utente. In SWT c'è la differenza, come dice la documentazione: "The UI thread is the thread in which the Display was created. All other widgets must be created in the UI thread."

    Se a seguito di un evento si vuole eseguire un lavoro "lungo", bisogna farlo in un thread separato. Non bisogna tenere "impegnato" il thread della UI. Questo vale in Swing e anche in SWT.

    Già su questo punto il tuo codice non è corretto. Hai sì definito un Runnable da usare a seguito dell'evento ma hai usato syncExec. Questo non va bene. syncExec/asyncExec vanno usati NON dal UI thread. Devi quindi creare un Thread nel modo classico.

    E il secondo aspetto importante: se non sei nel UI thread, NON devi accedere direttamente alla interfaccia utente. Questo vale in Swing e anche in SWT.
    Nel run del tuo Clock fai direttamente label.setText e anche questo non va bene. Dovresti usare asyncExec per far eseguire un altro piccolo Runnable nel UI thread.

    Per cortesia, cerca di chiarirti le idee su questi aspetti che sono b-a-s-i-l-a-r-i nella gestione delle interfacce utente. Perché come vedi non è tanto questione di SWT ... questi concetti (single UI thread ecc...) sono molto comuni e diffusi in tanti framework grafici.


    P.S. se devi fare poche cose e oltretutto sulla UI a intervalli abbastanza larghi (es. 1 secondo) e non necessariamente ultra-precisi, in Swing si può usare un javax.swing.Timer mentre in SWT se non sbaglio il Display ha il metodo timerExec.
  • Re: Problema Grafica

    Risolto, grazie delle delucidazioni, ora funziona a meraviglia
Devi accedere o registrarti per scrivere nel forum
2 risposte