You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Visual Studio中C#跨窗体调用绘制圆形不显示及传参问题

解决从Form1调用Form2绘制圆形并传参的问题

嘿,我来帮你搞定这个跨窗体绘制圆形的问题!你的代码里已经触发了绘制方法,但看不到图形其实是两个核心问题导致的:

  • CreateGraphics()创建的是临时的绘图对象,只要窗体一刷新(比如最小化再还原、拖动窗口),画的东西就没了;而且如果Form2还没显示出来,这个绘图对象对应的是不可见的窗体,自然看不到图形。
  • 直接调用方法绘制没有和窗体的绘制生命周期绑定,没法保证图形一直显示。

下面给你一套靠谱的实现方案:

第一步:重构Form2,让绘制逻辑和窗体生命周期绑定

我们把需要绘制的参数(比如圆心位置、半径)存在Form2的字段里,然后借助窗体的Paint事件来完成绘制——这个事件是窗体系统自动触发的,只要窗体需要渲染,就会执行绘制逻辑,这样画的圆形就不会消失了:

public partial class Form2 : Form
{
    // 用来存绘制圆形的参数,你可以根据需求调整
    public int CircleCenterX { get; set; }
    public int CircleCenterY { get; set; }
    public int CircleSize { get; set; } // 这里用一个值代表宽高,画正圆形
    public Pen DrawPen { get; set; } = new Pen(Color.Blue, 3);

    public Form2()
    {
        InitializeComponent();
        // 把Paint事件绑定到我们的绘制方法
        this.Paint += DrawCircleOnPaint;
    }

    private void DrawCircleOnPaint(object sender, PaintEventArgs e)
    {
        // 只有参数有效时才绘制,避免初始无参数时画空图形
        if (CircleSize > 0)
        {
            // 计算圆形的左上角坐标,这样圆心才会在设置的(CircleCenterX, CircleCenterY)位置
            int left = CircleCenterX - CircleSize / 2;
            int top = CircleCenterY - CircleSize / 2;
            e.Graphics.DrawEllipse(DrawPen, left, top, CircleSize, CircleSize);
        }
    }
}

第二步:在Form1中传参并显示Form2

现在Form1只需要创建Form2实例,把绘制参数传进去,然后显示Form2就行——显示的时候会自动触发Paint事件,完成圆形绘制:

// Form1里的调用代码,比如放在按钮点击事件里
private void btnOpenForm2_Click(object sender, EventArgs e)
{
    Form2 circleForm = new Form2();
    // 传递参数:圆心在(150,150),直径80(也就是半径40)
    circleForm.CircleCenterX = 150;
    circleForm.CircleCenterY = 150;
    circleForm.CircleSize = 80;
    // 要是想换画笔样式也直接改就行
    // circleForm.DrawPen = new Pen(Color.Red, 5);
    circleForm.Show(); // 显示Form2,此时自动触发绘制
}

可选:Form2显示后动态修改圆形

如果想在Form2已经打开的情况下,从Form1修改圆形的位置或大小,可以给Form2加个方法,修改参数后触发重绘:

// 在Form2里加这个方法
public void RefreshCircle(int newX, int newY, int newSize)
{
    CircleCenterX = newX;
    CircleCenterY = newY;
    CircleSize = newSize;
    // 调用Invalidate()告诉窗体需要重绘,会自动触发Paint事件
    this.Invalidate();
}

然后Form1里要保留Form2的实例引用(不能是局部变量),这样就能随时调用修改:

// 把Form2实例声明为Form1的字段
private Form2 _openedCircleForm;

// 打开Form2的方法
private void btnOpenForm2_Click(object sender, EventArgs e)
{
    _openedCircleForm = new Form2();
    _openedCircleForm.CircleCenterX = 150;
    _openedCircleForm.CircleCenterY = 150;
    _openedCircleForm.CircleSize = 80;
    _openedCircleForm.Show();
}

// 修改圆形的按钮事件
private void btnUpdateCircle_Click(object sender, EventArgs e)
{
    // 先判断Form2还没被关闭
    if (_openedCircleForm != null && !_openedCircleForm.IsDisposed)
    {
        // 改成圆心(250,250),直径100
        _openedCircleForm.RefreshCircle(250, 250, 100);
    }
}

最后再划个重点

  • 绝对不要用CreateGraphics()做持久化绘制,它只适合临时的绘图需求(比如拖拽时的临时线条)。
  • 所有需要一直显示的图形,都要放在窗体的Paint事件里绘制,这是WinForms绘制的标准做法。
  • 通过属性或方法传递参数,让绘制逻辑基于这些参数执行,这样就能轻松实现跨窗体传参绘制啦!

内容的提问来源于stack exchange,提问作者ritu2306

火山引擎 最新活动