SWING: Incolonnare i componenti in verticale.

di il
9 risposte

SWING: Incolonnare i componenti in verticale.

Buongiorno a tutti, stò realizzando una piccola applicazione con Swing, e vorrei provare ad ottenere una cosa che non riesco in alcuna maniera a capire.

In pratica, questo è il codice:

package rgbPackage;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class RenderizzaGrafica extends JFrame {

	private static final long serialVersionUID = 1L;
	
	private static final JPanel pannelloSuperiore = new JPanel();
	private static final JPanel pannelloSinistra = new JPanel();
	private static final JPanel pannelloCentrale = new JPanel();
	private static final JButton impostaBAUD = new JButton("Imposta Baud Rate");
	private static final JButton apriPorta = new JButton("Apri la porta USART");
	private static final JTextField StringaUsart = new JTextField("Stringa ricevuta",50);
	private static final JCheckBox baud1200 = new JCheckBox("Baud: 1200");	
	private static final JCheckBox baud2400 = new JCheckBox("Baud: 2400");	
	private static final JCheckBox baud4800 = new JCheckBox("Baud: 4800");	
	private static final JCheckBox baud9600 = new JCheckBox("Baud: 9600");	
	private static final JCheckBox baud19200 = new JCheckBox("Baud: 19200");	
	private static final JCheckBox baud57600 = new JCheckBox("Baud: 57600");	
	private static final JCheckBox baud115200 = new JCheckBox("Baud: 115200");	
	
	
	public static void InizializzaFinestra(){
	
		JFrame MioFrame = new JFrame("Comunicazione Seriale");
		MioFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		MioFrame.setSize(800, 500);
		MioFrame.setResizable(false);
		MioFrame.setVisible(true);
		Container MioContainer = MioFrame.getContentPane();
		MioContainer.setLayout(new BorderLayout());
		pannelloSuperiore.add(apriPorta);
		MioContainer.add(pannelloSuperiore,BorderLayout.NORTH);		
		pannelloSinistra.add(baud1200);
		pannelloSinistra.add(baud2400);
		pannelloSinistra.add(baud4800);
		pannelloSinistra.add(baud9600);
		pannelloSinistra.add(baud19200);
		pannelloSinistra.add(baud57600);
		pannelloSinistra.add(baud115200);		
		pannelloSinistra.add(impostaBAUD);
		MioContainer.add(pannelloSinistra,BorderLayout.WEST);
		pannelloCentrale.add(StringaUsart);
		MioContainer.add(pannelloCentrale,BorderLayout.CENTER);

	}

}
Uso come griglia la "BorderLayout" e, nel suo pannello di sinistra, vorrei ottenere in colonna uno sotto l'altro tutti i controlli di tipo CheckBox, ma l'unico layout che ottengo è di averli tutti in fila uno dopo l'altro.

Come si fà ad impostare che tutti i controlli Check vengano impilati e non acodati?

Esiste qualche impostazione di Swing stesso, per modificare il layout?

Grazie mille.

