在列表中拖放矩形

时间:2016-03-11 14:53:09

标签: c# list mousemove

我在c#中制作了一个简单的应用程序,它让我绘制一个矩形,而不是用鼠标移动它。现在我想绘制多个矩形我也将它们添加到列表中,这也有效,但我希望能够自己移动每个矩形。这出错了。我只能移动我创建的第一个矩形。如果我尝试移动另一个矩形,第一个矩形传送到我的鼠标,但只有当我点击第二个矩形时,如果我点击其他任何地方它会崩溃与nullpointer(我知道如何解决这个但不是问题)我是什么无法弄清楚为什么我不能移动第二个矩形

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace TekenTest
{
    public partial class Form1 : Form
    {
        bool isMouseDown;
        List<Item> _Items;
        Item i;

        public Form1()
        {
            InitializeComponent();
            _Items = new List<Item>(); 
            isMouseDown = false;
        }

        private void tekenVel_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            foreach (Item i in this._Items)
            {
                i.drawItem(g);
            }
        }

        private void tekenVel_MouseDown(object sender, MouseEventArgs e)
        {
           this.i = _Items.Find(Item => ((i.X <= e.X && (i.WIDTH + i.X) >= e.X) &&
                                         (i.Y <= e.Y && (i.HEIGTH + i.Y) >= e.Y)));

            i.note = Color.Azure;
            isMouseDown = true;
        }

        private void tekenVel_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown == true)
            {
                i.X = e.X;
                i.Y = e.Y;
                Refresh();
            }
        }

        private void tekenVel_MouseUp(object sender, MouseEventArgs e)
        {
            isMouseDown = false;
        }

        private void itemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.i = new Item();
            this._Items.Add(i);
            this.Refresh();
        }
    }
}

Object上课

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TekenTest
{
    class Object
    {
        public int X
        {
            get;
            set;
        }

        public int Y
        {
            get;
            set;
        }

        public int HEIGTH
        {
            get;
            set;
        }

        public int WIDTH
        {
            get;
            set;
        }

        public Object()
        {

        }
    }
}

Item上课

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TekenTest 
{
    class Item : Object
    {
        public Rectangle rect;
        public String text;
        public Font font;
        public Brush textb;
        public Color note;

        public Item()
        {
            this.X = 200;
            this.Y = 200;
            this.WIDTH = 200;
            this.HEIGTH = 200;
            font = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point);
            text = "Ik ben tekst";
            note = Color.Yellow;
            textb = Brushes.Black;
        }

        public void drawItem(Graphics g)
        {
            this.rect = new Rectangle(X, Y, WIDTH, HEIGTH);
           // g.DrawRectangle(new)
            g.FillRectangle(new SolidBrush(note), rect);
            g.DrawString(text, font, textb, rect);
        }
    }
}

3 个答案:

答案 0 :(得分:0)

我建议采用不同的方法。我不会使Item成为类变量或属性。每个控件都有一个名为Tag类型为对象的Property。它可以用于任何目的。我通常做的是在创建时将项目设置为所表示控件的标记。然后在Move触发器中,我将处理从Tag属性中提取Item,从对象中强制转换它,然后通过值直接操作它。

private void itemToolStripMenuItem_Click(object sender, EventArgs e)
{
    var i = ((Control)sender.Tag) as Item;

    this.i = new Item();
    this._Items.Add(i);

    // you dynamically create a control and set the Tag property
    someControl.Tag = i;

    this.Refresh();
}


private void tekenVel_MouseDown(object sender, MouseEventArgs e)
{
    var i = ((Control)sender.Tag) as Item;
    if(i!=null)
    {
        i.note = Color.Azure;
        isMouseDown = true;
    }
}

private void tekenVel_MouseMove(object sender, MouseEventArgs e)
{
    if (isMouseDown == true)
    {
            i.X = e.X;
            i.Y = e.Y;
            Refresh();
    }
}

您可能遇到的问题是find方法找不到实例,并且您正在尝试操作null对象。这样,这总是可以在特定对象上工作,而您不必搜索它。它清理代码并且运行得更顺畅。

修改 另外,我建议将您的类从Object重命名为其他内容。这样就不会与.NET对象根类型混淆

答案 1 :(得分:0)

问题可能是因为tekenVel_Paint循环中的函数foreach使用Item的名称与变量i的名称相同。把它改成其他像这里:

    private void tekenVel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        foreach (Item obj in _Items)
        {
            obj.drawItem(g);
        }
    }

tekenVel_MouseDown中的类似问题。您还应该在函数Find中的条件语句中更改名称。

    private void tekenVel_MouseDown(object sender, MouseEventArgs e)
    {
       this.i = _Items.Find(item => ((item.X <= e.X && (item.WIDTH + item.X) >= e.X) &&
                                     (item.Y <= e.Y && (item.HEIGTH + item.Y) >= e.Y)));

        i.note = Color.Azure;
        isMouseDown = true;
    }

此外,您不需要isMouseDown变量。您可以使用MouseEventArgs e功能中的tekenVel_MouseMove检查是否按下了鼠标按钮。 在MouseUp活动中,您应为活动项i设置常用颜色并将其设置为null。如果OnMouseMove不为null,请检查i事件,以防用户在您的控件内部点击但不在任何对象内部。

答案 2 :(得分:0)

我修改了我的列表搜索方法。我现在每个循环都不是最好的方法,所以我稍后会改变它:

private static final float MIN_FRAME_LENGTH = 1f/60f;
private float timeSinceLastRender;

/** @param delta time since the last render call. */
public void render(float delta) {
      timeSinceLastRender += delta;
      if (timeSinceLastRender >= MIN_FRAME_LENGTH) {
           // Do the actual rendering, pass timeSinceLastRender as delta time.
           timeSinceLastRender = 0f;
      }
}