You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm中如何为Panel内GDI+绘制的多边形设置独立颜色

问题:给Panel上绘制的自定义多边形设置填充色

参考图示:图中多边形需要设置为其他颜色
我是编程新手,过去数周学习进展顺利,目前编写了一款用于计算 second moment of area(面积二次矩) 的应用程序,支持用户选择顶点定义n边多边形,顶点及多边形会绘制在Panel控件上。出于美观性考虑,我希望将多边形设置为与面板背景不同的颜色,咨询可行实现方案。

代码上下文说明:vecPolygons 存储了一个或多个Polygon对象及其关联的顶点坐标

原有代码片段如下:

public void AppendNewPolygon()
{
    double[][,] vecTemp;
    vecTemp = vecPolygons;                         
    
    int i;
    vecPolygons = new double[vecTemp.Length + 1][,];     
    
    for( i=0; i< vecTemp.Length; i++)                   
    {
        vecPolygons[i] = vecTemp[i];
    }
    vecPolygons[vecTemp.Length] = new double[0, 2];         

}
public void AppendNewPointBefore()
{
    double[,] arrTemp;
    int i;

    if (vecPolygons.GetLength(0) > 0) 
    {
        arrTemp = vecPolygons[activePolygon];

        vecPolygons[activePolygon] = new double[arrTemp.GetLength(0) + 1, 2];


        for (i = 0; i < activePoint; i++)
        {
            vecPolygons[activePolygon][i, 0] = arrTemp[i, 0];
            vecPolygons[activePolygon][i, 1] = arrTemp[i, 1];
        }

        vecPolygons[activePolygon][activePoint, 0] = 0;
        vecPolygons[activePolygon][activePoint, 1] = 0;


        for (i = activePoint; i < arrTemp.GetLength(0); i++)
        {
            vecPolygons[activePolygon][i + 1, 0] = arrTemp[i, 0];
            vecPolygons[activePolygon][i + 1, 1] = arrTemp[i, 1];
        }
    } 
}

名为pGraphic的Panel控件的Paint事件处理代码如下:

private void pGraphic_Paint(object sender, PaintEventArgs e)
{
    pgr.DrawPolygons( flm.vecPolygons, pGraphic);
}     

点击按钮bViewA时会触发面板更新,对应逻辑如下:

private void bViewA_Click(object sender, EventArgs e)
{
    double yMin, yMax, zMin, zMax;
    flm.GetModelExtens(out yMin, out yMax, out zMin, out zMax);
    pgr.SetParametersForViewAll(pGraphic, yMin, yMax, zMin, zMax);

    pGraphic.Invalidate();
}

上述点击事件会调用两个方法,第一个是GetModelExtens:

public void GetModelExtens(out double ymin,out double ymax,out double zmin,out double zmax)
{
    ymin = double.MaxValue;
    ymax = -double.MaxValue;
    zmax = -double.MaxValue;
    zmin = double.MaxValue;

    for (int i = 0; i < vecPolygons.Length; i++)
    {
        for (int j = 0; j < vecPolygons[i].GetLength(0); j++)
        {
            
                if (vecPolygons[i][j, 0] < ymin)
                    ymin = vecPolygons[i][j, 0];
                if (vecPolygons[i][j, 1] < zmin)
                    zmin = vecPolygons[i][j, 1];
                if (vecPolygons[i][j, 0]  >ymax)
                    ymax = vecPolygons[i][j, 0];
                if (vecPolygons[i][j, 1] > zmax)
                    zmax = vecPolygons[i][j, 1];
            
        }
    }
}

第二个是SetParametersForViewAll,其所属的PolygonGraphics类定义如下:

public class PolygonGraphics
{
    double centerX, centerY, scale;
    public PolygonGraphics()
    {
        centerX = 0.0;
        centerY = 0.0;
        scale = 1.0;
    }
    public void SetParametersForViewAll ( Panel pGraphic ,double yMin, double yMax, double zMin, double zMax)
    {
        double scaleVert, scaleHorz;
        
        scaleVert = pGraphic.Width/ (yMax-yMin);
        scaleHorz = pGraphic.Height/ (zMax-zMin);

        scale = scaleHorz;
        if (scale > scaleVert)
        { 
            scale = scaleVert;
        }
        scale = scale * 0.9;
        centerX = -yMin * scale + (pGraphic.Width-(yMax-yMin)*scale)* 0.5;
        centerY =  zMax * scale + (pGraphic.Height - (zMax - zMin) * scale) * 0.5;
       
        
    }
}

