2016-03-11 2 views
0

Я создал простую программу в 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); 
     } 
    } 
} 
+1

Ваше заявление поиска в tekenVel_MouseDown проблематично. Вы используете i (очень плохое имя, на мой взгляд), которое является переменной класса, как если бы это была временная локальная переменная, созданная выражением лямбда. Вы должны написать что-то вроде: '_Items.Find ( temp => ( (temp.X <= e.X && (temp.WIDTH + temp.X)> = e.X) && (temp.Y <= eY && (temp.HEIGTH + temp.Y)> = eY) ' –

ответ

0

Я исправил это, изменив метод поиска в списке. Я сейчас для каждого цикла не лучший способ, поэтому я изменю это позже:

 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; 
    } 
0

I предложит другой подход. Я бы не сделал Item переменной класса или свойством. Каждый элемент управления имеет свойство Tag с типом объекта. Он может использоваться для любых целей. То, что я обычно делал, - это создать элемент как тег представленного элемента управления. Затем в триггере Move я обработаю извлечение Item из свойства Tag, отбрасывает его из объекта, а затем манипулирует им напрямую через значения.

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(); 
    } 
} 

Вы, наверное, проблема, что экземпляр не найден методом найти и вы пытаетесь манипулировать нулевой объект. Таким образом, это всегда будет работать над конкретным объектом, и вам не нужно его искать. Он очищает код, и он работает намного плавнее.

EDIT Кроме того, я бы предложил переименовать свой класс из Object в другое. просто так это не запутаться с объектом .NET корневого типа

+0

Mmm Я не совсем понимаю, как использовать свойство Tag моего прямоугольника, у вас есть простой пример ? – Zeepblok

+0

посмотреть. Вы создаете элемент управления прямоугольником, и это тег элемента управления, вы устанавливаете Item. Все уже есть в коде, который я предоставил – user853710

+0

Я продолжаю получать ошибку: объект не содержит определения тега на части: var i = ((Control) sender.Tag) как Item; – Zeepblok

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, если i не является нулевым, если пользователь щелкнет внутри вашего элемента управления, но не внутри какого-либо объекта.

Смежные вопросы