我正在为我的学校工作做一些例子。
现在我陷入了困境。我会尝试尽可能包含litllet代码,但我不确定你们都需要什么......
(对不起,包括我家乡的名字和作品)
继承我需要做的事情: 我得到了我的“绘画程序”,您可以通过单击添加点,然后相互绘制线条。我编写了一个网格,当你选中一个复选框时,它会在rastr(网格)列表中查找最近的可能点,然后将其坐标应用到你试图用鼠标绘制的点。
您还可以按轨迹栏值缩放该网格。
现在我的问题出现了:当我缩放它时,我需要用网格移动我的绘制点。我没有任何线索,因为我不能只为grid.X = p.X + trackbarValue中的每个点做。 (发生错误)
这是我的网格和绘画代码:
List<Point> rastr = new List<Point>(); //rastr means grid
List<Point> body = new List<Point>(); //painting poits
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics kp = e.Graphics;
foreach (Point p in body)
{
kp.FillEllipse(st, p.X-s/2, p.Y-s/2, s, s);
}
//double buffer nezapomenout
if (body.Count>1)
{
kp.DrawLines(pero, body.ToArray());//to array prevedeni na pole
}
for (int x = 0; x < panel1.Width; x += trackBarGrid.Value)
for (int y = 0; y < panel1.Height; y += trackBarGrid.Value)
{
if (showGrid == true)
{
kp.FillEllipse(grid, x-2, y-2, 4, 4);
}
Point gridpoint = new Point(x,y);
rastr.Add(gridpoint);
}
}
这里是寻找网格中最近的一个,然后应用坐标:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
if (useGrid == true)
{
//rozjedu cykly abych nasel nejblizsi bod (porovnavat jednotlivy koordinace)
foreach (Point p in rastr)
{
if (e.Location.X - p.X < trackBarGrid.Value / 2) //kdyz odecteme pozici bodu v listu rastr.x od pozice x kliknuti nesmi byt vetsi nez polovina delky odsazeni rastrovych bodu
if (e.Location.Y - p.Y < trackBarGrid.Value / 2) // to same jen s pozici Y
{
Point zapsat = new Point(p.X, p.Y);
body.Add(zapsat); //od tyhle pozice najit nejblizsi point v gridu
break;//bod jsme uspesne nasli. Nyni musime cyklus uzavrit aby se nezacli pridavat body ktere nechceme
}
}
panel1.Refresh();
}
else {
body.Add(e.Location);
panel1.Refresh();
}
}
我的轨迹栏事件:
private void trackBarGrid_Scroll(object sender, EventArgs e)
{
rastr.Clear();
panel1.Refresh();
}
我对此的不良尝试
private void trackBarGrid_Scroll(object sender, EventArgs e)
{
foreach (Point p in rastr)
{
p.X += TrackBarValue;
p.Y += TrackBarValue;
}
panel1.Refresh();
}
最后一点,我不需要保留“写意”画。我可以使用那个网格。
这是一些照片..
答案 0 :(得分:1)
There are two ways you can chose to scale your graphics. One is extremely simple the other somewhat involved.
Here is the simple one:
Simply add this to the top of the Paint
event:
float scale = trackBar1.Value / 100f;
if (scale == 0) scale = 1;
e.Graphics.ScaleTransform(scale, scale);
This looks a bit convoluted but the TrackBar
will not have a value when the Paint
event is called at first.
The Graphics
object itself is now scaled and everything you draw with will be scaled.
That was really simple.
One possible issue you may have is that everything, including the width of a Pen
will be scaled up or down.
You were going for the more involved way in your question, so let's do that as well..:
First we create a function that scales a point accoding to the TrackBar
's Value
. Here it is:
PointF scaledPoint(PointF pt, float scale, bool unscale)
{
if (unscale) return new PointF(pt.X / scale, pt.Y / scale);
else return new PointF( pt.X * scale, (pt.Y * scale));
}
Two things are worth noting:
The function actually works with PointF
not Point
. This is really important as the scaling must not lose precision! Going from, say 5 down to 33% and back up again will not go back to 5 but to 3..!
There is an extra parameter that will remove the scaling from a point. We don't need it at the moment; but you will, once you want to catch a point from a MouseClick
when the scaling is on!
Now let's use it to scale our point list.
We could do it directly, maybe like this:
for (int p = 0; p < body.Count; p++)
body[p] = scaledPoint(body[p], scale, false);
While this will work is has a nasty issue: When we move the TrackBar
it will reapetedly apply a growing scaling factor. This means that the graphics will get larger faster and faster..not good.
Instead we create a second List<PointF> bodyO
with the original point values, which need to maintain..
That means we add points to bodyO
but draw with body
and scale bodyO
to body..:
void scalePoints(float scale)
{
for (int p = 0; p < body.Count; p++)
body[p] = scaledPoint(body0[p], scale, false);
}
We call pretty much as in your code:
private void trackBar1_Scroll(object sender, EventArgs e)
{
scalePoints(trackBar1.Value / 100f);
panel1.Refresh();
}
Let's see how this works in the Paint
event:
private void panel1_Paint(object sender, PaintEventArgs e)
{
float scale = trackBar1.Value / 100f;
if (scale == 0) scale = 1;
bool showGrid = true; // inserted for testing
// these graphics work with the scaled points:
foreach (PointF pt in body) e.Graphics.FillEllipse(Brushes.Red,
pt.X - 2, pt.Y - 2, scale * 4, scale * 4);
if (body.Count > 1) e.Graphics.DrawLines(Pens.Black, body.ToArray());
// here we don't use points but calculate the coordinates, so we need to scale
for (int x = 0; x < panel1.Width; x += trackBar2.Value)
for (int y = 0; y < panel1.Height; y += trackBar2.Value)
{
if (showGrid == true)
{
e.Graphics.FillEllipse(Brushes.Gray,
scale * (x - 2), scale * (y - 2), scale * 4, scale * 4);
}
// Point gridpoint = new Point(x, y); // not sure what you do here..?
// rastr.Add(gridpoint); // maybe add the point scaled?
}
}
Note that I scaled the size of the points as well. Btw, to make both version look all the same you would have to scale the Pen
as well:
using (Pen pen = new Pen(somecolor, penWidth * scale))
Finally here is how to add a new Point in the MouseClick:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
body0.Add(scaledPoint(e.Location, trackBar1.Value / 100f, true));
body.Add(e.Location);
panel1.Invalidate();
}
We add it to the original list bodyO
reversing the current scaling and as is, i.e with the current 'pixel size' to the scaled list..
Btw: The many grid points take some time without DoubleBuffering
; this creates some flicker.. So either use a Panel
subclass with DoubleBuffering
:
class DrawPanel : Panel
{
public DrawPanel()
{ DoubleBuffered = true; }
}
Or go for a Picturebox
(recommended)!
答案 1 :(得分:0)
我以某种方式设法从那个列表中取出那些点然后编辑它们并将它们放回去。所以你说我只需要弄清楚那些缩放因子。它已经移动但没有与网格相对应。我说对不起我的英语,所以你看我不可能更纠正它:对不起......我出来帮助我了;((只是笑了一下这个专业档案说明) 一些人在这里发布的问题甚至比这更糟糕:D无论如何,我自己也有点解决了这个问题。 只是那个倍增的东西:)
private void trackBarGrid_Scroll(object sender, EventArgs e)
{
if (trackBarGrid.Value > trackbarval)
{
for (int i = 0; i < body.Count; i++)
{
Point point = body[i];
point.X += trackBarGrid.Value - trackbarval;
point.Y += trackBarGrid.Value - trackbarval;
body[i] = point;
}
}
else if (trackBarGrid.Value < trackbarval)
{
for (int i = 0; i < body.Count; i++)
{
Point point = body[i];
point.X -= trackbarval- trackBarGrid.Value;
point.Y -= trackbarval- trackBarGrid.Value ;
body[i] = point;
}
}
rastr.Clear();
panel1.Refresh();
trackbarval = trackBarGrid.Value;
}