View Full Version : [Java, banale] "flashare" una tab
esiste (in Swing) qualche modo per attirare l'attenzione dell'utente su una particolare tab di un controllo JTabbedPane? la tab è disattivata (ovvero, quella attiva è un'altra) e vorrei farla flashare per indicare all'utente che deve attivarla e vedere che succede lì dentro :D
considerate che le etichette delle tab sono molto grosse nel mio programma perché non contengono testo ma icone da 64x64 (immagini in PNG con parti trasparenti tra l'altro), quindi flashandole richiamano l'attenzione a sufficienza.
Messa lì tanto per dire si tratta di scambiare periodicamente il colore della linguetta con setBackgroundAt di JTabbedPane.
Per un bel po' di ragioni, tuttavia, la cosa è uno zinzinello più articolata. Non ultimo il fatto che, manco a farlo apposta, devi usare i Thread.
Diciamo che dato un JTabbedPane T e un componente C inserito in quel JTabbedPane vuoi illuminarne l'etichetta finchè l'utente non ci clicca sopra. Potremmo dire una cosa tipo:
TabFlasher flasher = new TabFlasher(T, C);
flasher.start();
Il codice che riciclo è quasi così.
private TabFlasherRegistry flasherRegistry = new TabFlasherRegistry();
//quando vuoi illuminare una tab
flasherRegistry.newTabFlasher(T, C).start();
Lo scopo del registro è quello di poter invocare il suo metodo dispose();
flasherRegistry.dispose();
quando si chiude l'applicazione. Internamente, dispose() altro non fa che fermare tutti i TabFlasher ancora attivi.
TabFlasherRegistry.java
package it.tukano.miniwrite.components;
import java.awt.Component;
import java.util.*;
import javax.swing.JTabbedPane;
/** Registro di TabFlasher. */
public class TabFlasherRegistry implements TabFlasher.TabFlasherNotifiable {
private final List<TabFlasher> FLASHERS =
Collections.synchronizedList(new ArrayList<TabFlasher>());
/** Crea e restituisce un nuovo TabFlasher. Il TabFlasher creato è
applicato alla linguetta del componente tabComponent in tabPane. */
public TabFlasher newTabFlasher(JTabbedPane tabPane, Component tabComponent) {
TabFlasher flasher = new TabFlasher(this, tabPane, tabComponent);
FLASHERS.add(flasher);
return flasher;
}
/** Termina tutti i TabFlasher creati da questo TabFlasher */
public void dispose() {
for(int i = 0; i < FLASHERS.size(); i++) {
FLASHERS.get(i).stop();
}
FLASHERS.clear();
}
/** @inheritDoc */
public void notifyTabFlasherStop(TabFlasher f) {
FLASHERS.remove(f);
}
}
TabFlasher.java
package it.tukano.miniwrite.components;
import java.beans.*;
import java.awt.Component;
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/** Illumina una linguetta di un JTabbedPane. La linguetta è quella
corrispondente ad un certo Component, contenuto nel JTabbedPane. L'illuminazione
si interrompe o per diretta invocazione del metodo stop() o per rimozione
del Component bersaglio dall'albero di visualizzazione o per selezione
della linguetta associata al Component o per rimozione del Component dal
JTabbedPane. */
public class TabFlasher implements Runnable, ActionListener, ChangeListener, PropertyChangeListener {
/** Interfaccia concretizzata da chi voglia ricevere una notifica
dell'avvenuta interruzione di questo TabFlasher */
public static interface TabFlasherNotifiable {
/** L'oggetto riceve una notifica di interruzione
del compito del TabFlasher in argomento */
void notifyTabFlasherStop(TabFlasher t);
};
/** Colore di illuminazione usato dai TabFlasher. Questo
colore è periodicamente scambiato con "null" e applicato
alla linguetta bersaglio nel JTabbedPane. */
private static final Color HIGHLIGHT_COLOR = new Color(
UIManager.getLookAndFeelDefaults().getColor("TabbedPane.selected").getRGB());
/** JTabbedPane che contiene il componente TAB_COMPONENT la cui
linguetta sarà illuminata periodicamente */
private final JTabbedPane TABBED_PANE;
/** Componente la cui linguetta deve essere periodicamente
illuminata */
private final Component TAB_COMPONENT;
/** Timer Swing per l'applicazione alternata del
colore di sfondo per la linguetta bersaglio */
private final Timer TIMER = new Timer(250, this);
/** Oggetto interessato a ricevere una notifica di interruzione
del lavoro di questo TabFlasher (Unicast Event Listener) */
private final TabFlasherNotifiable NOTIFIABLE;
/** Colore di sfondo corrente. Valore letto e scritto unicamente
dall'AWT Event Dispatcher Thread. */
private Color currentBackground;
/** Crea un TabFlasher per il JTabbedPane tabbedPane.
@param notifiable, oggetto interessato a ricevere una notifica di
interruzione dell'illuminazione. Può essere null.
@param tabbedPane, JTabbedPane che contiene la linguetta da
illuminare.
@param tabComponent, Componente contenuto nel JTabbedPane la cui
linguetta corrispondente sarà illuminata. */
public TabFlasher(TabFlasherNotifiable notifiable, JTabbedPane tabbedPane, Component tabComponent) {
TABBED_PANE = tabbedPane;
TAB_COMPONENT = tabComponent;
TABBED_PANE.addChangeListener(this);
TAB_COMPONENT.addPropertyChangeListener(this);
NOTIFIABLE = notifiable;
}
/** Periodicamente invocato dal Timer Swing */
public void actionPerformed(ActionEvent e) {
highlight();
}
/** Ferma lo scambio dei colori se il JTabbedPane fornito
in costruzione, a cui questo TabFlasher è connesso come
PropertyChangeListener, notifichi una mutazione di stato
derivante dalla perdità di connessione all'albero di
visualizzazione */
public void propertyChange(PropertyChangeEvent e) {
if(e.getPropertyName().equals("ancestor") && e.getNewValue() == null) {
System.out.println("Stopped");
stop();
}
}
/** Ferma lo scambio dei colori se il JTabbedPane fornito
in costruzione, a cui questo TabFlasher è connesso come
ChangeListener, notifichi una mutazione di stato comportante
la rimozione del componente bersaglio o l'avvenuta selezione
della linguetta del componente bersaglio. */
public void stateChanged(ChangeEvent e) {
int tabComponentIndex = TABBED_PANE.indexOfComponent(TAB_COMPONENT);
if(tabComponentIndex < 0 || tabComponentIndex == TABBED_PANE.getSelectedIndex()) {
stop();
}
}
/** Ferma lo scambio dei colori. Se è stato fornito
un TabFlasherNotifiable in costruzione, notifica a quel
TabFlasherNotifiable l'interruzione invocando il suo
metodo notifyTabFlasherStop, passando questo TabFlasher
come parametro dell'invocazione. */
public void stop() {
TIMER.stop();
if(NOTIFIABLE != null) {
NOTIFIABLE.notifyTabFlasherStop(this);
}
SwingUtilities.invokeLater(this);
}
/** Avvia lo scambio dei colori di sfondo
per l'etichetta del componente bersaglio */
public TabFlasher start() {
TIMER.start();
return this;
}
/** Applica il colore di sfondo corrente alla linguetta del componente
bersaglio. Se la linguetta selezionata nel JTabbedPane è quella del
componente bersaglio o il componente bersaglio è stato eliminato, ferma
tutto. */
public void highlight() {
Component selectedComponent = TABBED_PANE.getSelectedComponent();
int targetTabIndex = TABBED_PANE.indexOfComponent(TAB_COMPONENT);
boolean targetSelected = TABBED_PANE.getSelectedIndex() == targetTabIndex;
if(targetSelected || targetTabIndex < 0) {
stop();
} else {
TABBED_PANE.setBackgroundAt(targetTabIndex, switchColor());
}
}
/** Scambia il colore di background tra null e HIGHLIGHT_COLOR */
public Color switchColor() {
return currentBackground = currentBackground == null ? HIGHLIGHT_COLOR : null;
}
/** Operazioni Swing da eseguire al termine di questo TabFlasher */
public void run() {
int targetTabIndex = TABBED_PANE.indexOfComponent(TAB_COMPONENT);
if(targetTabIndex >= 0) {
TABBED_PANE.setBackgroundAt(targetTabIndex, null);
}
TAB_COMPONENT.removePropertyChangeListener(this);
TABBED_PANE.removeChangeListener(this);
}
}
Si nota che a me delle 80 colonne non m'è mai fregato niente? :D
setBackgroundAt! ecco la chiave. http://forums.nsn3.net/style_emoticons/default/55.gif
non vorrei che sembrasse che in tal modo me ne frego di tutto il papiro che hai scritto però: ti ringrazio dell'interessamento. :D
mi complimento, le classi che hai scritto mi sembrano veramente esaustive. inoltre vedo all'opera il tuo stile di scrittura :eek:
sinceramente non concordo col documentare il codice a quel livello di dettaglio... io riesco ad essere molto più produttivo tentando di scrivere codice autoesplicativo, e nel mio concetto di produttività rientra anche la riduzione dei bug al giorno e la velocità nella correzione dei bug presenti ;)
però penso anche che ognuno faccia meglio con la propria metodologia, se non altro per questioni "religiose". http://forums.nsn3.net/style_emoticons/default/55.gif
PS: per quanto riguarda le 80 colonne, a me frega talmente tanto che nel formatter di Eclipse ho impostato un valore assurdo per il wrapping delle linee, tipo un milione... :asd:
e ora scopro che esiste un valore di default percui il formatter non wrappa le linee :D
...
esiste? :huh:
tipo -1 che fa? :D
beppegrillo
21-01-2007, 00:32
Non ho letto tutto il papiello, ma dovresti non utilizzare il metodo stop di Thread, è un tantinello deprecato :P
Sei sicuro che il mio stop() sia sbagliato? Sicuro sicuro? La accendiamo? :D
beppegrillo
21-01-2007, 00:41
Sei sicuro che il mio stop() sia sbagliato? Sicuro sicuro? La accendiamo? :D
no spegnamola, visto che ora ho letto il tuo codice, e stop lo chiami sul timer e non sul thread, dunque di conseguenza non è valido ciò che dicevo prima :P
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.