Licence Informatique 2ème année Programmation Objet 1
Contrôle continu – 25/04/2019 - 1h30
Numéro étudiant : Nom :
Prénom :
Les notes de cours, TD et TP sont autorisées.
Exercice 1 (4 points) : Indiquez quelles lignes du programme suivant sont incorrectes 01 package pack1;
02
03 interface InterToto { 04 int getI();
05 }
06 package pack1;
07
08 class Titi extends Toto { 09 Titi(int i){
10 super();
11 this.i = 32;
12 }
13 private int getI() { 14 return 3;
15 } 16 }
17 package pack1.pack1_1;
18
19 public abstract class Toto implements pack1.InterToto{
20 int i=0;
21 protected Toto() { 22 this.i = 27;
23 } 24 }
Exercice 2 (6 points) : on veut écrire un programme pour représenter les Contes des 1001 Nuits. Un conte est composé d'un début (chaine de caractères), d'une fin (chaine aussi), et d'un certain nombre de parties stockées dans l'ordre. Chaque partie peut être une chaine de caractères, mais aussi une histoire en elle-même : les 1001 Nuits racontent l'histoire de Shéhérazade, qui elle-même raconte des histoires dans lesquelles des personnages racontent des histoires, dans lesquelles des personnages racontent des histoires, etc.
Tous les éléments des contes (histoires, parties, débuts et fins) doivent implémenter l'interface suivante :
public interface Racontable{
public void print(); // écrit l'objet à l'écran }
2.1 Proposez du code objet pour représenter les Contes des 1001 Nuits, sachant que la classe String est final (aucune classe ne peut en hériter). (5 points)
2.2 Écrivez une méthode principale qui crée une histoire commençant par "il était une fois", se terminant par "fin", ayant pour première partie "..." et pour deuxième partie une histoire qui commence par "ce jour-là", se termine par "à jamais" et a pour unique partie "...". (1 point)
Exercice 3 (10 points) : Il s'agit de développer une interface graphique qui indique l'heure de différentes façons.
Chaque composant qui indique l'heure doit implémenter l'interface HourDisplay qui ne doit pas être modifiée (rappel : toutes les classes des composants graphiques en Java héritent de Component) :
public interface HourDisplay{
public Component getComponent(); // renvoie le composant à afficher public void oneSecondMore(); // rafraichit l'affichage
}
La classe Horloge représente l'interface générale et ne doit pas être modifiée (sauf à la question 3.4).
public class Horloge extends JFrame{
private ArrayList<HourDisplay> dis;
private Box b;
public Horloge(){
super("Horloge");
this.dis = new ArrayList<HourDisplay>();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.b = new Box(BoxLayout.Y_AXIS);
this.add(this.b); this.setVisible(true);
} // renvoie l'heure courante
public static int getHour(){ return LocalDateTime.now().getHour(); } // renvoie la minute courante
public static int getMinute(){ return LocalDateTime.now().getMinute(); } // renvoie la seconde courante
public static int getSecond(){ return LocalDateTime.now().getSecond(); } public void addHourDisplay(HourDisplay hd){
this.b.add(hd.getComponent());
this.dis.add(hd);
this.pack(); this.repaint();
}
public void run(){
while(true){
try{Thread.sleep(1000);}catch(InterruptedException e){}
for(HourDisplay hd:this.dis) hd.oneSecondMore();
} } }
3.1 Écrivez une classe qui permette d'afficher l'heure sous forme d'un texte (Ex. 08:52:12) (2.5 points)
3.2 Écrivez une classe qui permette d'afficher l'heure sous forme d'un cadran à aiguilles. (2.5 points) Le code suivant dessine ce genre de cadran sur un objet de type Graphics si les variables h, m et s contiennent l'heure, la minute et la seconde courantes.
public void paint(Graphics g){
int b=15;
g.setColor(new Color(187, 210, 225));
g.fillRect(0,0,this.getWidth(),this.getHeight());
g.setColor(Color.BLACK);
((Graphics2D) g).setStroke(new BasicStroke(4.0f));
g.drawOval(b,b,this.getWidth()-2*b,this.getHeight()-2*b);
int x=this.getWidth()/2,y=this.getHeight()/2,r=(this.getWidth()-2*b)/2;
for(int i=0;i<12;i++){
double a = i*Math.PI*2/12;
g.drawLine((int)(x+0.95*r*Math.sin(a)),(int)(y-0.95*r*Math.cos(a)), (int)(x+1.05*r*Math.sin(a)),(int)(y-1.05*r*Math.cos(a)));
}
double ah = Math.PI*2*(h%12)/12, am = Math.PI*2*m/60, as = Math.PI*2*s/60;
((Graphics2D) g).setStroke(new BasicStroke(5.0f));
g.drawLine(x,y,(int) (x+0.7*r*Math.sin(ah)),(int) (y-0.7*r*Math.cos(ah)));
((Graphics2D) g).setStroke(new BasicStroke(3.0f));
g.setColor(new Color(120,120,120));
g.drawLine(x,y,(int)(x+0.85*r*Math.sin(am)),(int)(y-0.85*r*Math.cos(am)));
((Graphics2D) g).setStroke(new BasicStroke(1.0f));
g.drawLine(x,y,(int) (x+r*Math.sin(as)),(int) (y-r*Math.cos(as)));
}
3.3 Écrivez une méthode main pour que l'application ait l'apparence de l'image. (1.5 points)
3.4 L'horloge précédente ne fonctionne pas correctement, car l'affichage n'est pas rafraichi tout à fait à chaque seconde (la boucle while de la méthode run met plus d'une seconde à s'exécuter, ce qui introduit un décalage). On va donc utiliser un Timer, qui déclenche un événement à intervalle régulier. Les deux instructions suivantes créent un objet Timer qui génère un ActionEvent toutes les 1000 millisecondes. Cet ActionEvent est récupéré par l'écouteur a, qui est de type ActionListener.
Timer t = new Timer(1000, a); // a est un ActionListener t.start(); // on démarre le Timer
Modifiez la classe Horloge et la méthode main pour que les mises à jour de l'affichage soient provoquées toutes les secondes par un Timer. (3.5 points)
CO RR
EC TIO N
Exercice 1
l'interface InterToto doit être publique, il manque un import pack1.pack1_1.Toto; dans le fichier de la classe Titi, la méthode getI dans Titi doit être au moins sans modifieur, l'attribut i de Toto devrait être au moins protected.
Exercice 2
public class Chaine implements Racontable{
String s;
public Chaine(String s){
this.s = s;
}
public void print(){ System.out.println(s); } }
import java.util.ArrayList;
public class Histoire implements Racontable{
Chaine debut,fin;
ArrayList<Racontable> parties;
public Histoire(Chaine d, Chaine f){
this.debut = d;
this.fin = f;
this.parties = new ArrayList<Racontable>();
}
public void addPartie(Racontable r){
this.parties.add(r);
}
public void print(){
this.debut.print();
for(Racontable r:this.parties) r.print();
this.fin.print();
}
public static void main(String[] t){
Histoire h = new Histoire(new Chaine("il était une fois"),new Chaine("fin"));
h.addPartie(new Chaine("..."));
Histoire h2 = new Histoire(new Chaine("ce-jour-là"),new Chaine("à jamais"));
h2.addPartie("...");
h.addPartie(h2);
h.print();
} }
Exercice 3
public class Digital extends JLabel implements HourDisplay{
public Digital(){
super();
this.setFont(this.getFont().deriveFont(36.0f));
this.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
this.setText(format(Horloge.getHour())+":"+format(Horloge.getMinute())
+":"+format(Horloge.getSecond()));
this.setAlignmentX(Component.CENTER_ALIGNMENT);
}
private static String format(int i){
if(i<10) return "0"+i;
else return i+"";
}
public void oneSecondMore(){
this.setText(format(Horloge.getHour())+":"+format(Horloge.getMinute())
+":"+format(Horloge.getSecond()));
this.repaint();
}
public Component getComponent(){
return this;
CO RR
EC TIO N
} }
public class Analog extends JPanel implements HourDisplay{
int h,m,s;
public Analog(){
super();
this.setPreferredSize(new Dimension(200,200));
this.setMaximumSize(new Dimension(200,200));
this.oneSecondMore();
}
public void paint(Graphics g){
int b=15;
g.setColor(new Color(187, 210, 225));
g.fillRect(0,0,this.getWidth(),this.getHeight());
g.setColor(Color.BLACK);
((Graphics2D) g).setStroke(new BasicStroke(4.0f));
g.drawOval(b,b,this.getWidth()-2*b,this.getHeight()-2*b);
int x = this.getWidth()/2, y = this.getHeight()/2, r=(this.getWidth()-2*b)/2;
for(int i=0;i<12;i++){
double a = i*Math.PI*2/12;
g.drawLine((int) (x+0.95*r*Math.sin(a)),(int) (y-0.95*r*Math.cos(a)),(int) (x+1.05*r*Math.sin(a)),(int) (y-1.05*r*Math.cos(a)));
}
double ah = Math.PI*2*(h%12)/12, am = Math.PI*2*m/60, as = Math.PI*2*s/60;
((Graphics2D) g).setStroke(new BasicStroke(5.0f));
g.drawLine(x,y,(int) (x+0.7*r*Math.sin(ah)),(int) (y-0.7*r*Math.cos(ah)));
((Graphics2D) g).setStroke(new BasicStroke(3.0f));
g.setColor(new Color(120,120,120));
g.drawLine(x,y,(int) (x+0.85*r*Math.sin(am)),(int) (y-0.85*r*Math.cos(am)));
((Graphics2D) g).setStroke(new BasicStroke(1.0f));
g.drawLine(x,y,(int) (x+r*Math.sin(as)),(int) (y-r*Math.cos(as)));
}
public void oneSecondMore(){
h=Horloge.getHour();
m=Horloge.getMinute();
s=Horloge.getSecond();
this.repaint();
}
public Component getComponent(){
return this;
} }
On ajoute dans le main de la classe Horloge : h.addHourDisplay(new Digital());
h.addHourDisplay(new Analog());
2.4 La classe Horloge implémente ActionListener, et on remplace la méthode run par lla méthode actionPerformed :
public void actionPerformed(ActionEvent e){
for(HourDisplay hd:this.dis) hd.oneSecondMore();
}
La méthode main devient :
Horloge h = new Horloge();
h.addHourDisplay(new Digital());
h.addHourDisplay(new Analog());
new Timer(1000,h).start();