当其他面板移动时,面板上的抽绳会发生变化

时间:2014-12-24 14:55:15

标签: c# panel paint drawstring

我按下每个按钮绘制一个矩形面板。之后,在矩形边缘添加一条线,在中心添加文字。但是当我拖动一个面板移动到其他面板上时。面板字符串将更改。请指教。我无法上传图片。如何上传这样的图像可以更清楚地显示我的问题。

此链接http://i3.photobucket.com/albums/y53/ctkhai/1-4.png显示我的软件的gui。左上角和左下角是图片框。用户添加一个"框"当点击按钮一次和"框"将显示在左上角。用户可以将框拖动到右下方并排列所有框。

现在问题是用户拖动新添加的"框"并移动其他一些"框",我在前一个框上绘制的文字将会改变。像这样http://i3.photobucket.com/albums/y53/ctkhai/2-4.png

更新:我尝试为标签创建一个类。但它不会工作,数字再次改变。这是我为标签创建类的方式,读取是错误的?代码如下

Product _box = new Product();
List<Panel>product = new List<Panel>();

public  class Product
{        
    public  float X { set; get; }     //box coordinate
    public  float Y { set; get; }     //box coordinate
    public  int rotate { set; get; }
    public  int entryP { set; get; }
    public  int boxName { set; get; }

}

private void button_RecAdd_Click(object sender, EventArgs e)
{


   locX = pictureBox_conveyor.Left + (pictureBox_conveyor.Width / 2 - box_y / 2);
   locY = pictureBox_conveyor.Top + (pictureBox_conveyor.Height / 2 - box_x / 2);

   _box.boxName = panelBoxNo;
   _box.entryP = 1;
   _box.rotate = 0;
   _box.X = locX;
   _box.Y = locY;


   Panel box = new Panel();
   box.Location = new Point(locX, locY);
   box.Name = "box" + panelBoxNo;
   box.Tag = _box;  
   box.Size = new Size(box_y, box_x);
   box.BackColor = boxColor;
   pbW = box.Width;
   pbH = box.Height;
   box.MouseDown += panelBox_MouseDown;
   box.MouseMove += panelBox_MouseMove;               


   box.Paint += new PaintEventHandler((s, m) =>
   {

       Graphics g = m.Graphics;
       g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;]

       Product b = box.Tag as Product;

       string text = b.boxName.ToString();

       SizeF textSize = m.Graphics.MeasureString(text, Font);
       PointF locationToDraw = new PointF();
       locationToDraw.X = (pbW / 2) - (textSize.Width / 2);
       locationToDraw.Y = (pbH / 2) - (textSize.Height / 2);

       g.DrawString(text, Font, Brushes.Black, locationToDraw);
       g.DrawRectangle(new Pen(Color.Black), 0, 0, pbW - 1, pbH - 1);
       g.DrawLine(drawLine, 0, 0, 0, pbH);                      

   });

   product.Add(box);
   panel_pelletLayout.Controls.Add(box);
   box.BringToFront();
   label_boxNo.Text = panelBoxNo.ToString();
   panelBoxNo++;

}

private void panelBox_MouseDown(object sender, MouseEventArgs e)
    {
        Panel p = sender as Panel;

        if (e.Button == MouseButtons.Left)
        {
            xPos = e.X;
            yPos = e.Y;

            if (p != null)
            {
                activePnlBox = p.Name;                                     
                textBox_selectedName.Text = p.Name;                    
                textBox_selectedX.Text = p.Left.ToString();
                textBox_selectedY.Text = p.Top.ToString();

            }
        }
    }

private void panelBox_MouseMove(object sender, MouseEventArgs e)
    {
        Panel p = sender as Panel;      

        if (p != null)
        {

            if (e.Button == MouseButtons.Left)
            {

                p.Left = ((e.X + p.Left - (p.Width / 2)) / gripGap) * gripGap;                    
                p.Top = ((e.Y + p.Top - (p.Height / 2)) / gripGap) * gripGap;

                textBox_selectedX.Text = p.Left.ToString();
                textBox_selectedY.Text = p.Top.ToString();

            }        
        }
    }