9 Risposte

  • Re: SWING: Incolonnare i componenti in verticale.

    harpefalcata ha scritto:


    Uso come griglia la "BorderLayout" e, nel suo pannello di sinistra, vorrei ottenere in colonna uno sotto l'altro tutti i controlli di tipo CheckBox, ma l'unico layout che ottengo è di averli tutti in fila uno dopo l'altro.

    Come si fà ad impostare che tutti i controlli Check vengano impilati e non acodati?
    Ho solo letto velocemente il tuo codice (non in dettaglio, quindi). In generale in AWT/Swing è possibile (e consigliabile) sfruttare più layout manager per arrivare ad ottenere la interfaccia che si vuole. L'approccio quindi è quello di "inscatolare" contenitori dentro contenitori, che magari contengono componenti e altri contenitori, ecc... Applicando appunto un layout manager (eventualmente differente) per ciascun contenitore.

    Es. il content-pane del JFrame ha un BorderLayout (che è già per default), nella parte WEST magari ci metti un JPanel che ha un BoxLayout "verticale", che contiene N componenti incolonnati. Nella parte CENTER ci metti un JPanel che ha un GridLayout con altri componenti, ecc...

    Insomma, bisogna ovviamente conoscere i principali layout manager di AWT/Swing, sapere quali sono le caratteristiche, vincoli e potenzialità di ciascuno e poi avendo "in testa" una certa interfaccia utente, andare a comporla applicando in concetto appena detto.
  • Re: SWING: Incolonnare i componenti in verticale.

    Ho risolto in questo modo:
    pannelloSinistra.setLayout( new GridLayout(0,1))
    Inserita prima di appendere il pannello con tutte le checkbox nel container.
  • Re: SWING: Incolonnare i componenti in verticale.

    Dunque, ora il problema grafico l'ho risolto e vorrei chiedere una cosa circa un problema più di natura logica.

    Nell'applicazione grafica che ho realizzato in questo progetto, ho inserito un bottone da premere e, a questo bottone ho associato un ActionListener, con il suo metodo actionPerformed.

    All'interno di questo metodo actionPerformed, ho eseguito alcune operazioni su una variabile, ottenendo infine una costante numerica, che è legata ad alcuni altri controlli presenti nella grafica.

    La domanda è: come faccio a ritornare il valore di questa variabile all'interno del normale flusso?

    Il problema è questo: l'ActionListener viene invocato in maniera asincrona rispetto al normale flusso, questo perchè la routine dell'ActionListener viene eseguita solamente quando premo il pulsante, quindi il risultato di questa variabile cambia in maniera non prevedibile.

    Fintanto che non premo il pulsante quella variabile preserva il valore precedente.

    Non riesco a fare in modo che la routine asincrona: ActionListener mi restituisca indietro il nuovo valore, qualcuno sà come si fà?

    gRAZIE MILLE.
  • Re: SWING: Incolonnare i componenti in verticale.

    harpefalcata ha scritto:


    La domanda è: come faccio a ritornare il valore di questa variabile all'interno del normale flusso?
    Nelle applicazioni grafiche, non c'è di per sé un "flusso" di esecuzione (a meno che parliamo di operazioni particolari, lunghe e pesanti che vanno eseguite in un thread, flusso di esecuzione appunto, a parte in background).

    Tutta l'applicazione grafica "va avanti" per EVENTI. E quindi è ovvio che sia tutto molto asincrono, oltretutto "pilotato" da ciò che fa l'utente.
    Pertanto dovresti entrare di più in quest'ottica.
  • Re: SWING: Incolonnare i componenti in verticale.

    Forse ho capito la logica.

    Devo assegnare all'interno del main un nuovo "Event Listener" che ascolti quando è pronto il dato genrato dalla routine asincrona, in questo modo, anche se questo dato sarà pronto dopo un intervallo molto lungo, il main comunque continuerebbe a rimanere in ascolto, è corretto così?

    Se fosse corretto la domanda diventerebbe: come faccio, una volta che mi trovo nella routine asincrona, ed ho completato il calcolo della mia costante, a sollevare un evento, ed a segnalarlo?

    Grazie mille.
  • Re: SWING: Incolonnare i componenti in verticale.

    harpefalcata ha scritto:


    Devo assegnare all'interno del main un nuovo "Event Listener" che ascolti quando è pronto il dato genrato dalla routine asincrona, in questo modo, anche se questo dato sarà pronto dopo un intervallo molto lungo, il main comunque continuerebbe a rimanere in ascolto, è corretto così?
    Per "main" cosa intendi? ... il classico main(String[] args) ? Cosa vuoi fare? sospendere il thread che sta eseguendo il main() finché "qualcosa" avviene nella GUI? Tecnicamente è possibile ma non è banale e richiede la conoscenza di un po' di cose a livello di thread/concorrenza.

    Probabilmente non è chiaro a me cosa vuoi fare ma molto più probabilmente devi entrare più tu nell'ottica delle interfacce grafiche basate su eventi.
  • Re: SWING: Incolonnare i componenti in verticale.

    L'applicazione l'ho realizzata in questo modo: esiste un main classico: main(String[] args), che è il punto di ingresso dell'intera applicazione.

    Ho bisogno del metodo main, e di una routine "core" che istanzi tutti gli altri metodi perchè poi, il file .JAR che creerò, dovrà essere avviabile attraverso un lanciatore linux, il quale richiede il metodo "main" per poter funzionare.

    All'interno di questo metodo main, ho istanziatò una classe, che ho chiamato "renderizzaGrafica.Inizializza()" che si occupa di disegnare e renderizzare tutti i componenti grafici.

    Arrivato a questo punto, comincia la logica.
    In pratica questo programma fa uso della libreria RXTXcomm con la quale mi connetto ad una porta seriale che mi servirà a scaricare dei dati da un microcontrollore M4 che si occupa di fare una campionatura su un segnale e scarica tutti i dati sulla USART.

    Una volta completato il render dell'interfaccia grafica, il controllo ritorna al main.

    Una volta nel main richiamo i metodi che servono a fare una scansione delle porte disponibili nel computer, ad ottenere il nome della porta usart disponibile che, di solito è la "/dev/ttyUSB0", ad aprire quella porta, e poi rimarrò in ascolto che il controller mi invii tramite questa stessa porta tutti i dati che ha campionato.

    Il problema che ho descritto finora riguarda il fatto che, dall'interfaccia grafica io DEVO poter avere la possibilità di selezionare vari tipi di BAUD rates, e di passare questa scelta ai metodi che poi apriranno quella porta metodi che però, devono conoscere in anticipo il baud con il quale funziona tale porta, altrimenti non si apre la connessione.

    Quindi io mi ritrovo con una interfaccia grafica che estrae il valore delbaud scelto dall'utente, e questo valore che una semplice costante numerica, deve essere restituito al main, il quale poi lo passerà come parametro ai metodi della porta seriale, per poter instaurare la connessione.

    Separatamente ho realizzato tutto e funziona, ma non riesco a realizzare la parte nella quale l'ActionListener del pulsante Baud restituisce il valore baud al main.

    Grazie

  • Re: SWING: Incolonnare i componenti in verticale.

    harpefalcata ha scritto:


    L'applicazione l'ho realizzata in questo modo: esiste un main classico: main(String[] args), che è il punto di ingresso dell'intera applicazione.
    Questo è ovvio, è così per tutte le applicazioni "standalone".

    harpefalcata ha scritto:


    All'interno di questo metodo main, ho istanziatò una classe, che ho chiamato "renderizzaGrafica.Inizializza()" che si occupa di disegnare e renderizzare tutti i componenti grafici.
    Il main ... intendo il "main thread" non deve renderizzare un bel niente. La inizializzazione, gestione e ascolto degli eventi va fatto tutto nel contesto del Event Dispatch Thread.

    harpefalcata ha scritto:


    Una volta completato il render dell'interfaccia grafica, il controllo ritorna al main.
    No, non è così che "funzionano" le cose nelle GUI.
  • Re: SWING: Incolonnare i componenti in verticale.

    Alla fine credo di essere riuscito a risolvere.

    Ho integrato anche tutti i controlli della porta seriale nei vari ActionListener.

    In questo modo l'intera gestione dell'applicazione è asincrona.
Devi accedere o registrarti per scrivere nel forum
9 risposte