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

为什么在Paint事件中绘制的是小正方形而非圆形?

问题原因排查

1. 缩放因子计算方向完全颠倒

你当前的缩放因子用图像尺寸 / 控件尺寸计算,这会导致椭圆尺寸被错误缩小(当图像比控件大时),甚至因整数截断变成极小的正方形。正确逻辑应该是将图像坐标转换为控件显示坐标,缩放因子应为控件尺寸 / 图像尺寸:

// 修正后的缩放因子计算
double xFactor = (double)pictureBoxPoints.Width / bitmap.Width;
double yFactor = (double)pictureBoxPoints.Height / bitmap.Height;

2. 未适配PictureBox的SizeMode

如果SizeMode设为Zoom或CenterImage,图像会在控件内居中,存在空白偏移;若设为StretchImage,PictureBox会自动对Paint事件的Graphics应用拉伸变换,手动二次缩放会导致圆形被拉伸变形。

  • 针对Zoom模式,需先计算图像显示偏移量,再调整椭圆坐标:
    int offsetX = (pictureBoxPoints.Width - (int)(bitmap.Width * scaleFactor)) / 2;
    int offsetY = (pictureBoxPoints.Height - (int)(bitmap.Height * scaleFactor)) / 2;
    int ellipseX = offsetX + (int)(point.X * scaleFactor) - ellipseSize / 2;
    int ellipseY = offsetY + (int)(point.Y * scaleFactor) - ellipseSize / 2;
    
    此时scaleFactor应取Math.Min(xFactor, yFactor)(Zoom模式按最小比例保持图像比例)。

3. 整数截断导致尺寸失真

直接用(int)强制转换会截断小数部分,导致椭圆宽高虽代码中一致,但实际显示因误差变成近似正方形。建议用Math.Round取整后再转换:

int ellipseSize = (int)Math.Round(5 * scaleFactor);
int ellipseX = (int)Math.Round(point.X * scaleFactor) - ellipseSize / 2;
int ellipseY = (int)Math.Round(point.Y * scaleFactor) - ellipseSize / 2;

4. 可选优化:开启图形平滑模式

虽不影响形状,但开启后椭圆边缘更圆润,避免锯齿:

e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
修正后的完整代码示例
private void PictureBoxPoints_Paint(object sender, PaintEventArgs e)
{
    if (pictureBoxPoints.Image != null)
    {
        Bitmap bitmap = pictureBoxPoints.Image as Bitmap;
        double xFactor = (double)pictureBoxPoints.Width / bitmap.Width;
        double yFactor = (double)pictureBoxPoints.Height / bitmap.Height;
        double scaleFactor = 1;
        int offsetX = 0;
        int offsetY = 0;

        // 根据SizeMode调整参数
        if (pictureBoxPoints.SizeMode == PictureBoxSizeMode.Zoom)
        {
            scaleFactor = Math.Min(xFactor, yFactor);
            offsetX = (pictureBoxPoints.Width - (int)(bitmap.Width * scaleFactor)) / 2;
            offsetY = (pictureBoxPoints.Height - (int)(bitmap.Height * scaleFactor)) / 2;
        }
        else if (pictureBoxPoints.SizeMode == PictureBoxSizeMode.StretchImage)
        {
            scaleFactor = 1;
            xFactor = yFactor = 1;
        }

        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        foreach (System.Drawing.Point point in _dotPoints)
        {
            int ellipseSize = (int)Math.Round(5 * scaleFactor);
            int ellipseX = offsetX + (int)Math.Round(point.X * xFactor) - ellipseSize / 2;
            int ellipseY = offsetY + (int)Math.Round(point.Y * yFactor) - ellipseSize / 2;

            e.Graphics.FillEllipse(Brushes.Red, new Rectangle(ellipseX, ellipseY, ellipseSize, ellipseSize));
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:23:26