在列表中拖放矩形
Drag and drop rectangles in list
我用 c# 制作了一个简单的应用程序,它可以让我绘制一个矩形,然后用鼠标移动它。现在我想绘制多个矩形我也将它们添加到列表中,这也有效,但我希望能够单独移动每个矩形。这是错误的。我只能移动我创建的第一个矩形。如果我尝试移动另一个矩形,第一个矩形会传送到我的鼠标,但只有当我单击第二个矩形时,如果我单击其他任何地方,它会因空指针而崩溃(我知道如何解决这个问题,但这不是问题)无法弄清楚为什么我不能移动第二个矩形
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
class
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
class
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);
}
}
}
我建议采用不同的方法。我不会将 Item 设为 class 变量或 属性。每个控件都有一个 属性 类型对象的命名标签。它可以用于任何目的。我通常会做的是在创建时将项目设置为表示控件的标签。然后在移动触发器中,我将处理从标签 属性 中提取项目,从对象中转换它,然后直接通过值对其进行操作。
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 方法未找到该实例,而您正试图操作一个空对象。这样,它始终适用于特定对象,您不必搜索它。它清理了代码并且运行起来更加流畅。
编辑
另外,我建议将您的 class 从 Object 重命名为其他名称。只是为了不与 .NET 对象根类型混淆
问题可能是因为在 foreach
循环中的函数 tekenVel_Paint
中,您使用的 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
变量。您可以使用 tekenVel_MouseMove
函数中的 MouseEventArgs e
检查鼠标按钮是否被按下。
在 MouseUp
事件中,您应该为活动项目设置常用颜色 i
并将其设置为 null
。如果 i
不为空,则检查 OnMouseMove
事件,以防用户在您的控件内单击但不在任何对象内单击。
我通过更改列表搜索方法修复了问题。我现在 for each 循环不是最好的方法,所以我稍后会更改它:
private Item selectItem(MouseEventArgs e)
{
IEnumerable<Item> itemQuerry =
from it in _Items
where it.X <= e.X && it.WIDTH + it.X >= e.X && it.Y <= e.Y && it.HEIGTH + it.Y >= e.Y
select it;
foreach (Item foundItem in itemQuerry)
{
this.mItem = foundItem;
}
mItem.note = Color.Azure;
return mItem;
}
我用 c# 制作了一个简单的应用程序,它可以让我绘制一个矩形,然后用鼠标移动它。现在我想绘制多个矩形我也将它们添加到列表中,这也有效,但我希望能够单独移动每个矩形。这是错误的。我只能移动我创建的第一个矩形。如果我尝试移动另一个矩形,第一个矩形会传送到我的鼠标,但只有当我单击第二个矩形时,如果我单击其他任何地方,它会因空指针而崩溃(我知道如何解决这个问题,但这不是问题)无法弄清楚为什么我不能移动第二个矩形
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
class
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
class
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);
}
}
}
我建议采用不同的方法。我不会将 Item 设为 class 变量或 属性。每个控件都有一个 属性 类型对象的命名标签。它可以用于任何目的。我通常会做的是在创建时将项目设置为表示控件的标签。然后在移动触发器中,我将处理从标签 属性 中提取项目,从对象中转换它,然后直接通过值对其进行操作。
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 方法未找到该实例,而您正试图操作一个空对象。这样,它始终适用于特定对象,您不必搜索它。它清理了代码并且运行起来更加流畅。
编辑 另外,我建议将您的 class 从 Object 重命名为其他名称。只是为了不与 .NET 对象根类型混淆
问题可能是因为在 foreach
循环中的函数 tekenVel_Paint
中,您使用的 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
变量。您可以使用 tekenVel_MouseMove
函数中的 MouseEventArgs e
检查鼠标按钮是否被按下。
在 MouseUp
事件中,您应该为活动项目设置常用颜色 i
并将其设置为 null
。如果 i
不为空,则检查 OnMouseMove
事件,以防用户在您的控件内单击但不在任何对象内单击。
我通过更改列表搜索方法修复了问题。我现在 for each 循环不是最好的方法,所以我稍后会更改它:
private Item selectItem(MouseEventArgs e)
{
IEnumerable<Item> itemQuerry =
from it in _Items
where it.X <= e.X && it.WIDTH + it.X >= e.X && it.Y <= e.Y && it.HEIGTH + it.Y >= e.Y
select it;
foreach (Item foundItem in itemQuerry)
{
this.mItem = foundItem;
}
mItem.note = Color.Azure;
return mItem;
}