Curseur

Le composant JSlider

BoundedRangeModel

Evènement et Curseur

Date et Curseur

Les Curseurs

Marques d’espacement :

Affichage de ces marques :

Arrêt sur graduation :

Libellés des graduations :

Sans rail de guidage :

curseur.setMajorTickSpacing(20);

curseur.setMinorTickSpacing(5);

curseur.setPaintTicks(true);

curseur.setSnapToTicks(true);

curseur.setPaintLabels(true);

curseur.setPaintTrack(false);

Les Etiquettes des Curseurs

Inversion de direction :

Utilisation d'étiquettes particulières
Pas de renderer pour les étiquettes, utilisation
de plusieurs JLabel (erreur de design !).
Note : utiliser les Hashtable, c'est Mal !

JSlider slider=createTicksSlider();

slider.setPaintLabels(true);

Hashtable<Integer,JLabel> table=

new Hashtable<Integer,JLabel>();

for(int i=0;i<=100;i+=20)

table.put(i,new JLabel("text "+i));

slider.setLabelTable(table);

curseur.setInverted(true);

Propriété de l'UI des curseurs

Remplissage du rail :

La méthode putClientProperty() est définie dans JComponent. Elle permet d'associé une valeur à une propriété.

Les couples propriétés/valeurs
dépendandent du look & feel
de l'application (ComponentUI).

JSlider slider=...

slider.putClientProperty("JSlider.isFilled", Boolean.TRUE);

Modèle de Curseur

Le curseur utilise l'interface BoundedRangeModel comme modèle. Elle est aussi utilisée par JScrollBar.

Le modèle définie quatre valeurs :

La valeur (value)

Les bornes (minimum/maximum)

L'increment entre valeurs (extent)

Attention, l'incrément (extent) et la valeur (value) doivent se modifier par rapport au minimum et maximum.

Modèle de Curseur – gestion des évènement

L'interface BoundedRangeModel possède quatre méthodes ayant attrait à la gestion d'évènement :

addChangeEventListener()

removeChnageEventListener()

get/setValueIsAdjusting()

Le booléen valueIsAdjusting indique que la valeur (value) va subir plusieurs modifications successives.

Cette interface ne possède pas de classe abstraite gérant les évènement.

La classe DefaultBoundedRangeModel fourni l'implantation par défaut.

Modèle de Curseur

Le modèle possède pour les valeurs des méthodes get* et set*.

interface BoundedRangeModel {

public int getExtent();

public int getMaximum();

public int getMinimum();

public int getValue();

public boolean getValueIsAdjusting();

public void setExtent(int newExtent);

public void setMaximum(int newMaximum);

public void setMinimum(int newMinimum);

public void setValue(int newValue);

public void setRangeProperties(int value, int extent,
int min, int max, boolean adjusting);

public void setValueIsAdjusting(boolean isAdjusting);

public void addChangeListener(ChangeListener l);

public void removeChangeListener(ChangeListener l);

}

Exemple de Modèle - 1

extent et value change en fonction des min/max.

class FirstSliderModel implements BoundedRangeModel {

public int getExtent() {

return (value==getMinimum() || value==getMaximum())?0:1;

}

public int getMaximum() {

return 100;

}

public int getMinimum() {

return 0;

}

public int getValue() {

return value;

}

public void setValue(int newValue) {

if (newValue<getMinimum())

newValue=getMinimum();

else

if (newValue>getMaximum())

newValue=getMaximum();

this.value=newValue;

fireValueChanged();

}

Exemple de Modèle - 2

Les méthodes setExtent, setMaximum, setMinimum et setRangeProperties sont optionelles.

class FirstSliderModel implements BoundedRangeModel {

...

public void setExtent(int newExtent) {

throw new UnsupportedOperationException();

}

public void setMaximum(int newMaximum) {

throw new UnsupportedOperationException();

}

public void setMinimum(int newMinimum) {

throw new UnsupportedOperationException();

}

public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) {

throw new UnsupportedOperationException();

}

...

}

Exemple de Modèle -3

La gestion des évènements.

...

public boolean getValueIsAdjusting() {

return isAdjusting;

}

public void setValueIsAdjusting(boolean isAdjusting) {

this.isAdjusting=isAdjusting;

}

public void addChangeListener(ChangeListener l) {

list.add(l);

}

public void removeChangeListener(ChangeListener l) {

list.remove(l);

}

protected void fireValueChanged() {

for(int i=list.size();--i>=0;)

list.get(i).stateChanged(event);

}

private int value;

private boolean isAdjusting;

private ArrayList<ChangeListener> list=

new ArrayList<ChangeListener>();

private final ChangeEvent event=new ChangeEvent(this);

}

Les Curseurs - ChangeEvent

Le JSlider utilise un ChangeEvent pour notifier un changement des valeurs du modèle.

On écoute ces évènements en enregistrant un ChangeListener.

Un ChangeListener possède une unique méthode stateChanged() qui n'indique pas quelle propriété à changer.

Exemple de changeEvent

Le JSlider utilise un ChangeEvent pour notifier un changement des valeurs du modèle.

private static JSlider createSlider(final JSplitPane pane) {

final BoundedRangeModel model=
new DefaultBoundedRangeModel(0,1,0,100);

JSlider slider=new JSlider(model);

slider.getModel().addChangeListener(new ChangeListener() {

public void stateChanged(ChangeEvent e) {

double location=model.getValue()/(double)model.getMaximum();

pane.setDividerLocation(location);

}

});

return slider;

}

