Tracé de ligne pictureBox

Résolu
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016 - Modifié par sebbur le 31/05/2016 à 08:12
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016 - 8 juin 2016 à 08:36
Bonjour à tous,

J'aurai voulu savoir comment tracer une ligne dans une pictureBox à partir de la souris. J'arrive à tracer ça en écrivant les coordonnées dans le programme, mais je souhaiterai que l'utilisateur puisse tracer sa ligne où il le souhaite.

Merci d'avance,

Sebbur

16 réponses

Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
31 mai 2016 à 11:51
Bonjour

il faut que tu te serves des évènements de la souris dans le picturebox.

Par exemple:
  • un premier click => récupération du point de départ (position de la souris),
  • un deuxième click => récupération du point du point d'arrivée et traçage.


Pour que cela soit plus ergonomique, tu peux aussi, après le premier click, tracer une ligne à chaque déplacement de la souris et effacer la précédente, avec l'évènement mouseover.



1
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
1 juin 2016 à 17:36
Bon

déjà, ça ne sert à rien de convertir de convertir un int en string et d'en refaire un int plus loin.
Autant enregistrer la valeur directe en int.

Pour info, convertir un string en int, il y a 2 options:
int toto = Convert.ToInt32("1");
int tutu = int.Parse("2");


D'autre part, tel que tu as prévu ton truc, pour que ça marche il faut que l'utilisateur maintienne la souris enfoncée le temps de tracer la ligne.
En ce qui me concerne, je ne trouve pas ça pratique, je préfère un click par point, mais c'est toi qui vois.

Voici mon option
       int x1 = -1;
        int y1 = -1;
        int x2 = -1;
        int y2 = -1;

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {

            if (x1 == -1)
            {
                x1 = e.X;
                y1 = e.Y;
            }
            else
            {
                x2 = e.X;
                y2 = e.Y;
            }
        }

public void DrawLineInt(PaintEventArgs e)
        {
            Pen blackPen = new Pen(Color.Red, 3);

    //ici ton code pour déssiner la ligne

    //réinit des valeurs
            x1 = -1;
            y1 = -1;
            x2 = -1;
            y2 = -1;

        }


1
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
5 juin 2016 à 21:42
D'abord, il faut stocker les les lignes précédentes.
Par ligne on a besoin des 4 coordonnées, et éventuellement de la couleur si on veut varier (par exemple rouge celle en cours, et bleu les précédentes).
J'écris donc une classe qui stocke ça. Pour le coup, y'a pas plus simple comme classe:
using System.Drawing;

namespace Test_Winform
{
    class Segment
    {
       public Point Point1 { get; set; }

       public Point Point1 { get; set; }

       public Color Couleur { get; set; }
    }
}



Dans la Form, il faut gérer la collections de segments (une list<t>) et traiter les lignes sauvegardées et celle en cours
       List<Segment> segments = new List<Segment>();
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Pen blackPen;
            //Lignes précendentes
            foreach (Segment s in segments)
            {
                blackPen = new Pen(s.Couleur, 3);
                e.Graphics.DrawLine(blackPen,s.Point1,s.Point2);
            }


            //Gestion de la ligne en cours
            blackPen = new Pen(Color.Red, 3);

            if (x1 != -1)
            {
                e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);


                if (fin2ligne)
                {
                    //enregistre la ligne
                    segments.Add(new Segment(x1, y1, x2, y2, Color.Blue));

                    //réinit des valeurs
                    x1 = -1;
                    y1 = -1;
                    x2 = -1;
                    y2 = -1;
                }
            }
        }


1
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
31 mai 2016 à 11:57
Je te remercie de ta réponse et de ton aide !

Je vais, dans un premier temps, essayer un tracé simple et une fois réussi, je ferai tout ça de manière plus ergonomique avec les indications que tu m'as fournies.

Merci encore une fois,

Sebbur
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
31 mai 2016 à 13:47
En revanche je rencontre un problème quand je veux assigner la position de départ à ma variable.

J'ai créé une méthode pour dessiner la ligne. Les valeurs des variables de coordonnées je les récupère dans les évènements MouseDown et MouseUp. Du coup il est impossible de convertir le string de la variable de mon évènement en int de ma variable de la méthode.

