IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[Swing]Comment dessiner ce composant complexe?


Sujet :

AWT/Swing Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut [Swing]Comment dessiner ce composant complexe?
    salut,

    serait il possible avec swing de dessiner ce composant qui servira comme indicateur pour des données aéronautiques ... quelqu'un peut il me donner un coup de main svp ?

    merci
    Images attachées Images attachées  

  2. #2
    Membre expérimenté Avatar de Sebou77
    Inscrit en
    Mars 2006
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2006
    Messages : 212
    Par défaut
    Le mieux ça serait pas de faire une image du cadran, plusieur images de fleches suivant plusieur position, et les déplacer en fonction de tes données ?
    Parce que dessiner ça en swing ça va être violent

  3. #3
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Déja tu vas commencer par modéliser ton composant au niveau code, c'est à dire un model contenant les diverses informations de base, cad les diverses valeurs qui seront affichée (et donc les setters qui vont bien).

    La deuxième chose à faire est de décomposer les divers éléments dont tu auras besoin.

    Donc grosso merdo:
    • Une courbe et se graduations. => drawCurve et drawLine (utilisatiion de (co)sinus pour calculer l'inclinaison en fonction de ta courbe) sur les Graphics de ton composants
    • Une flèche (probablement une image que sur laquelle tu devras effectuer une rotation) récupération des graphics de ton image, rotation en fonction de la valeur puis drawImage sur ton composant
    • Les cadran de gauche et du bas sont composés de deux éléments: un rectangle et une String (drawRectangle et drawString sur les graphics de ton composant)
    • Pas mal d'huile de coude.
    Pour simplifier la chose au départ je te recommande de faire une graduation simple, c'est à dire droite au lieu de courbe

    Pour aérer ton code essaye de découper les différents dessins en plusieurs méthodes du genre

    & cie

    Bonne chance et bienvenu dans le monde de java2D

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut
    merci sinok mais je t'avoue que c'est encore du chinosi pour moi ..pourrais tu illustrer ce que tu as dit par un petit code qui pourra me servir de base ...je t'avoue que c'est un peu bloquant pour moi
    et encore merci

  5. #5
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    On va dire que faire un code de base ne serait pas forcément très rapide, puis là je suis au taf, donc pas forcément le bon endroit pour le faire... Ce soir peut être

    En attendant commences par te former de base sur le dessin en java: http://duj.developpez.com/tutoriels/java/dessin/intro/

    Et à lire les tutos java2D de Sun:
    http://java.sun.com/docs/books/tutorial/2d/TOC.html

    Ainsi que la javadoc des classes Graphics et Graphics2D

  6. #6
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Bon pour te donner une première idée de la modélisation (pas trop envie de me plonger la tête dans les maths ce soir, en ce moment en général)

    Voilà ce que ça donne

    Le modèle:

    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
     
     
    import javax.swing.event.EventListenerList;
     
     
    public class GraduationModel {
     
        private EventListenerList listeners;
     
        private int value;
     
     
     
        public GraduationModel() {
            super();
            this.listeners = new EventListenerList();
        }
     
        public int getValue() {
            return value;
        }
     
        public void setValue(int value) {
            int oldValue = this.value;
            this.value = value;
            fireValueChanged(oldValue,value);
        }
     
     
        protected void fireValueChanged(int oldValue, int newValue) {
            GraduationEvent event = null;
     
            for(GraduationListener listener : getValueListeners()) {
                if(event == null)
                    event = new GraduationEvent(oldValue, newValue);
                listener.valueChanged(event);
            }
     
        }
     
        public GraduationListener[] getValueListeners() {
            // TODO Auto-generated method stub
            return listeners.getListeners(GraduationListener.class);
        }
     
        public void addGraduateListener(GraduationListener l) {
            listeners.add(GraduationListener.class, l);
        }
     
    }
    Le listener et l'event associé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    import java.util.EventListener;
     
     
    public interface GraduationListener extends EventListener{
     
        public void valueChanged(GraduationEvent e);
    }
    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
     
     
     
    /**
     * @author sinok
     *
     */
    public class GraduationEvent {
        private int oldValue;
        private int newValue;
     
        /**
         * @param oldValue
         * @param newValue
         */
        GraduationEvent(int oldValue, int newValue) {
            this.oldValue = oldValue;
            this.newValue = newValue;
        }
     
        /**
         * @return
         */
        public int getOldValue() {
            return oldValue;
        }
     
        /**
         * @return
         */
        public int getNewValue() {
            return newValue;
        }
    }
    Le composant faisant le dessin

    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
     
     
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.geom.Line2D;
    import java.awt.geom.Rectangle2D;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
     
    import javax.imageio.ImageIO;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.Timer;
     
     
    public class GraduationComponent extends JComponent implements GraduationListener, ActionListener{
        private GraduationModel model;
        private int oldValue;
        private int newValue;
        private int direction;
        private Timer timer;
        private BufferedImage thumb;
     
        public GraduationModel getModel() {
            return model;
        }
     
        public void setModel(GraduationModel model) {
            this.model = model;
        }
     
        public GraduationComponent(GraduationModel model) {
            super();
            this.model = model;
            this.timer = new Timer(50,this);
            model.addGraduateListener(this);
            try {
                thumb = ImageIO.read(getClass().getResourceAsStream("arrow.png"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
     
        }
     
        @Override
        protected void paintComponent(Graphics g) {
            // TODO Auto-generated method stub
            //super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            if( this.isShowing()) {
                drawBackground(g2d);
                drawGraduate(g2d);
            }
        }
     
        public void valueChanged(GraduationEvent e) {
            // TODO Auto-generated method stub
            this.oldValue = e.getOldValue();
            this.newValue = e.getNewValue();
            if(oldValue > newValue) {
                direction = -1;
            } else if(oldValue < newValue) {
                direction = 1;
            } else {
                direction = 0;
            }
            timer.start();
        }
     
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            oldValue += direction;
            repaint();
            if(oldValue == newValue) {
                timer.stop();
            }
        }
     
        protected void drawGraduate(Graphics2D g2d) {
            g2d.setPaint(Color.white);
            g2d.drawString(String.valueOf(model.getValue()), 10, 20);
            g2d.drawString(String.valueOf(this.oldValue), 10, 40);
     
            g2d.draw(new Line2D.Double(150,190,150,10));
            for(int i = 10; i<191; i+=10) {
                if(i%20 == 10) {
                    g2d.draw(new Line2D.Double(140,i,150,i));
                } else {
                    g2d.draw(new Line2D.Double(145,i,150,i));
                }
     
            }
     
            g2d.drawImage(thumb,140-thumb.getWidth()-10,190-(thumb.getHeight()/2)-oldValue,thumb.getWidth(), thumb.getHeight(),null);
        }
     
        protected void drawBackground(Graphics2D g2d) {
            g2d.setPaint(Color.black);
            g2d.fill(new Rectangle2D.Double(0,0,getWidth()-1,getHeight()-1));
        }
     
     
        public static void main(String[] args) {
            final GraduationModel m = new GraduationModel();
            m.setValue(0);
            GraduationComponent c = new GraduationComponent(m);
            JFrame f = new JFrame();
            f.add(c);
            f.setSize(200,200);
            f.setLocationRelativeTo(null);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setVisible(true);
            Timer t = new Timer(5000,new ActionListener() {
     
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    m.setValue(m.getValue()+10);
                }
     
            });
            t.start();
     
     
        }
     
     
    }
    En ce qui concerne le dessin sur le composant c'est du vite fait mal fait (c'est moche, c'est une graduation droite & cie...

    Mais le'essentiel pour toi est déja de comprendre les bases de la création d'un composant. A toi de faire le reste (calculs sur les rotations, courbes et les dessiner)

    Vais pas te macher entièrement le taf non plus

    Si tu as des questions... (désolé je n'ais pas franchement eu le temps de commenter mon code...)

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    Les methodes indiquees precedement sont bonnes mais il n'est pas vraiment necessaire que la fleche soit une image (surtout si elle est si simple) ; une simple Shape (un GeneralPath ou un Polygon) fera tout aussi bien l'affaire. Apres c'est la meme methode : utiliser une transformation affine pour la dessiner avec le bon angle.

    Principe de base en 2D : en general, ne pas se prendre la tete en caculs complexe. Si tu sais tout dessiner a l'horizontal (resp a la verticale) autour de (0, 0) alors tu peux tout dessiner sous n'importe quel angle et a n'importe quel emplacement avec des transformations affines (et leur transformations inverses) de rotation et de translation (resp pour des transformation affines autre que des rotations).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut
    Merci a vous deux c'est tres gentil :

    cependant si j'ai bien compri sinok dans ton code tu as un timer qui te gere le deplacement de al fleche selon la valeur générée...cependant j'ai une petite question pourquoi quand j'oblige le timer a s'arrêter quand j'atteint une valeur X ( valeur max par exemple ) il continue a generer les valeurs et la fleche continue a remonter ?
    merci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
     
    public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            oldValue += direction;
            repaint();
            if((oldValue == newValue) || (maxValue == newValue )) // ou maxvalue est une valeur private initilaisée a 200 par exemple 
            timer.stop();
     
        }

  9. #9
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    L'action performed du composant ne gère que l'animation de la flèche (c'est à dire qu'il va depuis l'ancienne valeur du model vers la nouvelle...)

    C'est dans le main que je change les valeurs du model (c'est pas propre mais j'avais juste besoin de tester ^^...)

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut
    c'est bon il fallait juste agir a ce niveau:

    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
     
    public void valueChanged(GraduationEvent e) {
            // TODO Auto-generated method stub
            this.oldValue = e.getOldValue();
            this.newValue = e.getNewValue();
            if(oldValue > newValue) {
                direction = -1;
            } else if(oldValue < newValue) {
                direction = 1;
            } else {
                direction = 0;
            }
          if(maxValue < newValue ) // ici 
                timer.stop();
            else
            timer.start();
        }
    cependant bouye peut me dire si les transformation sont le seul moyen pour faire deplacer une shape ou image comme mon cas précis?
    merci

  11. #11
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    Non tu peux aussi faire des calculs a la main pour chacune des positions, mais ca devient vite bien prise de tete plus encore quand on a plein de points et de transformations a effectuer.

    C'est plus simple soit en manipulant directement le graphics (les methodes g.rotate(), etc... sont traduites en terme de transformation affine) soit en utilisant AffineTransform a nouveau soit directement sur le graphics (g.setTransform()), soit sur les formes de maniere a produire des formes intermediaires transformees (t.createTransformedShape()).
    Personelement je prefere les appliquer sur le graphics.

    Apres l'important c'est toujours de se souvenir quelle est (où est) l'origine actuelle du repere et quelle est la derniere transformation effectuee.

    Tu verras a l'usage que les indices de rendu du graphics ont des effets sur le rendu final nottament :
    RenderingHints.KEY_RENDERING - rendu general
    RenderingHints.KEY_INTERPOLATION - interpolation des couleurs (solides) des images transformees (preferrer RenderingHints.VALUE_INTERPOLATION_BILINEAR a RenderingHints.VALUE_INTERPOLATION_BICUBIC car elle est plus rapide et la 2nde, bien que de meilleur qualite en theorie, n'offre pas de resultats visibles flagrants).
    RenderingHints.KEY_ANTIALIASING - aliasing des formes
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut
    ok merci
    dans ce cas que suggere tu pour afficher une shape comme la fleche dont tu as parlé ...je veux dire pourquoi la fonction rotate par exemple doit être invoquée avant de dessiner un composant? tout ce que je veux c'est faire pivoter une flehe par rapport au centre d l'ecran ...comme l'aiguille d'une montre quoi mais je n'y arrive pas

  13. #13
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    La premiere etape consiste a se creer une Shape de fleche qui peut etre reutilisee ailleurs. On centrera la queue de la fleche sur O (0, 0).
    Cela peut se faire avec un Polygon ou un GeneralPath :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    GeneralPath path = new GeneralPath();
    path.moveTo(i1.x, i1.y);
    path.lineTo(i2.x, i2.y);
    path.lineTo(i3.x, i3.y);
    ...
    path.curveTo(i8.x, i8.y, i9.x, i9.y, i1.x, i1.y);
    path.close();
    Shape arrow = path;
    Pour connaitre les coordonnees des points a reutiliser, pas de probleme :
    - dessiner une fleche dans un logiciel de dessin bitmap et relever les coordonnees des pixels des sommets.
    - dessiner une fleche dans un logiciel de dessin vectoriel et relever les coordonnes des sommets et points de controle.
    - encore plus simple : dessiner une fleche sur du papier quadrille, ex : un calepin.

    Ensuite, nous desirons avoir ceci :


    En partant de ceci. Le cadre denote la surface d'affichage (du JPanel par exemple) dont l'origine est dans le coin superieur gauche.


    Tout d'abord nous faisons une translation du repere jusqu'au point ou devra se positionner notre queue de fleche. Note comme la zone d'affichage a ete transformee (cadre violet - c'est pour ca qu'il faut toujours penser a annuler ses transformation).


    Ensuite nous effectuons notre rotation suivant le bon angle.


    Nous dessinons ensuite notre jolie fleche horizontale toute simple. Mais il nous faut revenir au repere d'origine, en effet si jamais nous arretons le dessin ici, nous verrons juste une demi fleche horizontale affichee a l'ecran.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    g.setColor(Color.BLACK);
    g.fill(arrow);


    Nous effectuons la rotation inverse. Miracle notre fleche est correctement orientee. Attention cependant l'origine du repere n'est pas correctement positionnee. Si jamais nous arretons le dessin ici seul le bout de la queue de la fleche apparaitra a l'ecran.


    Nous effectuons donc la translation inverse pour repositionner correctement l'origine. Et voila !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g.translate(-c.x, -c.y);




    Ainsi donc si tu n'annules pas tes transformations, tu peux tout simplement avoir une fleche dessinee avec le bon angle mais qui se trouve en fait completement en dehors de ton espace d'affichage.

    Attention egalement lorsque tu travailles avec des doubles ou des floats tu peux avoir des erreurs d'arrondis ce qui fait que en fait en annulant plusieurs rotations successives, etc... tu peux ne pas tout a fait revenir a l'horizontal. Une methode consiste donc a sauvegarder la transformation du graphics par exemple au lieu de :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    g.rotate(theta);
    ...
    g.rotate(-theta);
    Faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    AffineTransform oldT = g.getTransform();
    g.rotate(theta);
    ...
    g.setTransform(oldT);
    Autre chose a se rappeler : l'orientation de l'axe des Y est inverse de celle qu'on voit a l'ecole ; ca veut dire egalement que le cercle trigonometrique est donc dans le sens des aiguilles d'une montre (a l'opposee donc de ce qu'on voit a l'ecole egalement).

    Ensuite, si tu veux travaille avec une bitmap pour dessiner ta fleche... ca marche pareil !
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  14. #14
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    oh violence, ça va le taf chez les Kanaks ^^

  15. #15
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    ?? Pour ce qui m'ennuie en ce moment au boulot, voir http://www.developpez.net/forums/sho...42&postcount=1

    Un petit exemple tres vite fait justement, plus besoin de se casser la tete pour dessiner des formes complexes.

    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
    package test;
     
    import java.awt.*;
    import java.awt.geom.*;
    import java.awt.event.*;
    import java.awt.font.*;
    import java.awt.image.*;
    import javax.swing.*;
    import java.util.*;
     
    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2006</p>
     *
     * <p>Company: </p>
     *
     * @author not attributable
     * @version 1.0
     */
    class Clock extends JPanel implements ActionListener {
      Ellipse2D.Double circle = new Ellipse2D.Double();
      Line2D.Double line = new Line2D.Double();
      Shape arrow = null;
      Calendar calendar = GregorianCalendar.getInstance();
      javax.swing.Timer timer;
     
      public Clock() {
        super();
        // Create initial arrow shape.
        GeneralPath path = new GeneralPath();
        path.setWindingRule(GeneralPath.WIND_EVEN_ODD);
        path.moveTo(54.81f, 286.50f);
        path.curveTo(63f, 243f, 49.54f, 213.88f, 49.54f, 213.88f);
        path.curveTo(33, 198, 38.14f, 233.32f, 38.14f, 233.32f);
        path.curveTo(23, 204, 26, 150, 26.51f, 136.40f);
        path.curveTo(28, 59, 65.64f, 12.59f, 65.64f, 12.59f);
        path.curveTo(12, 125, 70.40f, 207.45f, 70.40f, 207.45f);
        path.curveTo(59, 199, 63.63f, 219.48f, 63.63f, 219.48f);
        path.curveTo(70, 257, 54.81f, 286.50f, 54.81f, 286.50f);
        path.closePath();
        path.moveTo(38.85f, 192.72f);
        path.curveTo(38.85f, 192.72f, 35, 162, 37.64f, 155.94f);
        path.curveTo(37.64f, 155.94f, 44, 183, 51.76f, 196.26f);
        path.curveTo(51.76f, 196.26f, 44, 190, 38.85f, 192.72f);
        path.closePath();
        path.moveTo(72.67f, 268.82f);
        path.curveTo(85, 218, 74, 203, 63.75f, 177.85f);
        path.curveTo(38, 118, 51.90f, 81.73f, 51.90f, 81.73f);
        path.curveTo(43, 123, 68, 156, 73.17f, 165.67f);
        path.curveTo(100, 225, 72.67f, 268.82f, 72.67f, 268.82f);
        path.closePath();
        // The arrow tail was not centered around (0, 0), now it is.
        AffineTransform t = AffineTransform.getTranslateInstance( -55, -182);
        arrow = t.createTransformedShape(path);
      }
     
      /**
       * {@inheritDoc}
       */
      public void actionPerformed(ActionEvent event) {
        repaint();
      }
     
      /**
       * {@inheritDoc}
       */
      @Override protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Insets insets = getInsets();
        Dimension size = getSize();
        int width = size.width - (insets.left + insets.right);
        int height = size.height - (insets.top + insets.bottom);
        Graphics2D g2d = (Graphics2D) g.create(insets.left, insets.top, width, height);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setColor(getBackground());
        g2d.fillRect(0, 0, width, height);
        int diameter = Math.min(width, height) - 50;
        if (diameter > 0) {
          long date = System.currentTimeMillis();
          calendar.setTimeInMillis(date);
          int hours = calendar.get(Calendar.HOUR_OF_DAY);
          int minutes = calendar.get(Calendar.MINUTE);
          int seconds = calendar.get(Calendar.SECOND);
          g2d.setColor(getForeground());
          g2d.drawString(hours + ":" + minutes + ":" + seconds, 100, 100);
          double cX = width / 2.0;
          double cY = height / 2.0;
          double radius = diameter / 2.0;
          g2d.translate(cX, cY);
          circle.setFrameFromCenter(0, 0, radius, radius);
          g2d.setPaint(Color.WHITE);
          g2d.fill(circle);
          g2d.setPaint(getForeground());
          g2d.draw(circle);
          circle.setFrameFromCenter(radius / 2.0, radius / 2.0, 3 * radius / 4.0, 3 * radius / 4.0);
          g2d.setPaint(Color.WHITE);
          g2d.fill(circle);
          g2d.setPaint(getForeground());
          g2d.draw(circle);
          circle.setFrameFromCenter( -radius / 2.0, radius / 2.0, -3 * radius / 4.0, 3 * radius / 4.0);
          g2d.setPaint(Color.WHITE);
          g2d.fill(circle);
          g2d.setPaint(getForeground());
          g2d.draw(circle);
          circle.setFrameFromCenter(0, -radius / 2.0, radius / 4.0, -radius / 4.0);
          g2d.setPaint(Color.WHITE);
          g2d.fill(circle);
          g2d.setPaint(getForeground());
          g2d.draw(circle);
          drawLabelOnTop(g2d, "Chronometer", radius / 2.0, radius / 4.0 - 5);
          drawLabelOnTop(g2d, "Altitude", -radius / 2.0, radius / 4.0 - 5);
          drawLabelOnTop(g2d, "Presure", 0, -3 * radius / 4.0 - 5);
          double theta = 2 * Math.PI / 12;
          Font font = g2d.getFont();
          for (int i = 1; i <= 12; i++) {
            g2d.rotate(theta);
            line.setLine(0, -radius, 0, -radius - 5);
            String label = String.valueOf(i);
            drawLabelOnTop(g2d, label, 0, -radius - 10);
            g2d.draw(line);
          }
          Rectangle2D arrowBounds = arrow.getBounds2D();
          double arrowLength = -arrowBounds.getY();
          double scale = (0.80 * radius) / arrowLength;
          double hourAngle = (hours % 12) * 2 * Math.PI / 12;
          double minutesAngle = minutes * 2 * Math.PI / 60;
          double secondsAngle = seconds * 2 * Math.PI / 60;
          AffineTransform oldT = g2d.getTransform();
          g2d.rotate(minutesAngle);
          // Scale+shrink+mirror on X axis & scale on Y axis.
          g2d.scale( -0.5 * scale, scale);
          g2d.setPaint(getForeground().brighter().brighter().brighter().brighter());
          g2d.fill(arrow);
          drawLabelOnTop(g2d, "Minutes", 0, -arrowLength);
          //g2d.draw(arrowBounds);
          g2d.setTransform(oldT);
          g2d.rotate(hourAngle);
          // Scale on both axis.
          g2d.scale(0.66 * scale, 0.66 * scale);
          g2d.setPaint(getForeground());
          g2d.fill(arrow);
          drawLabelOnTop(g2d, "Hours", 0, -arrowLength);
          //g2d.draw(arrowBounds);
          g2d.setTransform(oldT);
          g2d.rotate(secondsAngle);
          g2d.setPaint(getForeground().brighter().brighter());
          // One simple vertical straight line.
          line.setLine(0, 0, 0, -0.95 * radius);
          g2d.draw(line);
          drawLabelOnTop(g2d, "Seconds", 0, -0.95 * radius);
          g2d.setTransform(oldT);
          // Chronometer.
          g2d.translate(radius / 2.0, radius / 2.0);
          g2d.rotate(2 * Math.PI / 3.0);
          line.setLine(0, 0, 0, 0.95 * radius / 4.0);
          g2d.setPaint(getForeground());
          g2d.draw(line);
          g2d.setTransform(oldT);
          // Altitude
          g2d.translate( -radius / 2.0, radius / 2.0);
          g2d.rotate(2 * Math.PI / 6.0);
          line.setLine(0, 0, 0, 0.95 * radius / 4.0);
          g2d.setPaint(getForeground());
          g2d.draw(line);
          g2d.setTransform(oldT);
          //Presure.
          g2d.translate(0, -radius / 2.0);
          g2d.rotate(2 * Math.PI / 4.0);
          line.setLine(0, 0, 0, 0.95 * radius / 4.0);
          g2d.setPaint(getForeground());
          g2d.draw(line);
          g2d.setTransform(oldT);
        }
        // Cancel all pending transforms.
        g2d.dispose();
      }
     
      protected void drawLabelOnTop(Graphics2D g2d, String label, double x, double y) {
        Font font = g2d.getFont();
        Rectangle2D labelBound = font.getStringBounds(label, g2d.getFontRenderContext());
        LineMetrics lineMetrics = font.getLineMetrics(label, g2d.getFontRenderContext());
        g2d.drawString(label, (float) (x - labelBound.getWidth() / 2.0), (float) (y - lineMetrics.getDescent()));
     
      }
     
      /** Start (or restart) timer.
       */
      public synchronized void start() {
        if (timer == null) {
          timer = new javax.swing.Timer(1000, this);
          timer.start();
        }
        else {
          timer.restart();
        }
      }
     
      /** Stop timer.
       */
      public synchronized void stop() {
        timer.stop();
      }
     
      /**
       * @param args Arguments from the command-line.
       */
      public static void main(String ...args) {
        // Start at EDT.
        SwingUtilities.invokeLater(new Runnable() {
          /**
           * {@inheritDoc}
           */
          public void run() {
            Clock clock = new Clock();
            clock.start();
            JFrame frame = new JFrame("Clock");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            frame.add(clock, BorderLayout.CENTER);
            frame.pack();
            frame.setVisible(true);
          }
        });
      }
    }
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 418
    Par défaut
    Salut,

    pas mal
    mais si l'on souhaite faire fonctionner tes indicateurs ( altitude, pressure...) on fait comment?...des threads ou un seul? je suis vraiement interessé!

    merci

  17. #17
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    Rien de plus special que le fait d'avoir une propriete/une variable equivalente pour chacune des valeurs. Sinon un Timer Swing si jamais il faut faire des annimations avec des fleches qui bougent de maniere "realiste". Apres divers frameworks sont en devellopement pour faire des animations de maniere plus avancee mais je ne suis pas trop la chose.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  18. #18
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Chouette

  19. #19
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 905
    Billets dans le blog
    54
    Par défaut
    Rien de plus en théorie/facon de parler :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // Altitude
          g2d.translate( -radius / 2.0, radius / 2.0);
          g2d.rotate(2 * Math.PI / 6.0);
          line.setLine(0, 0, 0, 0.95 * radius / 4.0);
          g2d.setPaint(getForeground());
          g2d.draw(line);
          g2d.setTransform(oldT);
    Il faut quand même modifier ca pour caculer le bon angle en fonction de l'altitude. Bon ce n'est pas vraiment la partie la plus compliquée à faire. Et mettre les getter/setter sur la propriété/membre créée.

    Après un "vrai" altimètre devrai disposer d'une graduation sur le cadran (voir comment faire celle de l'horloge) et éventuellement un indice de multiplication via un compteur sous les aiguilles ou d'un petite aiguille indiquant la multiplication (si on fait plusieurs tours du cadran).

    De même pour la pression alors que le chronomère aura tendance à avoir une autre aiguille mais pour les heures. Bref il y a des tas de manière de décorer/améliorer l'ensemble y compris en utilisant des bitmap ou des Painter pour obtenir un rendu plus réaliste.

    L'important de cet exemple c'était surtout pour montrer que les transformations affines sont vos amies et peuvent vous simplifier la vie (même si parfois ca semble être de l'artillerie lourde). Comme je disais au début : si vous savez dessiner une forme (complexe ou pas, peu importe) à l'horizontale/verticale, vous pouvez dessiner sous n'importe quel angle/transformation affine sans avoir besoin de calculer chaque point de cette forme vous-meme (cf les fèches de la montre).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

Discussions similaires

  1. Comment sauvegarder mes composants swing/awt en base ?
    Par ujin57 dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 05/05/2013, 20h36
  2. [Swing][Graphics2D] dessiner une flèche
    Par Galima dans le forum 2D
    Réponses: 13
    Dernier message: 03/12/2011, 23h31
  3. Réponses: 5
    Dernier message: 11/09/2007, 11h32
  4. Réponses: 4
    Dernier message: 20/06/2007, 12h15
  5. Comment cloner un composant
    Par totoranky dans le forum Composants
    Réponses: 2
    Dernier message: 12/04/2003, 15h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo