This question already has an answer here:
Why does my program draw all the lines from the top left corner? How to change this?
(1 answer)
Closed last month.
I am trying to make a program that will draw lines between 10 coordinates, determined by mouseclicks.
i can not get it to work.
code:
EDIT:
i figured out i have to define the coordinates making x and y values.
only it is still unclear how to do this.
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Point[] punten = new Point[2];
int index = 0;
int kliks = 0;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
Point[] punten = new Point[2];
int index = 0;
int kliks = 0;
kliks = kliks + 1;
index = kliks;
punten[index] = e.Location;
if (index < 2)
{
punten[index] = e.Location;
}
else
{
Pen pen = new Pen(Color.Blue);
Graphics papier = pictureBox1.CreateGraphics();
papier.DrawLines(pen, punten);
}
}
I have re read the textbook 10 times.. its unclear where to create the variables intially, but if i dont create them under pictureBox1 mouse click, i also cant use them.
Any help is appreciated.
greetings, Stefan.
i got it to work!
i need to keep telling my damn self: its all in the textbook...
with the explanations given by you guys (declaring variables at class level)
the instructions in the textbook work..
code:
public partial class Form1 : Form
{
Point[] punten = new Point[10];
private int kliks = 0;
private int lijst = 0;
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
kliks = kliks + 1;
lijst = kliks;
punten[lijst] = e.Location;
if (lijst < 5)
{
punten[lijst] = e.Location;
}
else
{
Pen pen = new Pen(Color.Blue);
Graphics papier = pictureBox1.CreateGraphics();
papier.DrawLines(pen, punten);
}
}
}
}
The Scope a variables is defined determines its accessibility within the process. You need to declare the punten array and the kliks int variables at the class level so they can be maintained across the button clicks.
public Form1()
{
InitializeComponent();
}
// create variables at class scope so they are
// accessible by all methods in this class and state is maintained
// across button clicks
private Point[] punten;
private int kliks;
private void Form1_Load(object sender, EventArgs e)
{
// initialize class level variables at form load
punten = new Point[10];
kliks = 0;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
int index = kliks;
if(index == 9) // arrays are zero based so our 10 items are at indexes 0 through 9
{
// append last mouse point clicked to list of points
punten[index] = new Point(e.Location.X, e.Location.Y);
// draw lines between all points
Pen pen = new Pen(Color.Blue);
Graphics papier = pictureBox1.CreateGraphics();
papier.DrawLines(pen, punten);
punten = new Point[10];
kliks = 0;
}
else
{
// append mouse point clicked to list of points
punten[index] = new Point(e.Location.X, e.Location.Y);
kliks = kliks + 1;
}
}
Related
i am trying to make signature panel in c# windowsform application where input is from drawing tablet
my code as below this code working for line drawing not dot created.
So please suggest how dot and line both are create.
{
Graphics graphics;
Boolean cusorMoving = false;
Pen cursorPen;
int cursorX = -1;
int cursorY = -1;
public SignPad()
{
InitializeComponent();
graphics = panel2.CreateGraphics();
cursorPen = new Pen(Color.Black, 2);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
Mouse Down event
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
cusorMoving = true;
cursorX = e.X;
cursorY = e.Y;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
cusorMoving = false;
cursorX = -1;
cursorY = -1;
}
Mouse Move event
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (cursorX != -1 && cursorY != -1 && cusorMoving == true)
{
graphics.DrawLine(cursorPen, new Point(cursorX, cursorY), e.Location);
cursorX = e.X;
cursorY = e.Y;
}
}
You need to store individual points in a collection and draw them separately in the Paint handler. Every time you add a point to the collection, you also need to tell the panel to draw the area where the new segment was added. Something like this:
using System.Collections.Generic;
using System.Drawing;
namespace Lines
{
public partial class SignPad : Form
{
Pen cursorPen = SystemPens.ControlText;
List<Point> points = new List<Point>();
bool cursorMoving = false;
public SignPad()
{
InitializeComponent();
cursorPen = new Pen(Color.Black, 2);
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel2_Paint(object? sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for (int i = 1; i < points.Count; ++i)
g.DrawLine(cursorPen, points[i - 1], points[i]);
}
private void panel2_MouseDown(object? sender, MouseEventArgs e)
{
if (!cursorMoving)
{
cursorMoving = true;
points.Clear();
points.Add(e.Location);
panel2.Invalidate();
}
}
private void panel2_MouseMove(object? sender, MouseEventArgs e)
{
if (cursorMoving && points.Count > 0)
{
var p = e.Location;
var q = points[points.Count - 1];
var r = Rectangle.FromLTRB(Math.Min(p.X, q.X), Math.Min(p.Y, q.Y), Math.Max(p.X, q.X), Math.Max(p.Y, q.Y));
r = Rectangle.Inflate(r, (int)cursorPen.Width, (int)cursorPen.Width);
points.Add(p);
panel2.Invalidate(r);
}
}
private void panel2_MouseUp(object? sender, MouseEventArgs e)
{
cursorMoving = false;
}
}
}
Don't forget to add the Paint handler the same way you added MouseMove, MouseDown and MouseUp handlers - in the Designer.
I want to click on points that I drew.
It would be also cool if a window would popup and I could do something with that. But the general thing i want to do is clicking on a drawn point. I want to make it work, that i can click on the map on points that I drew.
Example image:
public partial class Form1 : Form
{
Graphics g;
Pen p;
Point cursor;
int k = 0;
Point[] points = new Point[50];
public Form1()
{
InitializeComponent();
g = pbxkarte.CreateGraphics();
p = new Pen(Color.DeepSkyBlue, 3);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Pbxkarte_Click(object sender, EventArgs e)
{
if (drawmodecbx.Checked == true)
{
g.DrawEllipse(p, cursor.X - 10, cursor.Y - 10, 20, 20);
points[k++] = new Point(cursor.X, cursor.Y);
lbxDrawnPoints.Items.Add("X:" + cursor.X + "Y:" + cursor.Y);
}
}
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
cursor = this.PointToClient(Cursor.Position);
xydisplay.Text = "X:" + cursor.X + "Y:" + cursor.Y;
}
}
}
Example code:
Two class level variables and a helper function:
List<Point> dots = new List<Point>();
int dotSize = 12;
Rectangle fromPoint(Point pt, int size)
{
return new Rectangle(pt.X - size/ 2, pt.Y - size / 2, size, size);
}
The mouseclick (as opposed to the click event) contains the location:
private void Pbxkarte_MouseClick(object sender, MouseEventArgs e)
{
if (!dots.Contains(e.Location))
{
dots.Add(e.Location);
Pbxkarte.Invalidate(); // show the dots
}
}
You could add code to remove dots or change the properties, esp. if you create a dot class. - If you want to avoid overlapping dots you can to use code like the one in the mousemove to detect this. But. Don't repeat the code! Instead factor out a boolOrPoint IsDotAt(Point) function you can use both times!!
In the mousemove I only show the hit state. You do your thing..
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
bool hit = false;
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
if (gp.IsVisible(e.Location))
{
hit = true; break;
}
}
}
Cursor = hit ? Cursors.Hand : Cursors.Default;
}
All dot in the list must get shown every time anything changes, both in the list or in the system.:
private void Pbxkarte_Paint(object sender, PaintEventArgs e)
{
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
e.Graphics.FillPath(Brushes.Red, gp);
}
}
}
If you want more properties, like texts or colors do create a class dot and use a List<dot> !
I have a class assignment to move a picturebox randomly across the form. Once you click on the picturebox, it is supposed to scream and change the picture then change it back to the original picture. When you click again, it is supposed to go faster. I have it working up to the point of making it go faster. Here is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
tm1.Interval = 1000;
tm1.Tick += new EventHandler(tm_Tick);
}
Timer tm1 = new Timer();
int X = 0;
int Y = 0;
private void pictureBox1_Click(object sender, EventArgs e)
{
if (timer1.Enabled)
{
timer1.Stop();
pictureBox1.Image = Properties.Resources.Mimikyu;
Application.DoEvents();
pictureBox1.WaitOnLoad = true;
System.Threading.Thread.Sleep(10);
SoundPlayer sp = new SoundPlayer(Properties.Resources.screa);
sp.PlaySync();
pictureBox1.Image = Properties.Resources.Evee;
}
else
timer1.Start();
}
private void tm_Tick(object sender, EventArgs e)
{
int X = ((int)(new Random().Next(0, 1000)));
int Y = ((int)(new Random().Next(0, 500)));
if (X > 1025 - pictureBox1.Width)
{
X = 1025 - pictureBox1.Width;
}
if (Y > 545 - pictureBox1.Height)
{
Y = 545 - pictureBox1.Height;
}
pictureBox1.Location = new Point(X, Y);
}
}
}
Point me to where I need to go to get the interval to move faster and faster after each click Thank you.
decreasing the tm1.Interval should do it
...
else
if (tm1.Interval>10){tm1.Interval -= 10;}
timer1.Start();
I created 5 PictureBox "Shapes" and I want them to move to the left automatically when the program is launched. So in the timer1_Tick method, I use "Shapes[i].Left -= 2", it's said that "Shapes" isn't in the actual context, so How can I make the Shapes[i] global from the "CreatePipes" method?
public partial class Form1 : Form
{
int i = 0;
int N = 5;
int yspeed;
int gravity = 2;
public Form1()
{
InitializeComponent();
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
yspeed = -15;
}
}
private void Form1_Load(object sender, EventArgs e)
{
CreatePipes(1);
}
public void CreatePipes(object Number)
{
PictureBox[] Shapes = new PictureBox[N];
for (i = 0; i < N; i++)
{
Shapes[i] = new PictureBox();
Shapes[i].Name = "ItemNum_" + i.ToString();
Shapes[i].Location = new Point(300 + 120 * i, 250);
Shapes[i].Size = new Size(30, 1000 );
Shapes[i].BackColor = Color.Green;
Shapes[i].Visible = true;
this.Controls.Add(Shapes[i]);
}
}
private void bird_Click(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
for (i = 0; i < N; i++)
{
Shapes[i].Left -= 2; //So the problem is here. Shapes[i] isn't in the actual context. But I don't know to to make it global from CreatePipes
}
yspeed += gravity;
bird.Top += yspeed;
}
}
}
You have to declare PictureBox[] Shapes above CreatePipes function, in Form1 class. Then in CreatePipes func, change PictureBox[] Shapes = new PictureBox[N]; to Shapes = new PictureBox[N];
I Have a bresenham algorithm which I wrote it in class Line
I Can draw lines Now I wanted to draw polygons so I wrote it's function(void Polygon)
I should store coordinates of each click in an array and then my function should get them
I don't know how to store each click
Radiobutton1 is for draw line and radiobutton2 is for drawing polygons
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
if(radioButton1.Checked)
if (firstClick)
{
firstX = e.X;
firstY = e.Y;
firstClick = false;
}
else
{
Line l = new Line(firstX, firstY, e.X, e.Y, panel1.CreateGraphics(), Convert.ToInt32(textBox1.Text));
firstClick = true;
}
if(radioButton2.Checked)
{
//how to write here so as to store each click in array
}
}
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(textBox2.Text);
Polygon(n, coor);
}
void Polygon(int n,int[] coordinates)
{
if(n>=2)
{
Line l=new Line(coordinates[0],coordinates[1],coordinates[2],coordinates[3],panel1.CreateGraphics(), Convert.ToInt32(textBox1.Text));
for(int count=1;count<(n-1);count++)
l=new Line(coordinates[(count*2)],coordinates[((count*2)+1)],coordinates[((count+1)*2)],coordinates[(((count+1)*2)+1)],panel1.CreateGraphics(), Convert.ToInt32(textBox1.Text));
}
You can make a point of the click coordinates:
Point p = new Point(e.x, e.y);
Save the points you get in a List:
// Declaration:
List<Point> myPoints = new List<Point>();
// in the method:
if (radioButton2.Checked) {
myPoints.Add(new Point(e.x, e.y));
}
An array will not be a good idea, because you normally don't have any idea how many clicks there will be. A List is of variable length, so it's useful in this situation.