Bonjour,

Je me mets à Java pour ré-écrire un programme VB.
J'utilise la Javadoc, Eclipse comme EDI et "Introduction à Java" de chez O'REILLY ainsi que "Swing la synthèse" de chez Dunod ... et bien entendu le site developpez.com.
Je n'arrive pas à savoir si la façon dont je programme est bonne (même si le programme fait ce que j'attends de lui). J'ai vu lors des discussions que plusieurs d'entre vous aidaient de leurs conseils les débutants.
Je vous soumets la classe suivante. Pouvez-vous me dire s'il y a des erreurs de conception. Merci.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
package histoire;
 
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
 
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.border.*;
import javax.swing.JScrollBar;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.*;
import javax.swing.*;
 
/**
 * @author PATRICE
 *
 */
public class FormeHistoire extends JFrame {
	public static final long serialVersionUID= 1;
 
	private static final String TITRE = "Histoire mondiale";
	private transient static FormeHistoire fen =null;
	//le menu
	private JMenuBar menu = new JMenuBar();
	//le panneau central
		//à gauche
			//la carte
			private JPanel carte=new JPanel();
			//le scrollbar latitude
			private JScrollBar scrLatitude=new JScrollBar(JScrollBar.VERTICAL);
			//le scrollbar longitude
			private JScrollBar scrLongitude= new JScrollBar(JScrollBar.HORIZONTAL);
			//le bouton loupe
			private JButton btnLoupe=new JButton();
		private JPanel gauche=new JPanel();
		//à droite
		private WebBrowser droit;
	private JSplitPane centre=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
	//le panneau sud
		//la barre d'état
		private JPanel barreEtat=new JPanel();
		//le scrollbar dates
		private JScrollBar scbDate = new JScrollBar(JScrollBar.HORIZONTAL);
	private JPanel sud = new JPanel();
 
 
	public static FormeHistoire getInstance(){
		if (fen==null){
			fen=new FormeHistoire();
		}
		return fen;
	}
 
