【问题标题】:Arc graphic quality圆弧图形质量
【发布时间】:2019-01-08 23:25:43
【问题描述】:

回到这里。有什么办法可以提高Arc的质量吗?
我正在使用e.Graphics.SmoothingMode = SmoothingMode.AntiAlias

这是创建弧的一段代码:

using (GraphicsPath gp = new GraphicsPath())
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    gp.Reset();
    gp.AddPie(_OuterRectangle, (float)_Properties.Origin, (float)_Properties.GaugeType);
    gp.Reverse();

    gp.AddPie(_InnerRectangle, (float)_Properties.Origin, (float)_Properties.GaugeType);
    gp.Reverse();
    pArea.SetClip(gp);

    using (Pen oPen = new Pen(this.ForeColor, 2f))
    {
       e.Graphics.DrawPath(oPen, gp);
    }
    e.Graphics.SetClip(ClientRectangle);
}

提前致谢。

编辑:
我已经按照 LarsTech 的建议做了,现在质量很完美,但我没有我需要的数字:

  • OuterRectangle:是 ClientRectangle 区域,我正在对其进行操作以使 Width 和 Height 长度相同;
  • InnerRectangle:是 OuterRectangle 的 ClientRectangle 面积的 2/3;
  • Properties.Origin:是弧开始的角度。我将它作为基点放在枚举器中,其中北为 270,东为 0,
    所以。如上图,为西南,135度;

  • Properties.GaugeType:是另一个枚举器,表示 if is Complete = 360、Half = 180、Quarter = 90,因此我可以确定扫描角度。如果数字是 ThreeQuarter,270 度。

【问题讨论】:

  • 看起来您正在使用该图形路径进行剪辑。不能像这样剪辑区域,但仍然有抗锯齿工作。
  • 不用剪裁,你可以只使用_InnerRectangle,将其膨胀(-1,-1)并用画布的背景颜色填充(e.Graphics.FillEllipse())。这将在不影响抗锯齿(并避免进一步计算)的情况下消除饼线。
  • 如果您指的是我的评论(LarsTech 没有提到_InnerRectangle),我的意思是您可以在此处的代码中使用它来填充由AddPie 设计的弧并删除AddPie 正在生成的行:_InnerRectangle.Inflate(-1, -1); e.Graphics.FillEllipse([Brush from canvas.backcolor], _InnerRectangle);。然后,如果您出于其他原因想在其他地方使用它,那就无关紧要了。
  • @Jimi 我重新打开了这个问题(不太同意重复的问题),所以如果您想将其作为答案发布,请继续。
  • 由于问题被重新打开,我可以在此处发布该代码示例。它实际上并不是一个答案,但如果您认为它 适合 ,我会将其移至此处。

标签: c# winforms graphics graphicspath


【解决方案1】:

问题
剪切当前 Graphics 的区域时(Graphics.SetClip 方法),生成的绘图质量会下降,因为 Graphics.SmoothingMode = SmoothingMode.AntiAlias 生成的抗锯齿效果会丢失。

一种可能的解决方案是避免剪裁由用于设计弧的GraphicsPath 定义的区域(GraphicsPath.AddPie 方法);然而,这会使饼的线条可见,从而影响形状。

另一种解决方案是使用 Canvas 的背景颜色在弧的中心绘制一个省略号。由于弧线是使用两个矩形绘制的,我们可以使用内部矩形,根据需要对其进行膨胀(Rectangle.Inflate 方法)(通常是用于 ouline 的 Pen 大小的一小部分 - Pen.Width / 2 -)。

这允许删除由GraphicsPath 形状生成的工件并在形状的中心绘制一些其他图形内容。

例如,使用不同的画笔:

  LinearGradientBrush           HatchBrush               TextureBrush

当然还有其他方法可以达到相同的效果。我们可以使用GraphicsPath.AddArc 方法绘制弧线,提取或计算弧线的第一个点和最后一个点,并使用它们绘制两条线(GraphicsPath.AddLine)来闭合图形。

但是,由于我们要在圆弧的中心绘制不同的图形对象,这些对象无论如何都会覆盖中心区域。

如何使用此代码

  • 在表单中,添加一个 TrackBar(此处名为 tbarSpeed
  • 添加一个 PictureBox(名为 Canvas),大小为 (200, 200)
  • 连接 TrackBar tbarSpeed_Scroll 事件和 Panel Canvas_Paint 事件。

using System.Drawing;
using System.Drawing.Drawing2D;


float GaugeValue = 88.0f;
float GaugeSweepAngle = 270.0f;
float GaugeStartAngle = 135.0F;

private void Canvas_Paint(object sender, PaintEventArgs e)
{
    var canvas = sender as Control;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    var outerRectangle = new Rectangle(10, 10, 180, 180);
    var innerRectangle = new Rectangle(30, 30, 140, 140);
    var blendRectangle = new Rectangle(10, 10, 180, 160);
    var innerCenter = new PointF(outerRectangle.Left + (outerRectangle.Width / 2),
                                    outerRectangle.Top + (outerRectangle.Height / 2));
    float gaugeLength = (outerRectangle.Width / 2) - 2;

    using (var path = new GraphicsPath())
    {
        path.AddPie(outerRectangle, GaugeStartAngle, GaugeSweepAngle);
        path.AddPie(innerRectangle, GaugeStartAngle, GaugeSweepAngle);
        innerRectangle.Inflate(-1, -1);

        using (var pen = new Pen(Color.White, 3f))
        using (var backgroundbrush = new SolidBrush(canvas.BackColor))
        using (var gradientBrush = new LinearGradientBrush(blendRectangle,
               Color.Green, Color.Red, LinearGradientMode.ForwardDiagonal))
        {
            var blend = new Blend()
            {
                Factors = new[] { 0.0f, 0.0f, 0.1f, 0.3f, 0.7f, 1.0f },
                Positions = new[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f }
            };

            gradientBrush.Blend = blend;
            e.Graphics.FillPath(gradientBrush, path);
            e.Graphics.DrawPath(pen, path);

            e.Graphics.FillEllipse(backgroundbrush, innerRectangle);

            using (var format = new StringFormat())
            {
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
                innerRectangle.Location = new Point(innerRectangle.X, innerRectangle.Y + canvas.Font.Height);
                e.Graphics.DrawString(GaugeValue.ToString() + "%", canvas.Font, Brushes.White, innerRectangle, format);
            }

            using (var mx = new Matrix())
            {
                mx.RotateAt(GaugeStartAngle + 90 + (GaugeValue * (GaugeSweepAngle / 100)), innerCenter);
                e.Graphics.Transform = mx;
                e.Graphics.DrawLine(pen, innerCenter, new PointF(innerCenter.X, innerCenter.Y - gaugeLength));
                e.Graphics.ResetTransform();
            }
        }
    }
}

private void tbarSpeed_Scroll(object sender, EventArgs e)
{
    GaugeValue = tbarSpeed.Value;
    Canvas.Invalidate();
}

Sample code on PasteBin

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-15
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 2014-05-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多