Tu l'avais déjà écris ...Code:
1
2 AddCommand command = AddCommand(plan,nvlElt); CommandManager.getInstance().execute(command);
Version imprimable
Tu l'avais déjà écris ...Code:
1
2 AddCommand command = AddCommand(plan,nvlElt); CommandManager.getInstance().execute(command);
oui mais lorsque j'écris cela :
pour la premiere ligne on me met une erreur au deuxieme AddCommand, il faut rajouter un new, je pense non ?Code:
1
2
3 AddCommand command = AddCommand(plan,nvlElt); CommandManager.getInstance().execute(command);
et pour la deuxieme ligne elle est souligné en jaune avec ce message :
The static method execute(Command) from the type CommandManager should be accessed in a static way
j'ai donc remplacé par cela :
et du coup lorsque je dessine une ligne et que j'appuie sur mon bouton undo il m'affiche ce message :Code:
1
2
3
4 AddCommand command = new AddCommand(plan,nvlElt); CommandManager.getInstance(); CommandManager.execute(command);
Debug processor : No command to undo
c'est celle que j'affiche dans mon commandManager ici :
Pourquoi çà ne marche pas ?Code:
1
2
3
4
5
6
7
8
9
10
11 public void performUndo() { if (!this.undoList.isEmpty()) { Command command = this.undoList.get(this.undoList.size() - 1); this.undoList.remove(this.undoList.size() - 1); command.undo(); this.redoList.add(command); }else{ System.out.println("Debug processor : No command to undo"); } }
Cela veux dire que tu n'as pas la commande dans ta liste d'historique.
Remplacement moi ça :
Par :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 public static void execute(Command command) { getInstance().performAction(command); } public void performAction(Command command) { command.execute(); this.redoList.clear(); if (command instanceof Command) { this.undoList.add((Command) command); } else { this.undoList.clear(); this.reallyDirty = true; } }
Code:
1
2
3
4
5
6
7
8 public void execute(Command command) { System.out.println("Debug processor : Commande exécuté :"+command.getClass().getName()); command.execute(); System.out.println("Debug processor : List redo vidé"); this.redoList.clear(); System.out.println("Debug processor : List undo : élément ajouté !"); this.undoList.add(command); }
ma classe commandManager est maintenant comme cela :
et dans ma classe insertionLigneListener j'ai bien cela :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 public class CommandManager { private ArrayList<Command> redoList; private ArrayList<Command> undoList; private boolean reallyDirty = false; static CommandManager _instance = null; public static CommandManager getInstance() { if (_instance == null) _instance = new CommandManager(); return _instance; } public static void undo() { getInstance().performUndo(); } public static void execute() { getInstance().performExecute(); } public boolean isDirty() { return this.reallyDirty || !hasUndo(); } public boolean hasUndo() { return !this.undoList.isEmpty(); } public boolean hasExecute() { return !this.redoList.isEmpty(); } public void execute(Command command) { System.out.println("Debug processor : Commande exécuté :" + command.getClass().getName()); command.execute(); System.out.println("Debug processor : List redo vidé"); this.redoList.clear(); System.out.println("Debug processor : List undo : élément ajouté"); this.undoList.add(command); } public void performExecute() { if (!this.redoList.isEmpty()) { Command command = this.redoList.get(this.redoList.size() - 1); this.redoList.remove(this.redoList.size() - 1); command.execute(); this.undoList.add(command); } else { System.out.println("Debug processor : No command to redo"); } } public void performUndo() { if (!this.undoList.isEmpty()) { Command command = this.undoList.get(this.undoList.size() - 1); this.undoList.remove(this.undoList.size() - 1); command.undo(); this.redoList.add(command); } else { System.out.println("Debug processor : No command to undo"); } } public void reset() { this.undoList.clear(); this.redoList.clear(); this.reallyDirty = false; } private CommandManager() { redoList = new ArrayList<Command>(); undoList = new ArrayList<Command>(); } }
et lorsque je selectionne sur le bouton undo après avoir ajouter une ligne il me m'est le message suivant :Code:
1
2
3 AddCommand command = new AddCommand(plan,nvlElt); CommandManager.getInstance().execute(command);
Et plus haut il y a marqué cela :Code:
1
2 11-07 17:26:03.486: I/System.out(5785): Debug processor : No command to undo
je précise aussi que ma classe Main est dans un package et les autres classes insertion, ligne, addcomand, commandManager et l'interface command dans un autre, je ne sais pas si cela change quelque chose.Code:
1
2
3
4 11-07 17:25:54.121: I/System.out(5785): Debug processor : Commande exécuté :com.exemple.ligne.AddCommand 11-07 17:25:54.121: I/System.out(5785): Debug processor : List redo vidé 11-07 17:25:54.121: I/System.out(5785): Debug processor : List undo : élément ajouté
Je trouve bizarre car vu les messages que tu m'a dit d'ajouter, on voit bien que l'élément à été ajouté mais il indique que ma liste est vide
A mon avis tu devrait faire un peu de debug sur ton application et voir quand ta liste est vidé.
Car tu la remplis à un moment, et quand tu fait le undo(), celle-ci est vide. Cela veux dire qu'elle a été vidé par quelqu'un à un moment...
Cordialement,
Patrick Kolodziejczyk.
Le fonctionnement marche bien car lorsque je dessine une ligne et que j'appuie sur le bouton undo et le bouton redo je vois bien que cela marche, lorsque je vérifie en mode débug seulement ma ligne ne s'efface pas de mon plan. Il faut peu être que je fasse appel a ma méthode doBitmap a nouveau ? je ne sais pas ce que vous en penser car je n'utilise pas paint
J'ai donc résolu le problème en faisant appel à la méthode invalidate() au niveau de ma classe AddCommand dans mes méthodes execute et undo.
Je remercie tous ce qui ont pu m'aider
J'ai un autre petit problème c'est que j'ai la possibiliter de rajouter une fenetre sur ma ligne, qui n'est autre qu'une autre ligne d'une autre couleur ma classe et la suivante :
et du coup comme pour l'exemple précédent j'ai voulu remplacer :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 private void onTouchDown(MotionEvent event) { if (ligneSelected != null) { if (ligneSelected.isVertical()) { if (selection == SELECT_WINDOW) selectedWindow = ligneSelected.getFenetreAt( ligneSelected.getPosition().x, (int) event.getY()); } else { if (selection == SELECT_WINDOW) selectedWindow = ligneSelected.getFenetreAt( (int) event.getX(), ligneSelected.getPosition().y); } } if (plan.getSelectedLigne() == null || (selectedWindow == null)) { if (plan.getSelectedLigne() == null) plan.setSelectedLigne(plan.getCurrentFloor().getSelectedLigne( (int) event.getX(), (int) event.getY())); ligneSelected = plan.getSelectedLigne(); if (ligneSelected != null) { ligneSelected.setSelected(true); if (ligneSelected.isVertical()) { switch (plan.getEltBatToInsert()) { case Plan.FENETRE: { nvlEltF = Fenetre.FenetreVerticale("FENETRE_1", ligneSelected.getPosition().x, (int) event.getY(), 0); nvlEltF.setMeterThickness(nvlEltF.getPixelsThickness() / plan.getScale()); /** Largeur de la fenetre **/ nvlEltF.setMeterLength(nvlEltF.getPixelsLength() / plan.getScale()); /** Ajout de la fenêtre à la ligne **/ ligneSelected.add(nvlEltF); selectedWindow = nvlEltF; break; } } } else { switch (plan.getEltBatToInsert()) { case Plan.FENETRE: { nvlEltF = Fenetre.FenetreHorizontale("FENETRE_", (int) event.getX(), ligneSelected.getPosition().y, 0); nvlEltF.setMeterLength(nvlEltF.getPixelsThickness() / plan.getScale()); nvlEltF.setMeterThickness(nvlEltF.getPixelsLength() / plan.getScale()); ligneSelected.add(nvlEltF); selectedWindow = nvlEltF; break; } } } } } else { if (ligneSelected.isVertical()) { if (selection == SELECT_WINDOW) selectedWindow = ligneSelected.getFenetreAt( ligneSelected.getPosition().x, (int) event.getY()); } else { if (selection == SELECT_WINDOW) selectedWindow = ligneSelected.getFenetreAt( (int) event.getX(), ligneSelected.getPosition().y); } } plan.invalidate(); }
par :Code:
1
2 ligneSelected.add(nvlEltF);
Donc du coup de la même maniere j'ai ajouter a ma classe addCommand :Code:
1
2
3 command = new AddCommand(ligneSelected, nvlEltF); CommandManager.getInstance().execute(command);
et dans ma méthode execute :Code:
1
2
3
4
5 public AddCommand(Ligne ligneSelected, Fenetre nvlEltF) { this.ligne = ligneSelected; this.fenetre = nvlEltF; }
Mais çà ne veut pas inserer ma fenetre sur la ligne, alors que çà le faisait bien avec juste :Code:
1
2
3
4
5 if (fenetre != null) { this.plan.add(this.fenetre); plan.invalidate(); }
J'ai besoin de cela car pour l'instant si je dessine une ligne avec une fenêtre si je fais mon bouton undo alors la ligne s’enlève au premier clic sur le bouton alors que la fenêtre devrait s'enlever avant,Code:
1
2 ligneSelected.add(nvlEltF);
merci
Bonjour, j'ai toujours le même problème si quelqu'un pouvait m'aider,
j'ai donc dans ma classe AddCommand le code suivant :
et ma classe InsertionPorte et la suivante :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 public class AddCommand implements Command { private Plan plan; private Ligne ligne; private Porte porte; private EltPlan elt; AddCommand(Plan p, Ligne l) { this.plan = p; this.ligne = l; } AddCommand(Ligne l, Porte p) { this.ligne = l; this.porte = p; } public AddCommand(Ligne ligneSelected, EltPlan elt) { this.ligne = ligneSelected; this.setElt(elt); } public void execute() { if ((ligne != null && porte == null)) { this.plan.add(this.ligne); } if((porte != null)){ this.ligne.add(this.porte); } plan.invalidate(); } @Override public void undo() { if (ligne != null) this.plan.remove(this.ligne); if (porte != null) this.ligne.remove(this.porte); plan.invalidate(); } public EltPlan getElt() { return elt; } public void setElt(EltPlan elt) { this.elt = elt; } }
Je n'arrive donc pas à ajouter une porte sur mon mur et donc l'ajouter dans ma pile afin de pouvoir utiliser par la suite mon bouton undoCode:
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
157 public class InsertionPorteListener implements OnTouchListener { private Plan plan; private Ligne ligneSelected; private EltPlan selectedDoor; public AddCommand command; private Porte nvlEltP; private int selection = 0; public static final int NO_SELECTION = 0; public static final int SELECT_DOOR = 1; public InsertionPorteListener(Plan plan) { this.plan = plan; } @Override public boolean onTouch(View v, MotionEvent event) { v.performClick(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { onTouchDown(event); return true; } case MotionEvent.ACTION_MOVE: { onTouchMove(event); return true; } case MotionEvent.ACTION_UP: { onTouchUp(event); break; } } return false; } private void onTouchDown(MotionEvent event) { if (ligneSelected != null) { if (ligneSelected.isVertical()) { if (selection == SELECT_DOOR) selectedDoor = ligneSelected.getPorteAt( ligneSelected.getPosition().x, (int) event.getY()); } else { if (selection == SELECT_DOOR) selectedDoor = ligneSelected.getPorteAt((int) event.getX(), ligneSelected.getPosition().y); } } if (plan.getSelectedLigne() == null || (selectedDoor == null)) { /** Si on sélectionne rien on peut ajouter une porte **/ if (plan.getSelectedLigne() == null) plan.setSelectedLigne(plan.getCurrentFloor().getSelectedLigne( (int) event.getX(), (int) event.getY())); /** indication de sélection de la ligne **/ ligneSelected = plan.getSelectedLigne(); /** Si ligne sélectionné **/ if (ligneSelected != null) { ligneSelected.setSelected(true); if (ligneSelected.isVertical()) { switch (plan.getEltBatToInsert()) { case Plan.PORTE: { nvlEltP = Porte.PorteVerticale("PORTE_1", ligneSelected.getPosition().x, (int) event.getY(), 0); nvlEltP.setMeterThickness(nvlEltP.getPixelsThickness() / Plan.getScale()); nvlEltP.setMeterLength(nvlEltP.getPixelsLength() / Plan.getScale()); command = new AddCommand(ligneSelected, nvlEltP); CommandManager.getInstance().execute(command); // ligneSelected.add(nvlEltP); selectedDoor = nvlEltP; break; } } } else { switch (plan.getEltBatToInsert()) { case Plan.PORTE: { nvlEltP = Porte.PorteHorizontale("PORTE_2", (int) event.getX(), ligneSelected.getPosition().y, 0); nvlEltP.setMeterLength(nvlEltP.getPixelsThickness() / Plan.getScale()); nvlEltP.setMeterThickness(nvlEltP.getPixelsLength() / Plan.getScale()); command = new AddCommand(ligneSelected, nvlEltP); CommandManager.getInstance().execute(command); ligneSelected.add(nvlEltP); selectedDoor = nvlEltP; break; } } } } } else { if (ligneSelected.isVertical()) { if (selection == SELECT_DOOR) selectedDoor = ligneSelected.getPorteAt( ligneSelected.getPosition().x, (int) event.getY()); } else { if (selection == SELECT_DOOR) selectedDoor = ligneSelected.getPorteAt((int) event.getX(), ligneSelected.getPosition().y); } } plan.invalidate(); } private void onTouchMove(MotionEvent event) { if (selectedDoor != null) { if (ligneSelected.isVertical()) selectedDoor .setPosition(selectedDoor.getPosition().x, (int) (event .getY() - selectedDoor.getPixelsLength() / 2)); else selectedDoor .setPosition((int) (event.getX() - selectedDoor .getPixelsThickness() / 2), selectedDoor .getPosition().y); } plan.invalidate(); } private void onTouchUp(MotionEvent event) { } public void reinitialize() { setSelectedLigne(null); setSelectedPorte(null); } public void setSelectedLigne(Ligne l) { ligneSelected = l; } public void setSelectedPorte(Porte porte) { selectedDoor = porte; } public void setSelection(int selection) { this.selection = selection; } }
J'ai changer quelque truc dans mon code qui me permettent maintenant d'ajouter ma porte sur ma ligne, voici mon code :
avant lorsque je faisais un redo mais que je n'indiquer pas plan.invalidate(); on ne voyais rien sur l’écran changer, maintenant on voit bien la suppression de la ligne j'ai voulu ajouter cela pour ma porte mais il m'indique une erreur lorsque je l'ajoute j'ai l'impression que tout est bon mais qu'il faudrait un truc pour rafraîchir le plan ou la ligne pour voir la suppression de la porteCode:
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 public class AddCommand implements Command { private Plan plan; private Ligne ligne; private Porte porte; private EltPlan elt; AddCommand(Plan p, Ligne l) { this.plan = p; this.ligne = l; } AddCommand(Ligne l, Porte p) { this.ligne = l; this.porte = p; } public AddCommand(Ligne ligneSelected, EltPlan elt) { this.ligne = ligneSelected; this.setElt(elt); } public void execute() { if ((ligne != null)) { if (porte != null) { this.ligne.add(this.porte); } else { this.plan.add(this.ligne); plan.invalidate(); } } } @Override public void undo() { if (ligne != null) { if (porte != null) { this.ligne.remove(this.porte); //plan.invalidate(); } else { this.plan.remove(this.ligne); plan.invalidate(); } } } public EltPlan getElt() { return elt; } public void setElt(EltPlan elt) { this.elt = elt; } }
Si j'ai bien compris ton invalidate() déclenche la mise à jour de ce que tu affiche.Code:
1
2
3
4
5
6 if (porte != null) { this.ligne.add(this.porte); } else { this.plan.add(this.ligne); plan.invalidate(); }
Comment est mise à jour la ligne dans ce cas là ? Doit-elle faire ligne.getPlan().invalidate() ?
De manière général, quand tu as une vue qui affiche/représent le modèle pour l'utilisateur. Il est intéressant d'avoir un mécanisme pour invalider l'ensemble de la vue. Ainsi, avoir une mise à jour propre par rapport au modèle. (Particulièrement dans ces cas de débug.)
Cordialement,
Patrick Kolodziejczyk.
Oui, exactement lorsque j'enleve plan.invalidate() et que j'appuie sur undo à l'écran rien ne ce passe ma ligne est toujours présente alors que j'affiche dans ma console qu'il y a un element dans ma pile. Justement je ne sais pas comment faire pour mettre à jour ma ligne, j'ai essayer comme vous m'avez indiqué mais il ne le reconnait pas. Je vous aurait bien envoyé mon projet pour que vous puissiez voir par vous même mais il est trop gros pour une pièce jointe.
J'ai donc defini une variable plan dans ma classe ligne et j'ai donc ajouté comme vous me l'avez dit : ligne.getPlan().invalidate() mais çà ne marche pas et lorsque j'appuie sur undo j'ai ce message dans la console :
Code:
1
2
3
4
5
6
7 01-21 11:04:55.471: E/AndroidRuntime(12644): FATAL EXCEPTION: main 01-21 11:04:55.471: E/AndroidRuntime(12644): java.lang.NullPointerException 01-21 11:04:55.471: E/AndroidRuntime(12644): at com.example.ligne.indoor.AddCommand.undo(AddCommand.java:43) 01-21 11:04:55.471: E/AndroidRuntime(12644): at com.example.ligne.indoor.CommandManager.performUndo(CommandManager.java:64) 01-21 11:04:55.471: E/AndroidRuntime(12644): at com.example.ligne.indoor.CommandManager.undo(CommandManager.java:20) 01-21 11:04:55.471: E/AndroidRuntime(12644): at com.example.ligne.IndoorActivity.onClick(IndoorActivity.java:489)
L'erreur est dû au fait que votre ligne n'a pas de plan associé.
Il est très probable que quand vous ajoutez votre ligne à votre plan. Vous ne référencez pas le plan dans votre ligne :
Par exemple :Code:this.plan.add(this.ligne);
Ce qui te permet d'invalider ce qui contient ta ligne :Code:this.ligne.setContainer(this.plan);
Note :Code:this.ligne.getContainer().invalidate();
Tu aurai dû crée deux commandes distincte l'une ajoutant une Porte à une Ligne et l'autre une Ligne à un Plan. (Les deux héritant de le la même classe.)
Ou avoir une commande plus générique avec :
Avec Plan/Ligne/Porte héritant de Elt.Code:AddCommand(Elt contenant, Elt Contenu)
Et fait la fonction qui met à jour tout. Tu verra que c'est utile.
Cordialement,
Patrick Kolodziejczyk.
D'accord donc pour vous je devrais revoir un peu ma conception et comment je pourrais le faire ?
setContainer je le fait ou ?
Je declarer une variable container dans ligne avec Plan en parametre ?
Et container est de quel type ?
Dans ma classe Addcommand qu'est ce que je dois changer ?
Dans mon cas la classe Porte herite de EltPlan et Ligne herite de EltPlan
Et du coup tu me dis de faire de méthode car pour le moment je n'ai que celle là ?
Code:
1
2
3
4
5 public AddCommand(Ligne ligneSelected, EltPlan elt) { this.ligne = ligneSelected; this.setElt(elt); }
il faudrait :
Je vous remercie de votre réponseCode:
1
2
3
4
5 public AddCommand(Porte porteSelected, Ligne ligneSelected){ this.porte = porteSelected; this.setLigne(porteSelected); }
Votre container doit-être au niveau de votre EltPlan.
Cependant, celui-ci doit-être soit un EltPlan soit un Plan. Ce qui implique une classe parent entre les deux. Si plan n'est pas déjà un EltPlan.
Il n'y a rien à ajouter dans votre classe AddCommand.
Le mieux serai de revoir votre méthode add(EltPlan element). Celle-ci devrait :
- Vérifier si votre élément n'est pas déjà dans un autre container. (Si c'est le cas agir en conséquence erreur, ou l’enlever de l'ancien container.)
- Ajouter l’élément au container.
- Indiquer à l'élément qui le contient via le setContainer.
Ainsi, lorsque que vous manipulez un élément, vous êtes toujours en mesure de retrouver son container. Et donc l'invalider si nécessaire.
Vous devriez regarder comment cela est fait dans Swing. Car, c'est exactement les mêmes concepts qui sont utilisés. Il y a la même problématique de parcours arborescence, d'invalidation des composants(repaint.), de transmissions d’événement (Comment savoir si vous avez cliqué sur tel ou tel composant ?)
Cordialement,
Patrick Kolodziejczyk.
Je vous remercie de votre réponse, j'ai fait cela est tout marche :
Merci encoreCode:
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 public class AddCommand implements Command { private Plan plan; private Ligne ligne; private Porte porte; private EltPlan elt; AddCommand(Plan p, Ligne l) { this.plan = p; this.ligne = l; } AddCommand(Ligne l, Porte p) { this.ligne = l; this.porte = p; } public AddCommand(Ligne ligneSelected, EltPlan elt) { this.ligne = ligneSelected; this.setElt(elt); } public void execute() { if ((ligne != null)) { if (porte != null) { this.ligne.add(this.porte); this.ligne.getPlan().invalidate(); } else { this.ligne.setPlan(this.plan); this.plan.add(this.ligne); plan.invalidate(); } } } @Override public void undo() { if (ligne != null) { if (porte != null) { this.ligne.remove(this.porte); this.ligne.getPlan().invalidate(); } else { this.plan.remove(this.ligne); plan.invalidate(); } } } public EltPlan getElt() { return elt; } public void setElt(EltPlan elt) { this.elt = elt; } public Plan getPlan() { return plan; } public void setPlan(Plan plan) { this.plan = plan; } public Ligne getLigne() { return ligne; } public void setLigne(Ligne ligne) { this.ligne = ligne; } public Porte getPorte() { return porte; } public void setPorte(Porte porte) { this.porte = porte; } }