Tracé de ligne pictureBox [Résolu]

Signaler
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016
-
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016
-
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

Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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.



Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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;

        }


Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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;
                }
            }
        }


Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
Peux tu montrer le code pour dessiner?
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

Voici ma ligne de code pour le dessin de la ligne :

e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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;
                }
            }
        }
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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 ?
Messages postés
2429
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
1 juin 2021
137
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 !
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551 >
Messages postés
2429
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
1 juin 2021

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.
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
Il faudra stocker les coordonnées des lignes précédentes, et les redessiner à chaque fois. Je te ferai un exemple plus tard.
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

D'accord pas de soucis, merci beaucoup !
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

Merci d'avoir prit le temps de m'illustrer ça à travers un exemple. Je vais essayer ça tout de suite !

Encore merci,

Sebbur
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

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
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016
>
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021

D'accord pas de soucis, merci et à plus tard.

Sebbur
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
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; }
    }
}
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016

Merci beaucoup, ça fonctionne très bien !

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

Sebbur
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021
551
De rien, tu,peux marquer le sujet résolu, si cela te convient.
Messages postés
39
Date d'inscription
lundi 9 mai 2016
Statut
Membre
Dernière intervention
27 juillet 2016
>
Messages postés
16032
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
13 juin 2021

Voilà qui est fait.
Encore merci pour ton aide.

Sebbur