Si je n'ai pas été suffisamment clair, n'hésitez pas à me demander des précisions.

Merci d'avance,

Sebbur
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
31 mai 2016 à 18:16
Peux tu poster le code que tu as utilisé, en utilisant cette procédure
http://codes-sources.commentcamarche.net/faq/10686-le-nouveau-codes-sources-comment-ca-marche#balises-code
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
1 juin 2016 à 08:48
Bien sûr, le voici :

public void DrawLineInt(PaintEventArgs e)
        {
            Pen blackPen = new Pen(Color.Red, 3);

            int x1 = a1;
            int y1 = a2;
            int x2 = b1;
            int y2 = b2;

        }

        string a1, a2, b1, b2;
        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            // Récupération de la position de départ
            a1 = e.X.ToString();
            a2 = e.Y.ToString();

        }

        private void pictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            // Récupération de la position d'arrivée
            b1 = e.X.ToString();
            b2 = e.Y.ToString();
        }


Mon code est faux, j'en suis conscient, mais je ne vois pas bien comment faire autrement.

Merci de ton aide,

Sebbur
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
2 juin 2016 à 08:57
Je te remercie pour ta réponse.

J'ai bien compris ton code et il doit convenir à ma problématique, mais quand je l'ai testé rien ne se passe, c'est-à-dire que quand j'essaie de tracer une ligne avec la souris elle ne se trace pas.

Merci de ton aide,

Sebbur
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
2 juin 2016 à 14:53
Peux tu montrer le code pour dessiner?
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
2 juin 2016 à 14:59
Voici ma ligne de code pour le dessin de la ligne :

e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
2 juin 2016 à 18:53
La méthode que tu utilises ne peut marcher qu'abonnée à l'événement Paint du contrôle.
Sinon le "e", on y a pas accès.
Si on veut abonner ta méthode à l'évènement Paint, ça ne veut pas car, la signature n'est pas bonne.
Le plus simple dans la fenêtre des évènements, tu doubles click sur Paint, ça va te créer une méthode qui va bien et l'abonnée.

Encore faut il que cet événement soit déclenché, pour ça il faut forcer un Refresh au moment opportun.

        int x1 = -1;
        int y1 = -1;
        int x2 = -1;
        int y2 = -1;

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {


            if (x1 == -1)
            {
                x1 = e.X;
                y1 = e.Y;
            }
            else
            {
                x2 = e.X;
                y2 = e.Y;

                pictureBox1.Refresh();
            }
        }

 
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Pen blackPen = new Pen(Color.Red, 3);

            e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);

            //réinit des valeurs
            x1 = -1;
            y1 = -1;
            x2 = -1;
            y2 = -1;
        }


Et avec la ligne qui suit la souris entre deux clicks
        int x1 = -1;
        int y1 = -1;
        int x2 = -1;
        int y2 = -1;
        bool fin2ligne = false;
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (x1 == -1)
            {
                x1 = e.X;
                y1 = e.Y;
            }
            else
            {
                x2 = e.X;
                y2 = e.Y;
                fin2ligne = true;
                pictureBox1.Refresh();
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {

            if (x1 == -1) return;
            x2 = e.X;
            y2 = e.Y;
            fin2ligne = false;
          
            pictureBox1.Refresh();

        }


        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {

            Pen blackPen = new Pen(Color.Red, 3);

            if (x1 != -1)
            {
                e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);


                if (fin2ligne)
                {
                    //réinit des valeurs
                    x1 = -1;
                    y1 = -1;
                    x2 = -1;
                    y2 = -1;
                }
            }
        }
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
3 juin 2016 à 08:50
Je te remercie pour ton aide et tes indications, le code marche très bien !

Il y a juste une chose que je n'ai pas bien compris. Pourquoi initialiser les valeurs à -1 et non pas à 0 ?
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié par vb95 le 3/06/2016 à 12:18
Bonjour
Le point 0,0,existe : c'est celui qui est tout en haut à gauche de ta Form
Le point -1,-1 est en dehors de ta Form donc impossible d'avoir cette valeur au clic de la souris !
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656 > vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024
Modifié par Whismeril le 3/06/2016 à 13:58
Tout à fait.
Cela évite de se trimbaler un boolean supplémentaire pour savoir si une ligne est commencée ou pas.

