[Swing] JSpinner personnalisé
Bonjour à tous,
Je fais appel à votre science pour m'aider à résoudre un petit problème concernant les JSpinner :
Je voudrais en effet créer un JSpinner qui permet de choisir une durée sous la forme "00:00".
J'aimerais que ce JSpinner ait un comportement similaire à celui d'un JSpinner de Date : lorsque le curseur est sur le nombre des heures, le clic sur les flèches du JSpinner aura un effet sur le nombre d'heures, idem pour les minutes.
De plus j'aimerais qu'il soit éditable avec une vérification de la saisie (un JFormattedTextField quoi) mais c'est une autre histoire.
Mais j'ai tout essayé, de l'AbstractSpinnerModel au SpinnerNumberModel, mais je n'arrive pas à faire en sorte d'adapter le JSpinner à ma classe représentant une durée que voici :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
| public class Duration {
/** Number of milliseconds in an hour */
private static final long MILLISECONDS_IN_AN_HOUR = 1000 * 60 * 60;
/** Number of milliseconds in a minute */
private static final long MILLISECONDS_IN_A_MINUTE = 1000 * 60;
/** Hours */
private int hours;
/** Minutes */
private int minutes;
/**
* Constructor
* Initializes the duration to 0 hours and 0 minutes
*/
public Duration() {
setMilliseconds(0);
}
/**
* Constructor
* @param duration the duration in milliseconds
*/
public Duration(long duration) {
setMilliseconds(duration);
}
/**
* Constructor
* @param hours the hours
* @param minutes the minutes
*/
public Duration(int hours, int minutes) {
setHours(hours);
setMinutes(minutes);
}
/**
* Constructor
* @param duration the duration from which the current duration is initialized
*/
public Duration(Duration duration) {
setMilliseconds(duration.getMilliseconds());
}
/**
* Adds a duration to the current duration
* @param duration the duration to add
*/
public void add(Duration duration) {
setMilliseconds(getMilliseconds() + duration.getMilliseconds());
}
/**
* Substract a duration to the current duration
* @param duration the duration to substract
*/
public void substract(Duration duration) {
if (getMilliseconds() <= duration.getMilliseconds()) {
setMilliseconds(0);
} else {
setMilliseconds(getMilliseconds() - duration.getMilliseconds());
}
}
/**
* @return the duration in milliseconds
*/
public long getMilliseconds() {
return (this.hours * Duration.MILLISECONDS_IN_AN_HOUR + this.minutes
* Duration.MILLISECONDS_IN_A_MINUTE);
}
/**
* @param duration the duration to set in milliseconds
* Duration can't be negative
*/
public void setMilliseconds(long duration) {
if (duration < 0) {
throw new IllegalArgumentException("Duration can't be negative");
}
this.hours = (int) (duration / Duration.MILLISECONDS_IN_AN_HOUR);
this.minutes = (int) (duration % Duration.MILLISECONDS_IN_AN_HOUR
/ Duration.MILLISECONDS_IN_A_MINUTE);
}
/**
* @return the duration hours
*/
public int getHours() {
return this.hours;
}
/**
* @param hours the number of hours to set
* Number of hours can't be negative
*/
public void setHours(int hours) {
if (hours < 0) {
throw new IllegalArgumentException("Number of hours can't be negative");
}
this.hours = hours;
}
/**
* @return the duration minutes
*/
public int getMinutes() {
return this.minutes;
}
/**
* @param minutes the number of minutes to set
* Number of minutes must be an integer between 0 and 59
*/
public void setMinutes(int minutes) {
if ((minutes < 0) || (minutes > 59)) {
throw new IllegalArgumentException(
"Number of minutes must be an integer between 0 and 59");
}
this.minutes = minutes;
}
@Override
public String toString() {
String hours = Integer.toString(this.hours);
String minutes = Integer.toString(this.minutes);
if (this.hours < 10) {
hours = "0" + this.hours;
}
if (this.minutes < 10) {
minutes = "0" + this.minutes;
}
return (hours + ":" + minutes);
}
/**
* Converts a String into a Duration
* @param durationString the duration string to convert into Duration
*/
public static Duration valueOf(String durationString) {
if (durationString.length() != 5 || durationString.charAt(2) != ':') {
throw new IllegalArgumentException("Duration string is not in the correct format");
}
Duration duration = new Duration();
duration.setHours(Integer.valueOf(durationString.substring(0, 2)));
duration.setMinutes(Integer.valueOf(durationString.substring(3, 5)));
return duration;
}
} |
Voici le code du modèle de mon JSpinner :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class SpinnerDurationModel extends AbstractSpinnerModel {
/** Duration */
private Duration duration;
/**
* Constructor
*/
public SpinnerDurationModel() {
super();
this.duration = new Duration();
}
@Override
public Object getValue() {
return this.duration;
}
@Override
public void setValue(Object duration) {
this.duration = (Duration)duration;
}
@Override
public Object getNextValue() {
Duration nextDuration = new Duration(this.duration);
nextDuration.add(new Duration(0, 1));
return nextDuration;
}
@Override
public Object getPreviousValue() {
Duration previousDuration = new Duration(this.duration);
previousDuration.substract(new Duration(0, 1));
return previousDuration;
}
} |
Visiblement, la méthode appelée lors du clic sur une flèche du JSpinner est setValue, et il semble qu'elle est appelée avec une String en paramètre. Pourtant mes méthodes getNext/PreviousValue ne retournent pas une String mais bien une durée.
D'où une exception : impossible de caster une String en Duration, ce qui est normal.
J'ai essayé quelques feintes mais ça me dérange de changer cette conception qui me semble correcte (ou alors je me trompe et j'attends vos corrections ;) ).
Enfin bref, un peu d'aide de votre part serait la bienvenue !
Merci d'avance ! :)