Home
Swing e i look and feel

15 Gennaio 2018

Swing e i look and feel

di

Java 9 offre abbondanti strumenti per la programmazione, compresa quella dell’aspetto e delle reazioni di ogni componente software.

Il toolkit Swing permette di decidere la modalità con cui i componenti grafici (widget) di una applicazione Java saranno visualizzati (il loro look) e il modo in cui essi interagiranno a seguito dell’interazione con l’utente (feel).
Prima dell’avvento di Swing, con il framework “delle origini” AWT, ogni applicazione dotata di una GUI aveva un L&F uguale a quello del sistema operativo dove era eseguita; ciò comportava di sicuro un vantaggio per l’utente perché quelle applicazioni apparivano e rispondevano allo stesso modo delle applicazioni scritte in modo nativo. Per lo sviluppatore, però, ciò provocava seri problemi di portabilità, dato che ogni GUI per un particolare sistema poteva renderizzare i widget in posizioni diverse o addirittura non prevedere certi comportamenti di interazione. Nella sostanza il famoso motto di Java, WORA (Write Once, Run Everywhere), non era di semplice applicazione quando si dovevano scrivere applicazioni dotate di interfacce grafiche.

Grafica per tutti

Swing ha consentito di risolvere i problemi anzidetti perché ha introdotto dei L&F cross-platform che appaiono e si comportano in modo uniforme su tutti i sistemi previsti: il vetusto Metal e il relativamente nuovo Nimbus, quest’ultimo introdotto in Java SE 6 Update 10. In ogni caso è ancora possibile utilizzare L&F che appaiono e si comportano in modo nativo rispetto al sistema dove la relativa applicazione sta girando. Esistono: per GNU/Linux, Solaris o Unix in generale, GTK+ o Motif se GTK+ almeno dalla versione 2.2 non è installato; per Windows, quello classico oppure quello della versione corrente di utilizzo; per macOS, quello fornito da Apple stessa (allo stato attuale il L&F è quello proprio di macOS).


Bravi, i programmi scritti in Java come si deve. E anche belli.

I tipi propri dei L&F sono disposti in determinati package del JDK (com.sun.java.swing.plaf.gtk, com.sun.java.swing.plaf.motif, com.sun.java.swing.plaf.nimbus, com.sun.java.swing.plaf.windows, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.plaf.nimbus e javax.swing.plaf.basic.synth) che a partire da Java 9 fanno parte del modulo java.desktop.

Che cosa mi metto

Vediamo lo stralcio di un listato che dà la possibilità di scegliere dei L&F e che mostra alcuni widget e come essi siano renderizzati (il sorgente completo, unitamente alle istruzioni su come compilarlo correttamente, è reperibile su GitHub.  

package com.pellegrinoprincipe;
…
public class SwingLookAndFeel extends javax.swing.JFrame

{
	public SwingLookAndFeel()
	{
		initComponents();
	}
…
	private void initLookAndFeelMenu()
	{
		final UIManager.LookAndFeelInfo plaf[] = 
UIManager.getInstalledLookAndFeels();

		for (int i = 0, n = plaf.length; i < n; i++)
		{
			JMenuItem menuItem = new JMenuItem();
			menuItem.setText(plaf[i].getName());

			menuItem.addActionListener((ActionEvent evt) -> // lambda expr.
			{
				JMenuItem itemSeleced = (JMenuItem) evt.getSource();
				int ix = 
itemSeleced.getParent().getComponentZOrder(itemSeleced);

				try
				{
					UIManager.setLookAndFeel(plaf[ix].getClassName());
					SwingUtilities.updateComponentTreeUI
(SwingLookAndFeel.this);
				}
				catch (Exception ex)
				{
					JOptionPane.showMessageDialog(this, ex);
				}
			});

			myMenu.add(menuItem);
		}
	}

	public static void main(String args[])
	{
		java.awt.EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				SwingLookAndFeel slf = new SwingLookAndFeel();
				slf.setVisible(true);
				slf.initLookAndFeelMenu();
			}
		});
	}
…
}

Il listato in esame crea una finestra con una serie di widget e un menu applicativo dove ogni item rappresenta un determinato L&F da scegliere. La classe UIManager, grazie al metodo statico getInstalledLookAndFeels (segnatura completa: public static UIManager.LookAndFeelInfo[] getInstalledLookAndFeels​() ) restituisce un array di oggetti di tipo LookAndFeelInfo dove ciascun elemento contiene informazioni circa il nome del L&F e la relativa classe di implementazione. Nel nostro caso l’array plaf, di tipo LookAndFeelInfo, viene usato in un apposito ciclo for per aggiungere dinamicamente gli item del menu Look And Feel il cui nome rispecchierà il nome dei L&F disponibili, ottenuti mediante l’invocazione del metodo getName (segnatura completa: public String getName​() ) della classe LookAndFeelInfo.

Come cambia il menu

Successivamente, a ogni scelta effettuata per il tramite del menu, nel listener di gestione del relativo evento (ActionEvent) cambieremo da programma il L&F corrente mediante il metodo statico setLookAndFeel (segnatura completa: public static void setLookAndFeel​(String className) ) della classe UIManager, al quale passeremo il nome della classe del L&F ottenuta con il metodo getClassName (segnatura completa: public String getClassName​() ) della classe LookAndFeelInfo. Infine, per rendere subito operativo il cambiamento del L&F scelto, invochiamo il metodo statico updateComponentTreeUI (segnatura completa: public static void updateComponentTreeUI​(Component c) ) della classe SwingUtilities. L’esempio illustrato consente di cambiare il L&F direttamente dal programma applicativo; possiamo tuttavia compiere questa operazione anche da linea di comando, avviando l’applicazione con il comando java e l’opzione -Dswing.defaultlaf:

java -Dswing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
com.pellegrinoprincipe.SwingLookAndFeel

In alternativa si può anche creare (se non è già presente), nella directory lib del runtime di Java (per esempio, in Windows, C:Program FilesJavajdk1.8.0_152jrelib), il file swing.properties con la chiave swing.defaultlaf e l’indicazione della classe del L&F (con Java 9 il percorso del predetto file è cambiato e infatti dovrà essere inserito in un’apposita directory conf: per esempio, sempre in ambiente Windows, il path sarà qualcosa come C:Program FilesJavajre-9conf). Ritornando dunque al nostro precedente esempio, il file potrà contenere la seguente stringa:

swing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel

L'autore

  • Pellegrino Principe
    Pellegrino Principe lavora come ricercatore informatico e capo sviluppatore software presso il Drappello Analisi e Studi della Sezione E-Government del Comando Generale della Guardia di Finanza di Roma dove è anche docente in Linguaggi di Programmazione. È appassionato dei linguaggi con una sintassi “C-like”.

Iscriviti alla newsletter

Novità, promozioni e approfondimenti per imparare sempre qualcosa di nuovo

Gli argomenti che mi interessano:
Iscrivendomi dichiaro di aver preso visione dell’Informativa fornita ai sensi dell'art. 13 e 14 del Regolamento Europeo EU 679/2016.