Comme tu n'as pas précisé si tu veux tracer plusieurs lignes, je ne l'ai pas prévu.
En l'état, toute nouvelle ligne efface la précédente.
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
5 juin 2016 à 13:22
Je vous remercie pour vos indications, je comprends mieux les coordonnées -1;-1 maintenant.

Oui c'est vrai que je ne l'ai pas précisé. C'est très bien comme ça pour le moment. Mais si jamais je souhaiterais que la ligne précédente ne soit pas effacée, comment je peux faire ?

Merci encore.

Sebbur
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
5 juin 2016 à 15:45
Il faudra stocker les coordonnées des lignes précédentes, et les redessiner à chaque fois. Je te ferai un exemple plus tard.
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
5 juin 2016 à 15:52
D'accord pas de soucis, merci beaucoup !
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
6 juin 2016 à 11:42
Merci d'avoir prit le temps de m'illustrer ça à travers un exemple. Je vais essayer ça tout de suite !

Encore merci,

Sebbur
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
6 juin 2016 à 13:09
Voici mon code que j'ai testé.

public Form1()
        {
            InitializeComponent();
        }
        int x1 = -1;
        int y1 = -1;
        int x2 = -1;
        int y2 = -1;
        bool fin2ligne = false;

        class Segment
        {
            public Point Point1 { get; set; }
            public Point Point2 { get; set; }
            public Color Couleur { get; set; }
        }
        List<Segment> segments = new List<Segment>();

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Pen blackPen;
            //Lignes précédentes
            foreach (Segment s in segments)
            {
                blackPen = new Pen(s.Couleur, 3);
                e.Graphics.DrawLine(blackPen, s.Point1, s.Point2);
            }

            //Gestion de la ligne en cours
            blackPen = new Pen(Color.Red, 3);

            if (x1 != -1)
            {
                e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);

                if (fin2ligne)
                {
                    //enregistre la ligne
                    segments.Add(new Segment(x1, y1, x2, y2, Color.Blue));

                    //réinitialisation des valeurs
                    x1 = -1;
                    y1 = -1;
                    x2 = -1;
                    y2 = -1;
                }
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (x1 == -1) return;
            x2 = e.X;
            y2 = e.Y;
            fin2ligne = false;

            pictureBox1.Refresh();
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (x1 == -1)
            {
                x1 = e.X;
                y1 = e.Y;
            }
            else
            {
                x2 = e.X;
                y2 = e.Y;
                fin2ligne = true;
                pictureBox1.Refresh();
            }
        }


J'ai une erreur au moment où j'enregistre la ligne.
L'erreur : 'Form1.Segment' ne contient pas de constructeur qui accepte des arguments 5
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
6 juin 2016 à 16:18
Ha oui, une erreur de copier coller de m part.
Je te corrige ça dans la soirée.
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016 > Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024
6 juin 2016 à 16:23
D'accord pas de soucis, merci et à plus tard.

Sebbur
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
6 juin 2016 à 17:34
using System.Drawing;

namespace Test_Winform
{
    class Segment
    {
        public Segment(int X1, int Y1, int X2, int Y2, Color Couleur)
        {
            Point1 = new Point(X1, Y1);
            Point2 = new Point(X2, Y2);
            this.Couleur = Couleur;
        }

       public Point Point1 { get; set; }

       public Point Point2 { get; set; }

       public Color Couleur { get; set; }
    }
}
0
sebbur Messages postés 39 Date d'inscription lundi 9 mai 2016 Statut Membre Dernière intervention 27 juillet 2016
7 juin 2016 à 17:16
Merci beaucoup, ça fonctionne très bien !

Merci d'avoir prit le temps de m'aider, c'est sympa ! ;)

Sebbur
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
7 juin 2016 à 18:13
De rien, tu,peux marquer le sujet résolu, si cela te convient.
0
Rejoignez-nous