动态改变图形矩形的颜色 [英] Change color of graphic rectangle dynamically

查看:213
本文介绍了动态改变图形矩形的颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个c#类,里面包含图形。
这是我如何构建类并绘制矩形。它完美地工作:

 公共图形形状; 
public Rectangle rc;

//构造函数
public CLASS_NAME(Graphics formGraphics)
{
this.shape = formGraphics;

$ b $ public void draw(int x,int y,int w,int h)
{
SolidBrush myBrush = new SolidBrush(Color.Red);
this.rc = new Rectangle(x,y,w,h);
this.shape.FillRectangle(myBrush,rc);

myBrush.Dispose();
}

然后我想为对象添加一个新方法以更改颜色,但是当我调用这个没有任何反应时:

  public void change_color()
{
SolidBrush myBrush =新的SolidBrush(Color.Yellow);
this.shapeFillRectangle(myBrush,rc);
myBrush.Dispose();
}

我也试过: rc.Fill = 但VS无法识别 rc.Fill 作为有效的方法。




  • 我得到的错误:它表示在 change()方法中,这一行: this .shapeFillRectangle(myBrush,rc); 有一个无效的参数。

解决方案

好的,让我们从一个'drawRectangle'类开始。它有足够的数据来创建一个简单的 Pen ,拥有一个 Rectangle 并且引用 Control 它会被使用。



我添加了一个 ToString 覆盖,所以我们可以显示它的所有属性,比如 ListBox ..



version 1 < >

  public class DrawRectangle 
{
public Color color {get;组; }
public float width {get;组; }
public Rectangle rect {get;组; }
公共控制表面{get;组; }

public DrawRectangle(Rectangle r,Color c,float w,Control ct)
{
color = c;
width = w;
rect = r;
surface = ct;
}

public override string ToString()
{
return rect.ToString()+(+ color.ToString()+
- + width.ToString(0.00)+)on+ surface.Name;


接下来我们需要这些矩形的列表: p>

  public List< DrawRectangle> rectangles = new List< DrawRectangle>(); 

现在让我们将它们添加到按钮点击的循环中:

  private void buttonAddLoop_Click(object sender,EventArgs e)
{
for(int i = 0; i <10; i ++)
rectangles.Add(new DrawRectangle(new Rectangle(i * 30,i * 30,22,22),
Color.Black,3.5f,drawPanel1));
drawPanel1.Invalidate();
}

请注意我是如何使我希望它们被控制的控件无效无效它! (您也可以使用 Form ,因为 Form 继承自 Control

为此,我们需要编写每个需要控件的 Paint c事件画一些矩形;我只使用一个面板drawPanel1

  private void drawPanel1_Paint(object sender ,PaintEventArgs e)
{
foreach(DrawRectangle dr在矩形中)
{
if(dr.surface == sender)
{
using(Pen pen = new Pen(dr.color,dr.width))
e.Graphics.DrawRectangle(pen,dr.rect);



$ / code $ / pre

现在我们可以更改任何我们的 DrawRectangles ,也许在另一个按钮点击:

  private void buttonChangeButton_Click对象发件人,EventArgs e)
{
矩形[3] .color = Color.Red;
矩形[6] .width = 7f;
drawPanel1.Invalidate();
}



更新:

上面的类很简单地展示了如何封装'矩形'类需要;它不是完美的!



这是一个缺陷:它并不十分关心传播责任的最佳方式。它把长方形的Burdon放在控件上,如果你有更复杂的绘图代码和更多的控件,每个控件都必须学习更复杂的代码。不是很好。相反责任应该留在Rectangle类中。该控件应该只告诉他们自己绘制..



这是一个更新的类,将会这样做。作为一个更复杂的绘图,它将能够绘制填充矩形以及..:

第2版

  public class DrawRectangle 
{
public Color color {get;组; }
public float width {get;组; }
public Color fillColor {get;组; }
public Rectangle rect {get;组; }
公共控制表面{get;组; }

public DrawRectangle(Rectangle r,Color c,float w,Color fill,Control ct)
{
color = c;
width = w;
fillColor = fill;
rect = r;
surface = ct;
}

public DrawRectangle(Rectangle r,Color c,float w,Control ct)
:this。 DrawRectangle(r,c,w,Color.Empty,ct){}

public override string ToString()
{
return rect.ToString()+(+ color.ToString()+
- + width.ToString(0.00)+);
}
$ b $ public void Draw(Graphics g)
{
if(fillColor!= Color.Empty)
using(SolidBrush brush = new SolidBrush fillColor))
g.FillRectangle(brush,rect);
if(color!= Color.Empty)
using(Pen pen = new Pen(color,width))g.DrawRectangle(pen,rect);
}
}

它使用第二种颜色来确定填充。 (我没有为 ToString 方法添加填充颜色。)它将颜色与特殊颜色值 Color.Empty 来确定应该绘制什么和不应该绘制什么。



创建新矩形的循环现在可以包含填充颜色。如果没有,将调用旧的构造函数,现在将填充颜色设置为 Color.Empty



以下是 Paint 事件得到的简单程度:

  private void drawPanel1_Paint(object sender,PaintEventArgs e)
{
foreach(DrawRectangle dr在矩形中)
if(dr.surface == sender)dr.Draw(e.Graphics);
}

要填充一些矩形,我们现在可以写出:

 矩形[2] .fillColor = Color.Fuchsia; 



除此之外:

注意颜色比较:不明显,颜色 Color.Empty 确实只是'透明黑'(0,0,0,0),颜色比较是特殊的 NamedColors 以及 KnownColors ,包括 Color.Empty 始终比较假与普通颜色。要进行真正的颜色比较,必须将其转换为正常颜色

  bool ok = Color.FromArgb(255,255,255,255)== Color.White; // false 
bool ok = Color.FromArgb(255,255,255 255)== Color.FromArgb(Color.White.ToArgb()); // true

因此,比较 Draw 代码是安全的。


I have write a c# class, which contains graphics inside. this is how I build the class and draw the rectangle. It works perfectly:

public Graphics shape;
public Rectangle rc;

// constructor
public CLASS_NAME(Graphics formGraphics)
{
    this.shape = formGraphics;
}

public void draw(int x, int y, int w, int h)
{
    SolidBrush myBrush = new SolidBrush(Color.Red);
    this.rc = new Rectangle(x, y, w, h);
    this.shape.FillRectangle(myBrush, rc);

    myBrush.Dispose();
}

then I wanted to add a new method to the object in order to change the color, but when I call this nothing happens:

public void change_color()
{
    SolidBrush myBrush = new SolidBrush(Color.Yellow);
    this.shapeFillRectangle(myBrush, rc);
    myBrush.Dispose();
}

I also tried: rc.Fill = but VS doesn't recognize rc.Fill as a valid method.

  • THE ERROR I GET IS: it says that in the change() method, this line: this.shapeFillRectangle(myBrush, rc); has a parameter that isn't valid.

解决方案

OK, let's start with a 'drawRectangle' class. It has enough data to create a simple Pen, holds a Rectangle and also a reference to the Control it will draw on.

I have added a ToString override, so we can display it with all its properties in, say a ListBox..

version 1

public class DrawRectangle
{
    public Color color { get; set; }
    public float width { get; set; }
    public Rectangle rect { get; set; }
    public Control surface { get; set; }

    public DrawRectangle(Rectangle r, Color c, float w, Control ct)
    {
        color = c;
        width = w;
        rect = r;
        surface = ct;
    }

    public override string ToString()
    {
        return rect.ToString() + " (" + color.ToString() + 
               " - " + width.ToString("0.00") + ") on " + surface.Name;
    }
}

Next we need a list of those rectangles:

public List<DrawRectangle> rectangles = new List<DrawRectangle>();

Now let's add them in a loop in a button click:

private void buttonAddLoop_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 10; i++)
        rectangles.Add(new DrawRectangle(new Rectangle(i * 30, i * 30, 22, 22), 
                                            Color.Black, 3.5f, drawPanel1));
    drawPanel1.Invalidate();
}

Note how I invalidate the control I want them painted on by Invalidating it! (You can use the Form as well, as Form inherits from Control..)

For this to work we need to code the Paint event of each control that needs to paint some of the rectangles; I use only a Panel drawPanel1:

private void drawPanel1_Paint(object sender, PaintEventArgs e)
{
    foreach (DrawRectangle dr in rectangles)
    {
        if (dr.surface == sender)
        {
            using (Pen pen = new Pen(dr.color, dr.width))
                e.Graphics.DrawRectangle(pen, dr.rect);
        }
    }
}

Now we can change any of our DrawRectangles, maybe in another button click:

private void buttonChangeButton_Click(object sender, EventArgs e)
{
    rectangles[3].color = Color.Red;
    rectangles[6].width = 7f;
    drawPanel1.Invalidate();
}

Update:

The above class was a simple start to show how to encapsulate the things a 'Rectangle' class would need; it was not meant to be perfect!

Here is one flaw it has: It doesn't really care enough about the best way to spread responsibilities. It put the burdon of drawing the rectangles on the controls and if you have more complex drawing code and more controls each of them would have to learn the more complex code. This is not good. Instead the responsibility should stay with the Rectangle class. The control should only tell them to draw themselves..

Here is an updated class that will do just that. As a more complex drawing it will be able to draw filled rectangles as well..:

version 2

public class DrawRectangle
{
    public Color color { get; set; }
    public float width { get; set; }
    public Color fillColor { get; set; }
    public Rectangle rect { get; set; }
    public Control surface { get; set; }

    public DrawRectangle(Rectangle r, Color c, float w, Color fill, Control ct  )
    {
        color = c;
        width = w;
        fillColor = fill;
        rect = r;
        surface = ct;
    }

    public DrawRectangle(Rectangle r, Color c, float w,  Control ct) 
    : this. DrawRectangle(r, c, w, Color.Empty, ct)  {}

    public override string ToString()
    {
        return rect.ToString() + " (" + color.ToString() + 
               " - " + width.ToString("0.00") + ")";
    }

    public void Draw(Graphics g)
    {
        if (fillColor != Color.Empty) 
            using (SolidBrush brush = new SolidBrush(fillColor))
                 g.FillRectangle(brush, rect);
        if (color != Color.Empty)
            using (Pen pen = new Pen(color, width)) g.DrawRectangle(pen, rect);
    }
}

It uses a second color to determine the filling. (I didn't add the fill color the the ToString method.) It compares the color with the special color values Color.Empty to determine what should and shouldn't be drawn.

The loop to create the new rectangles may now include the fill color. If it doesn't, the old constructor will be called, which now sets the fill color to Color.Empty.

Here is how simple the Paint event gets:

private void drawPanel1_Paint(object sender, PaintEventArgs e)
{
    foreach (DrawRectangle dr in rectangles)
        if (dr.surface == sender) dr.Draw(e.Graphics);
}

To fill some rectangle we can now write:

rectangles[2].fillColor = Color.Fuchsia;

Aside:

A note an color comparison: It is not obvious, but while the color Color.Empty really is just 'transparent black' (0,0,0,0), color comparison is special: NamedColors as well as KnownColors, including Color.Empty always compare false to normal colors. To make a true color comparison one would have to cast to a 'normal' Color:

bool ok=Color.FromArgb(255,255,255,255) == Color.White;  // false
bool ok=Color.FromArgb(255,255,255 255) == Color.FromArgb(Color.White.ToArgb()); // true

Therefore the comparison in the Draw code is safe.

这篇关于动态改变图形矩形的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