Come disegnare la linea e selezionarla in Pannello

Il mio programma può disegnare linee usando canvas.Drawline (). Come fare clic sulla linea e cambiare questo colore (selezionare la linea)?

private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas=panel1.CreateGraphics(); } 

Linea di coordinate memorizzata in coordFirs & coodLast.

Ecco una class Line appropriata:

 class Line { public Color LineColor { get; set; } public float Linewidth { get; set; } public bool Selected { get; set; } public Point Start { get; set; } public Point End { get; set; } public Line(Color c, float w, Point s, Point e) { LineColor = c; Linewidth = w; Start = s; End = e; } public void Draw(Graphics G) { using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); } public bool HitTest(Point Pt) { // test if we fall outside of the bounding box: if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) || (Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y)) return false; // now we calculate the distance: float dy = End.Y - Start.Y; float dx = End.X - Start.X; float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y; float N = dy * dy + dx * dx; float dist = (float)( Math.Abs(Z) / Math.Sqrt(N)); // done: return dist < Linewidth / 2f; } } 

Definisci un elenco per le linee, probabilmente a livello di class:

  List lines = new List(); 

Ecco come puoi inizializzarlo con poche righe:

 for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f, new Point(R.Next(panel1.Width), R.Next(panel1.Height)), new Point(R.Next(panel1.Width), R.Next(panel1.Height)))); 

Ecco il risultato del clic su una traversata:

inserisci la descrizione dell'immagine qui

Ogni volta che aggiungi, modifichi o rimuovi una linea devi far sì che il Panel rifletta le notizie triggersndo l'evento Paint :

 panel1.Invalidate(); 

Ecco l'evento Paint del Panel :

 private void panel1_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; foreach (Line L in lines) L.Draw(e.Graphics); } 

Nell'evento MouseClick fai il test:

 private void panel1_MouseClick(object sender, MouseEventArgs e) { foreach(Line L in lines) L.LineColor = L.HitTest(e.Location) ? Color.Red : Color.Black; panel1.Invalidate(); } 

Per evitare lo sfarfallio, non utilizzare la class di base di Panel quanto non è a doublebuffered . Utilizzare invece una sottoclass PictureBox o doublebuffered Panel :

 class DrawPanel : Panel { public DrawPanel () { DoubleBuffered = true; } } 

Note :

  • Non esiste una "linea" in WinForms, solo pixel di vari colors. Quindi per selezionare una linea è necessario memorizzare le due coordinate dell'endpoint e poi scoprire se è stata cliccata.

  • L'esempio sopra mostra come farlo in matematica.

  • Invece si potrebbe testare ogni linea disegnandola su una bitmap e testare il pixel su cui il mouse ha fatto clic. Ma disegnare quei bitmap dovrebbe anche fare matematica dietro le quinte e allocare lo spazio per le bitmap, quindi la matematica sarà più efficiente ..

  • Sì, la class Line sembra un po 'lunga per una cosa così semplice come una linea, ma guarda quanto sono brevi tutti i codici evento! Questo perché le responsabilità sono al loro posto!

  • Si noti inoltre che la prima regola di eseguire qualsiasi disegno in WinForms è: Non memorizzare mai nella cache o archiviare un object Grahics . In realtà non dovresti mai usare CreateGraphics in primo luogo, poiché l'object Graphics non rimarrà mai nell'oscilloscopio e la grafica prodotta non persisterà (ovvero sopravviverà una sequenza di minimizzazione-ingrandimento).

  • Si noti inoltre come si trasmette l'object e.Graphics dei parametri dell'evento Paint alle istanze Line modo che possano disegnarsi con un object Graphics corrente!

  • Per selezionare linee più sottili può essere utile modificare leggermente la distanza.

  • Il Math è stato preso direttamente da Wikipedia .

Puoi cambiare il colore di tutto al clic. Utilizzando l’evento click di un object particolare.

Ti do un esempio per pulsante. Se fai clic sul pulsante, il colore del panal cambierà. È ansible modificare il codice secondo le proprie esigenze.

 private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas = panel1.CreateGraphics(); } private void panel1_Click(object sender, EventArgs e) { panel1.BackColor = Color.Blue; } private void nonSelectableButton3_Click(object sender, EventArgs e) { panel1.BackColor = Color.BurlyWood; }