【问题标题】:Can't paint 2 of the same control on winForm无法在 winForm 上绘制 2 个相同的控件
【发布时间】:2013-03-30 23:06:55
【问题描述】:

我正在用 winform (tic-tac-toe) 制作一个简单的游戏,但在绘制块控制时遇到了一些问题。

这是我制作的类,代表游戏中的一个方块(没有游戏逻辑,只有 UI)。

public class UI_Block : Control
{
    private Rectangle block;
    private SIGNS sign;
    public  SIGNS Sign 
    {
        get {return sign;}
        set
        {
            if (sign == SIGNS.EMPTY)
                sign = value;
        } 
    }

    public UI_Block( ) {
        sign = SIGNS.EMPTY;
    }

    public void SetBlockOnBoard(int x, int y)
    {
        this.Location = new Point( x , y );
        this.Size = new Size(Parent.Width /3, Parent.Height / 3);

        block = new Rectangle(this.Location, this.Size);
    }

    public void DrawSign(Graphics g)
    {
        Pen myPen = new Pen(Color.Red);

        if (sign == SIGNS.O)
        {
            drawO(g,new Pen(Brushes.Black));
        }

        if (sign == SIGNS.X)
        {
            drawX(g, new Pen(Brushes.Red));
        }

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        DrawSign(e.Graphics);
        base.OnPaint(e);
    }

    //Draw X
    private void drawX(Graphics g, Pen myPen)
    {
        //draw first daignol
        Point daignolStart = new Point {  X = this.Location.X  ,  Y = this.Location.Y   };
        Point daignolEnd = new Point   {  X = this.Size.Width  ,  Y = this.Size.Height  };

        g.DrawLine(myPen, daignolStart, daignolEnd);

        //draw second daignol
        daignolStart = new Point {  X = Size.Width ,  Y = this.Location.Y  };
        daignolEnd = new Point   {  X = Location.X,   Y = Size.Height      };

        g.DrawLine(myPen, daignolEnd, daignolStart);
    }


    //Draw O
    private void drawO(Graphics g, Pen myPen)
    {
        g.DrawEllipse(myPen, block);
    }

}

我将它们都添加到 winForm 类中,并查看绘制它们时的样子:

public partial class Form1 : Form
{
    UI.UI_Block block;
    UI.UI_Block blockX;

    public Form1()
    {
        InitializeComponent();

        block = new UI.UI_Block();
        blockX = new UI.UI_Block();
        Controls.Add(block);
        Controls.Add(blockX);

    }

    protected override void OnLoad(EventArgs e)
    {
        block. SetBlockOnBoard(0, 0);
        blockX.SetBlockOnBoard(0, block.Height);

        block.Sign = SIGNS.X;
        blockX.Sign = SIGNS.O;

        base.OnLoad(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        //block.DrawSign(e.Graphics);
        //block.DrawSign(e.Graphics);
        base.OnPaint(e);
    }

}

我尝试了一些方法,例如不使用 onPaint 事件,但我仍然得到相同的结果。

这是我运行它时看到的:

知道为什么我不能同时画它们吗?

【问题讨论】:

  • 你在哪里调用绘图方法?我所看到的只是你放下障碍。最好将其放在 setSign 属性中。
  • 我将这两个块都添加到了 winForm 控件,因此每次我重新绘制表单时都会调用 OnPaints 方法(form.Invalidate)。我应该用不同的方式做吗?
  • 单步执行您的代码并查看添加第二个控件时它是否正在调用 OnPaint。您可能必须将表单中的Graphics 作为参数添加到 UI_Block 构造函数。由于这个原因,我没有对 Paint 做太多事情。你可以只设置图标,还是必须使用画图?
  • 我在 OnPaint 中添加了一个 MassageBox(this.Sign +""),它们都像 i thogut 一样被调用。我尝试在两个对象上使用表单中的 Graphic 对象(并禁用 OnPaint),但我看到了相同的结果。图标是什么意思,图片是什么意思?
  • 是的。将图像添加到项目的资源中,并在设置Sign 时,使用它来设置要在 UI_Block 上显示的图像。

标签: c# winforms user-interface


【解决方案1】:

您没有在其可见区域中绘制控件的内容,因此它绘制得很好但您看不到它。

每个控件都有它自己的坐标空间(客户端坐标),它从 0,0 开始,不管它在父控件中的位置。您通过设置它的位置正确地将控件放置在它的父级中,但是您还使用位置来偏移图形,因此它们基本上偏移了两次。

(如果您将控件放大,您将能够看到 X 在屏幕下方被绘制得更远)

要解决此问题,请在控件的客户端坐标空间中进行所有绘制,即在区域(0、0、宽度、高度)中绘制

(P.S. 您可以在父控件中绘制所有 9 个图块,这比创建 9 个子控件更有效。但是您所做的将正常工作)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多