问题
Currently I am making a searching program for Rooms/Office based on the image shown.
I am having trouble on the program that I want show a line on the 2D map where buttons will be use to connect each coordinates of the line. But after searching a room no lines that will appear.
private void button2_Click(object sender, EventArgs e)
{
System.Drawing.Pen myPen;
myPen = new System.Drawing.Pen(System.Drawing.Color.Red, 5);
System.Drawing.Graphics frmGraphics = pictureBox1.CreateGraphics();
if (textBox1.Text == "")
{
MessageBox.Show("Nothing to Search!", "", MessageBoxButtons.OK);
}
else
{
if (radioButton2.Checked == true)
{
if(textBox1.Text == "dental clinic")
{
frmGraphics.DrawLine(myPen, path1.Location.X, path1.Location.Y, path2.Location.X, path2.Location.Y);
Thread.Sleep(500);
frmGraphics.DrawLine(myPen, path2.Location.X, path2.Location.Y, path3.Location.X, path3.Location.Y);
Thread.Sleep(500);
frmGraphics.DrawLine(myPen, path3.Location.X, path3.Location.Y, path4.Location.X, path4.Location.Y);
lbres.Text = "Dental Clinic";
lbloc.Text = "OutPatient Department";
OPDView opdfrm = new OPDView();
dview = opdfrm;
}
else
{
MessageBox.Show("No Results Found!", "", MessageBoxButtons.OK);
}
myPen.Dispose();
frmGraphics.Dispose();
return;
}
}
I have 4 buttons which a had rename as path1 - path4 and wish to connect them all on the line. I need some help about this, thanks.
回答1:
The code has more issues but I'll only hint at them at the end..
The error you probably trip on is in not getting the coordinates right.
PictureBox
is not a container control, so whatever you put on top of it is not sitting inside it. Test by moving the PB: The Buttons
won't move with it.. - Note that this is different from putting a Button
onto a Panel
or a GroupBox
..
There are two ways to fix it:
- You can make the
Buttons
children of thePictureBox
in code or - You can calculate the correct positions.
Here is how to make the Button children of the PB:
path1.Parent = pictureBox1;
path2.Parent = pictureBox1;
path3.Parent = pictureBox1;
Note that you will have to adopt the code that moces the buttons now
Or you correct the position taking the PB's location into account:
Point np1 = Point.Subtract(path1.Location, (Size)pictureBox1.Location);
Point np2 = Point.Subtract(path2.Location, (Size)pictureBox1.Location);
Point np3 = Point.Subtract(path3.Location, (Size)pictureBox1.Location);
frmGraphics.DrawLine(myPen, Point.Empty, np1 , np2);
...
Another issue is thatthe way to draw, using control.CreateGraphics
is not persistent. In fact it is almost always wrong! The results will disappear at each window resize etc.. The better way is to draw in the Picturebox.Paint
event using the e.Graphics
parameter.
I also wonder what the Buttons
are there for in the first place? You can create a List<Point>
and draw without them just as well.
Also using Thread.Sleep(500)
for an animation will freeze the UI thread. Instead use a Timer
to go through the list of points. It you need a fixed number of ways to animate you can create a Dictionary<string, List<Point>>
to hold them all..
Update
To create a list of points is simple. Declare it at class level:
List<Point> way = new List<Point>();
And fill it when you know the data:
way.Add(new Point(100, 100));
way.Add(new Point(150, 100));
way.Add(new Point(150, 200));
way.Add(new Point(10, 200));
way.Add(new Point(10, 220));
way.Add(new Point(50, 220));
way.Add(new Point(50, 250));
Also create a Timer and set its Interval. In its Tick event you move up a pointer to the current segment and call the Paint event be invalidating the PictureBox:
void aTimer_Tick(object sender, EventArgs e)
{
point = Math.Min(point + 1, way.Count);
pictureBox1.Invalidate();
if (point >= way.Count) aTimer.Stop();
}
And in the Paint event of the PictureBox you draw the path from start to the current index:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(Color.DarkGoldenrod, 2.5f))
for (int i = 1; i < point; i++) e.Graphics.DrawLine(pen , way[i - 1], way[i]);
}
I left out a few checks and you will want to think of a way to store or construct the point lists..
You also may want to improve the animation by drawing smaller segments. For this you could add more points but using a function will be more flexible..:
int stepLen = 10; // draw 10 pixels on each tick
List<Point> SlowWay(List<Point> way)
{
List<Point> slow = new List<Point>();
for (int i = 1; i < way.Count; i++ )
{
int dx = way[i].X - way[i - 1].X;
int dy = way[i].Y - way[i - 1].Y;
float len = (float)Math.Sqrt(dx*dx+dy*dy);
int stepCount = (int)(len / stepLen);
float stepX = dx / stepCount;
float stepY = dy / stepCount;
slow.Add(way[i - 1]);
for (int s = 0; s < stepCount; s++)
slow.Add(new Point((int)(way[i - 1].X + s * stepX),
(int)(way[i - 1].Y + s * stepY)));
}
slow.Add(way[way.Count - 1]);
return slow;
}
来源:https://stackoverflow.com/questions/34995588/draw-a-line-using-buttons-as-a-coordinates-on-a-picturebox