3 个答案:

答案 0 :(得分:1)

您的Paint事件处理程序必须负责每次都绘制所有内容。您的代码看起来只绘制一个对象。

当您在box上拖动某些内容时,该框变为无效,需要从头开始绘制,这意味着它会删除所有内容并调用您的Paint处理程序。然后,您的Paint事件处理程序只绘制一个对象。

我怀疑你想要做的是保留你绘制的每个项目的数据结构,然后在Paint事件处理程序中有一个循环,它将绘制你添加的所有对象。

答案 1 :(得分:1)

不要在paint事件中使用在循环外定义的变量。那可能是你的问题。 尝试绘制((Panel)s).Name。这是否正常?

答案 2 :(得分:0)

您的标题让我们所有人感到困惑..您不会绘制矩形,您在每个ButtonClick上创建新的面板,对吗?

Paint事件的代码并不完全正确。就像在任何Paint事件中一样,您应该使用内置的Graphics对象。正如汉斯所指出的那样,你不应该摧毁/处置你没有创造的东西。

您描述的主要问题似乎是您的盒子必须在不参考实际数字的情况下自己绘画。你应该存储他们的号码在他们的Tags ..

(或者您可以从他们的Names中提取它,就像您在MouseDown中一样!)

box[panelBoxNo].Name = "box" + panelBoxNo;
box[panelBoxNo].Tag =  panelBoxNo;                     // < === !!
//..

box[panelBoxNo].Paint += new PaintEventHandler((s, m) =>
{
   Graphics g = m.Graphics;                            // < === !!
   g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
   string text = box[panelBoxNo].Tag.ToString();       // < ===
   SizeF textSize = g.MeasureString(text, Font);
   PointF locationToDraw = new PointF();
   locationToDraw.X = (pbW / 2) - (textSize.Width / 2);
   locationToDraw.Y = (pbH / 2) - (textSize.Height / 2);

   g.DrawString(text, Font, Brushes.Black, locationToDraw);
   g.DrawRectangle(new Pen(Color.Black), 0, 0, pbW - 1, pbH - 1);
   g.DrawLine(drawLine, 0, 0, 0, pbH);
   //  g.Dispose();                       // < === !!

  //  m.Graphics.DrawImageUnscaled(drawBox, new Point(0, 0));         // < === !!
  // m.Dispose();                       // < === !!
});

而且,正如我已经注意到的,如果您(或代码)确实知道元素的数量,那么您应该只使用数组。在您的情况下,List<Panel>可以灵活地保存任意数量的元素,而不会更改代码的任何其他部分,除了添加。您可以像数组一样访问List。 (它在幕后......)

更新:我现在看到的方式,你的问题都以某种方式与范围有关。

Scope最直接的含义是代码的一部分其中变量是已知且可访问的。在稍微宽泛的含义中,它也是它具有您需要的价值的时间。

您的原始问题属于后一种类型:您在Panel的thr Paint事件中访问了partNo,当它长期更改为新的,可能更高的值时。

您当前的问题是了解ButtonClick事件中变量的范围。

通常这没问题;看着一对大括号,范围很明显。但是:这里我们有一个动态创建的Lambda事件,这完全超出了Click事件的范围! 在幕后,此Paint事件将从Click代码中删除,放置在一个新事件中,并替换为一条线,只需将一个委托添加到Paint处理程序,就像任何常规事件一样。

所以:ButtonClick中声明的 <{1}}代码已知

要访问这些数据,您必须将它们放在Paint中,我们就是Panel properties,并通过Tag参数Sender投射来访问它们。

所以你需要在Paint事件中更改这一行

s

这样的事情:

Product b = box.Tag as Product;