Date & Curseur

On souhaite pouvoir changer la valeur d'une date par jours/heure/minute/seconde, etc.

Lorsque l'on change un
curseur, cela change la
date et raffraichi
l'ensemble des curseurs
en conséquence.

Rappel sur les Dates en Java

Une date est un long correspondant au temps en mili-secondes depuis le 1 janvier 1970.

La classe mutable java.util.Date stocke cet entier,
les méthodes get/setTime() permette de changer la date en miliseconde.

La classe abstraite Calendar interprète une date en fonction d'un calendrier.
La date est rentré par les méthodes get/setTime(Date) et get/setTimeMillis(long).

La méthode Calendar.getInstance() (factory) renvoie le calendrier utiliser localement
(GregorianCalendar pour la france).

La classe java.text.DateFormat affiche en texte.

Rappel sur les Dates en Java - 2

La classe Calendar définie un ensemble de constante :
DAY_OF_MONTH,DAY_OF_YEAR, DAY_OF_WEEK, HOUR,HOUR_OF_DAY, etc.

get/set() permet d'obtenir/changer l'heure :

add() permet d'ajouter/retrancher du temps :

Les minimum/maximum pour chaque constante :

calendar.get(Calendar.HOUR)
calendar.set(Calendar.HOUR, 5);

calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.HOUR_OF_DAY,-2);

calendar.getActualMaximum(Calendar.DAY_OF_MONTH) -> 28/31
calendar.getActualMininum(Calendar.HOUR) -> 0

Design du MVC

Relation entre les vues et les modèles.

vues

SliderDateModel

SliderDateModel

SliderDateModel

SliderDateModel

SliderDateModel

SliderDateModel

DateModel

Le DateModel

Un modèle de date commun.

Indique les changements de date par listener.

class DateModel {

public DateModel(Date date) {

this.time=date.getTime();

}

public void setTime(long time) {

this.time=time;

fireStateChanged();

}

public long getTime() {

return time;

}

public void addChangeListener(ChangeListener l) {

list.add(l);

}

public void removeChangeListener(ChangeListener l) {

list.remove(l);

}

protected void fireStateChanged() {

for(int i=list.size();--i>=0;)

list.get(i).stateChanged(event);

}

private long time;

private final ChangeEvent event=new ChangeEvent(this);

private final ArrayList<ChangeListener> list=

new ArrayList<ChangeListener>();

}

Une vue de la date : DateView

Vue spécifique affichant la date.

La vue s'enregistre sur du modèle à la construction.

class DateView extends JLabel {

public DateView(final DateModel model) {

model.addChangeListener(new ChangeListener() {

public void stateChanged(ChangeEvent e) {

changeText(model);

}

});

changeText(model);

}

void changeText(DateModel model) {

setText(format.format(new Date(model.getTime())));

}

private final DateFormat format=
DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.SHORT);

}

Le modèle de slider

Le modèle dépend du DateModel.

Le modèle n'est pas ré-entrant => pas grave.

class SliderDateModel implements BoundedRangeModel {

public SliderDateModel(DateModel model,int calendarField) {

this.model=model;

this.calendarField=calendarField;

}

...

public int getValue() {

calendar.setTimeInMillis(model.getTime());

return calendar.get(calendarField);

}

public void setValue(int newValue) {

calendar.setTimeInMillis(model.getTime());

calendar.set(calendarField,newValue);

model.setTime(calendar.getTimeInMillis());

}

private int calendarField;

private final DateModel model;

private final transient Calendar calendar=Calendar.getInstance();

}

Le modèle de slider - 2

L'extent dépend de la valeur.

Les maximum/minimum dépendent de la date courante.

public int getExtent() {

int value=getValue();

return (value==getMinimum() || value==getMaximum())?0:1;

}

public int getMaximum() {

calendar.setTimeInMillis(model.getTime());

return calendar.getActualMaximum(calendarField);

}

public int getMinimum() {

calendar.setTimeInMillis(
model.getTime());

return calendar.getActualMinimum(
calendarField);

}

public int getValue() {

calendar.setTimeInMillis(
model.getTime());

return calendar.get(calendarField);

}

public void setExtent(int newExtent) {

throw new UnsupportedOperationException();

}

public void setMaximum(int newMaximum) {

throw new UnsupportedOperationException();

}

public void setMinimum(int newMinimum) {

throw new UnsupportedOperationException();

}

public void setRangeProperties(int value,
int extent, int min, int max, boolean adjusting) {

throw new UnsupportedOperationException();

}

Le modèle de slider - 3

La gestion des évènement est délégué au DateModel.

isAdjusting par slider (pas obligatoire).

public boolean getValueIsAdjusting() {

return valueIsAdjusting;

}

public void setValueIsAdjusting(boolean valueIsAdjusting) {

this.valueIsAdjusting=valueIsAdjusting;

}

public void addChangeListener(ChangeListener l) {

model.addChangeListener(l);

}

public void removeChangeListener(ChangeListener l) {

model.addChangeListener(l);

}

private boolean valueIsAdjusting;

Berstel Jean

2001-03-14T09:29:37