	protected FormeHistoire(){
		//action prévue à la fermeture
		addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				fermerApplication();
			}
		});
		//taille de la fenêtre
		setExtendedState(JFrame.MAXIMIZED_BOTH);
		Rectangle taille=Fonctions.trouverDimensionFen(this);
		setLocation(taille.x,taille.y);
		setPreferredSize(new Dimension(taille.width,taille.height));
		//la taille sur cet ordinateur c'est 1032x742
		//installation du menu, sa hauteur = 23, la hauteur utile devient 719 
		initialiserMenus();
		//installation du bas : barre d'état et scroll dates, sa hauteur 37,
		//la hauteur utile devient 682
		initialiserSud();  //
		//la carte, ses scrolls, son bouton et le WB
		//la hauteur de la carte (et ses contrôles) c'est 682.
		setTitle(TITRE);
		initialiserCentre();
		setVisible(true);
		repaint();
	}
	private void initialiserCentre(){
		centre.setDividerSize(0);
		int h=getPreferredSize().height
				-menu.getPreferredSize().height
				-sud.getPreferredSize().height
				-8;
		centre.setDividerLocation(h);
		//initialisation gauche
		gauche.setLayout(new GridBagLayout());
		GridBagConstraints contraintes=new GridBagConstraints();
		btnLoupe.setMargin(new Insets(0,0,0,0));
		carte.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		Fonctions.addGB(gauche, carte, contraintes, 0, 0,1f,1f);
		Fonctions.addGB(gauche,scrLongitude,contraintes,1,0);
		Fonctions.addGB(gauche, scrLatitude, contraintes, 0,1);
		Fonctions.addGB(gauche,btnLoupe,contraintes,1,1);
		centre.setLeftComponent(gauche);
		//initialisation droite
		droit=new WebBrowser();
		centre.setRightComponent(droit);
		add(centre,BorderLayout.CENTER);
 
		}
 
	private void initialiserSud(){
 
		sud.setLayout(new BoxLayout(sud,BoxLayout.Y_AXIS));
		sud.add(scbDate);
		initialiserBarreEtat();
		sud.add(barreEtat);
		add(sud,BorderLayout.SOUTH);
	}
 
	protected void initialiserBarreEtat(){
 
		barreEtat.setLayout(new BoxLayout(barreEtat,BoxLayout.X_AXIS));
		JLabel lblLocalisation=new JLabel("Localisation");
		lblLocalisation.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		barreEtat.add(Box.createHorizontalStrut(3));
		barreEtat.add(lblLocalisation);
		JLabel lblDate=new JLabel("Date");
		lblDate.setBorder(BorderFactory.createLoweredBevelBorder());
		barreEtat.add(Box.createHorizontalStrut(3));
		barreEtat.add(lblDate);
		JLabel lblLoupe=new JLabel("Loupe");
		lblLoupe.setBorder(BorderFactory.createLoweredBevelBorder());
		barreEtat.add(Box.createHorizontalStrut(3));
		barreEtat.add(lblLoupe);
		barreEtat.add(Box.createGlue());
		JLabel lblPays=new JLabel("Pays");
		lblPays.setOpaque(true);
		lblPays.setBackground(Color.BLACK);
		lblPays.setForeground(Color.WHITE);
		lblPays.setBorder(BorderFactory.createEtchedBorder(5,Color.WHITE,Color.DARK_GRAY));
		barreEtat.add(Box.createHorizontalStrut(5));
		barreEtat.add(lblPays);
		JLabel lblRoi=new JLabel("Souverain");
		lblRoi.setOpaque(true);
		lblRoi.setBackground(Color.BLACK);
		lblRoi.setForeground(Color.WHITE);
		lblRoi.setBorder(BorderFactory.createEtchedBorder(5,Color.WHITE,Color.DARK_GRAY));
		barreEtat.add(Box.createHorizontalStrut(3));
		barreEtat.add(lblRoi);
		barreEtat.add(Box.createHorizontalStrut(3));
		add(barreEtat,BorderLayout.SOUTH);
	}
 
	private void initialiserMenus(){
		JMenu MnFichier=new JMenu("Fichier");
     	JMenuItem Annul = new JMenuItem("Annuler les modifications précédentes");
 
     	Annul.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e){
         JOptionPane.showMessageDialog(null,"Sert à annuler les modifications précédentes");}
     	});
     	MnFichier.add(Annul);
    	//menu valeurs initiales
    	JMenuItem ValeursInit = new JMenuItem("Valeurs initiales");
    	ValeursInit.addActionListener(new ActionListener(){
	        public void actionPerformed(ActionEvent e){
	        JOptionPane.showMessageDialog(null,
	        		"Sert à récupérer les valeurs de l'installation");}
    	});
    	MnFichier.add(ValeursInit);
    	MnFichier.addSeparator();
    	//menu sauver carte
    	JMenuItem MnISauverCarte = new JMenuItem("Sauvegarder une carte");
    	MnISauverCarte.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){
	    	JOptionPane.showMessageDialog(null,
	    			"Sert à Sauver une carte et le texte afférent");}
    	});
    	MnFichier.add(MnISauverCarte);
    	//menu visualiser carte
    	JMenuItem MnIVisualiserCarte = new JMenuItem("Visualiser une carte sauvegardée");
    	MnIVisualiserCarte.addActionListener(new ActionListener(){
	        public void actionPerformed(ActionEvent e){
	        JOptionPane.showMessageDialog(null,
	        		"Sert à visualiser une carte sauvegardée et le texte afférent");}
    	});
    	MnFichier.add(MnIVisualiserCarte);
 
    	//Création du menu Choix
	    JMenu MnChoix = new JMenu("Choix");
        JMenuItem MnIChxRegion = new JMenuItem("d'une région");
        MnIChxRegion.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
            JOptionPane.showMessageDialog(null,
        		   "Sert à choisir une région (un paragraphe)");}
         });
        MnChoix.add(MnIChxRegion);
        JMenuItem MnIChxDate = new JMenuItem("d'une date");
        MnIChxDate.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
            JOptionPane.showMessageDialog(null,
            		"Sert à choisir une date");}
         });
        MnChoix.add(MnIChxDate);
 
        //Création du menu Option
	    JMenu MnOption = new JMenu("Options");
	    JMenu MnZoom = new JMenu("Zoom");
	    JMenu MnDeplacements=new JMenu("Déplacements");
	    JMenu MnSources = new JMenu("Sources");
	    JMenu MnAide = new JMenu("Aide");
 
        MnOption.add(new JCheckBoxMenuItem("Info permanentes"));
        MnOption.add(new JCheckBoxMenuItem("Zone-loupe active"));
        MnOption.add(new JCheckBoxMenuItem("Fleuves visibles"));
        MnOption.add(new JCheckBoxMenuItem("ToolTipText visibles"));
 
        //Création du menu Zoom
        ButtonGroup groupZoom=new ButtonGroup();
        JRadioButtonMenuItem rbmi;
        float [] t= {1F, 1.3F, 1.8F, 2.5F,3.5F,4.5F, 6F, 8F};
        for(int i=0;i<t.length;i++){
            rbmi=new JRadioButtonMenuItem(t[i] + "x ",true);
            groupZoom.add(rbmi);
            MnZoom.add(rbmi);
        }
        t=null;
 
        //Création du menu Déplacements
        JMenu MnDeplDates=new JMenu("Dates");
        String [] valeurs={"1 an","5 ans","10 ans","25 ans","50 ans","100 ans","250 ans","500 ans"};
        ButtonGroup groupDates=new ButtonGroup();
        for(int i=0;i<valeurs.length;i++){
            rbmi=new JRadioButtonMenuItem(valeurs[i],true);
            groupDates.add(rbmi);
            MnDeplDates.add(rbmi);
        }
        MnDeplacements.add(MnDeplDates);
        JMenu MnDeplEspace=new JMenu("Espace (en degré)");
        valeurs=new String [] {"1°","2°","5°","10°","15°","20°"};
        ButtonGroup groupEspace=new ButtonGroup();
        for(int i=0;i<valeurs.length;i++){
            rbmi=new JRadioButtonMenuItem(valeurs[i],true);
            groupEspace.add(rbmi);
            MnDeplEspace.add(rbmi);
        }
        MnDeplacements.add(MnDeplEspace);
 
        //création du menu Sources
        MnSources.add(new JMenuItem("Bibliographie"));
        MnSources.add(new JMenuItem("Liens"));
 
        //création du menu Aide
        MnAide.add(new JMenuItem("Présentation"));
        MnAide.add(new JMenuItem("A propos"));
 
        menu.add(MnFichier);
        menu.add(MnChoix);
        menu.add(MnOption);
        menu.add(MnZoom);
        menu.add(MnDeplacements);
        menu.add(MnSources);
        menu.add(MnAide);
        setJMenuBar(menu);
 
	}
 
	private void fermerApplication(){
		FormeDynastie.getInstance().dispose();
		System.out.println("Au revoir.\nN'oubliez pas de tout nettoyer.");
		System.exit(0);
	}
}
Plus particulièrement :
1) à quoi sert le serialVersionUID que me demande Eclipse
public static final long serialVersionUID= 1;
2) la classe formeHistoire est appelée à partir de la classe application qui appelle aussi l'instance de la classe formeDynasties. Est-il nécessaire d'utiliser la méthode dispose() sur cette instance lors de la fermeture de la fenêtre "principale" ?
3) comment ordonner à une forme d'être maximale dés son affichage sans passer par un getPreferredSize qui reprend les dimensions de l'écran ?
4)j'utilise une classe abstraite Fonctions pour les fonctions génériques sans instance. Par exemple TrouverDimensionFenêtre me renvoie la plus grande dimension possible d'une fenêtre dans l'environnement.
Je donne la fonctions ci-dessous :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
	public static Rectangle trouverDimensionFen(JFrame fen){
		/**
                 * On cherche les dimensions maximum de la fenêtre dans laquelle
                 * peut s'inscrire le programme.
                 * On calcule d'abord les dimensions de l'écran en pixels sous
                 * la forme d'un Rectangle (x,y,w,h)(x,y) sont les coordonnées
                 * du coin supérieur gauche, w est la largeur du rectangle, h est sa
                 * hauteur.
                 * On calcule ensuite les marges qui sont utilisées pour les bordures
                 * sous la forme d'un Insets (h,g,b,d) où h est la marge haute, g est
                 * la marge gauche, b est la marge bas et d est la marge droite.
                 * Dans le cas de cet ordinateur
                 * l'écran vaut (0,0,1024,768)
                 * les marges valent (0,0,34,0)
                 * 34 correspond à la barre d'outil Windows qui se trouve en bas (en
                 * la plaçant à gauche, en gaut ou en bas les valeurs varient)  
                 * On s'imagine donc que les dimensions de la fenêtre se calculent
                 * de la façon suivante : 
         * hauteur = hauteur de l'écran - marge.haut - marge.bas
         * largeur = largeur de l'écran - marge.gauche - marge.droite
                 * mais une fois la fenêtre visible, des marges de 4 pixels
                 * apparaissent de chaque côté, ces marges ne se voient pas car
                 * la fenêtre est positionnée (valeurs x et y) de telle façon que
                 * la marge haut et gauche ne se voient pas.
                 * En fait une fenêtre a ses propres marges intérieures sous la forme d'un Insets
                 * Les valeurs pour cet ordinateur est m=(4,30,4,4)
                 * Les dimensions à prendre en compte sont donc : 
         * x=E.x+M.left-m.right,
                 * y=E.y+M.top-m.left,
         * hauteur = hauteur de l'écran - (marge.haut + marge.bas) + (m.haut+m.bas) 
         * largeur = largeur de l'écran - (marge.gauche + marge.droite) + (m.gauche+m.droite)
         */
		fen.pack();
		fen.setVisible(true);
		GraphicsConfiguration gc=
            GraphicsEnvironment.getLocalGraphicsEnvironment().
            	getDefaultScreenDevice().getDefaultConfiguration();
		//T la taille de l'écran en pixel
		Rectangle E = gc.getBounds();
		//M les marges systèmes
        Insets M = fen.getToolkit().getScreenInsets(gc);
        //m les marges d'une fenêtre
        Insets m=fen.getInsets();
		return new Rectangle(
							 E.x+M.left-m.right,
							 E.y+M.top-m.left,
							 E.width-(M.left+M.right)+(m.left+m.right),
							 E.height-(M.top+M.bottom) +(m.left+m.right));
	}
Cette méthode est-elle correcte ?