调用Invalidate方法触发面板重绘后,pGraphic_Paint事件会调用DrawPolygons方法执行实际绘制,该方法代码如下:

public void DrawPolygons(double[][,] vecPolygons, Panel panel)
{
    Graphics gr;
    Pen pn = new Pen(Color.Black, 1);
    

    gr = panel.CreateGraphics();
    gr.Clear(panel.BackColor);

    double xpx1, ypx1, xpx2, ypx2, ymm1, ymm2, zmm1, zmm2;

    int iLine, iPolygon, index2;

    for (iPolygon = 0; iPolygon < vecPolygons.GetLength(0); iPolygon++)
    {
        for (iLine = 0; iLine < vecPolygons[iPolygon].GetLength(0); iLine++)
        {
            index2 = (iLine + 1) % vecPolygons[iPolygon].GetLength(0);
            ymm1 = vecPolygons[iPolygon][iLine, 0];
            zmm1 = vecPolygons[iPolygon][iLine, 1];

            ymm2 = vecPolygons[iPolygon][index2, 0];
            zmm2 = vecPolygons[iPolygon][index2, 1];

            xpx1 = scale * ymm1 + centerX;
            ypx1 = -scale * zmm1 + centerY;

            xpx2 = scale * ymm2 + centerX;
            ypx2 = -scale * zmm2 + centerY;
           
            gr.DrawLine(
                pn,
                (float)xpx1,
                (float)ypx1,
                (float)xpx2,
                (float)ypx2);


        }
    }
    
}

解决方案

你当前的代码只逐段绘制了多边形的黑色边框,没有调用填充API,同时使用CreateGraphics获取画布的写法存在绘制内容不持久的问题,按以下步骤修改即可实现自定义多边形颜色:

  • 修改Paint事件调用逻辑:不要自行创建Graphics对象,直接使用Paint事件传入的画布对象,避免重绘时内容丢失:
    private void pGraphic_Paint(object sender, PaintEventArgs e)
    {
        pgr.DrawPolygons(flm.vecPolygons, e.Graphics);
    }
    
  • 重写DrawPolygons方法:先将每个多边形的所有顶点转换为屏幕坐标点数组,调用FillPolygon填充内部颜色,再绘制边框,代码如下:
    public void DrawPolygons(double[][,] vecPolygons, Graphics gr)
    {
        gr.Clear(pGraphic.BackColor);
        // 自定义边框颜色、填充色,替换成和面板背景不同的颜色即可
        using Pen borderPen = new Pen(Color.Black, 1);
        using Brush fillBrush = new SolidBrush(Color.LightSteelBlue);
    
        for (int iPolygon = 0; iPolygon < vecPolygons.GetLength(0); iPolygon++)
        {
            int pointCount = vecPolygons[iPolygon].GetLength(0);
            if (pointCount < 3) continue; // 少于3个点无法构成封闭多边形,跳过
            
            PointF[] polygonPoints = new PointF[pointCount];
            for (int i = 0; i < pointCount; i++)
            {
                double ymm = vecPolygons[iPolygon][i, 0];
                double zmm = vecPolygons[iPolygon][i, 1];
                float x = (float)(scale * ymm + centerX);
                float y = (float)(-scale * zmm + centerY);
                polygonPoints[i] = new PointF(x, y);
            }
            // 先填充再描边,避免边框被填充层覆盖
            gr.FillPolygon(fillBrush, polygonPoints);
            gr.DrawPolygon(borderPen, polygonPoints);
        }
    }
    

原有视口计算、顶点增删、全览按钮的逻辑不需要改动,重绘时会自动应用填充效果。如果需要给不同多边形设置不同颜色,只要在循环绘制每个多边形时传入对应颜色的画刷即可。


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:51:36