动态改变图形矩形的颜色

Change color of graphic rectangle dynamically

我写了一个c#class,里面有图形。 这就是我构建 class 并绘制矩形的方式。它完美运行:

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

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

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

我也试过:rc.Fill = 但是 VS 不承认 rc.Fill 是一个有效的方法。

好的,让我们从'drawRectangle' class开始。它有足够的数据来创建一个简单的 Pen,包含一个 Rectangle 以及对它将使用的 Control 的引用。

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

版本 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;
    }
}

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

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

注意我是如何使我想让它们画在 Invalidating 上的控件无效的! (您也可以使用 Form,因为 Form 继承自 Control..)

为此,我们需要为每个需要绘制一些矩形的控件编写 Paint 事件;我只使用 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);
        }
    }
}

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

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

更新:

上面的 class 是一个简单的开始,展示了如何封装 'Rectangle' class 需要的东西;它并不意味着完美!

这是它的一个缺陷:它不太关心分散 责任 的最佳方式。它把绘制矩形的负担放在控件上,如果您有更复杂的绘图代码和更多控件,则每个控件都必须学习更复杂的代码。这个不好。相反,责任应该由矩形 class 承担。控件应该只告诉他们自己画..

这是一个更新的 class 可以做到这一点。作为一个更复杂的绘图,它也可以绘制填充的矩形..:[=​​43=]

版本 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);
    }
}

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

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

Paint 事件变得如此简单:

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

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

rectangles[2].fillColor = Color.Fuchsia;

旁白:

注意一个颜色比较:它并不明显,但是颜色Color.Empty确实只是'transparent black' (0,0,0, 0),颜色比较特殊:NamedColors以及KnownColors,包括Color.Empty总是比较假 到正常颜色。要进行真实的颜色比较,必须转换为 '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

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