【问题标题】:Fill path not filling entire graphics path?填充路径不填充整个图形路径?
【发布时间】:2019-07-06 08:57:04
【问题描述】:

试图填满那个中心区域,不知道我做错了什么。

Imports System.Drawing.Drawing2D

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Form1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Dim gp As GraphicsPath = CreatePath(New Rectangle(New Point(200, 200), New Size(250, 100)))
        e.Graphics.FillPath(New SolidBrush(Color.LightBlue), gp)
        e.Graphics.DrawPath(New Pen(Color.Black), gp)

    End Sub

    Private Function CreatePath(ByVal area As Rectangle) As GraphicsPath

        Dim gp As New GraphicsPath()
        Dim rect As Rectangle = New Rectangle(area.Location, New Size(area.Width, area.Height \ 3))
        gp.AddEllipse(rect)

        Dim hadj As Integer = area.Height \ 4
        gp.AddLine(New Point(area.X, area.Y + area.Height - hadj), New Point(area.X, area.Y + (rect.Height \ 3) + 8))

        Dim gh As Integer = area.Width \ 4
        Dim pts(4) As PointF
        pts(0) = New PointF(area.X, area.Y + area.Height - hadj)
        pts(1) = New Point(area.X + gh, area.Y + area.Height - (hadj \ 2))
        pts(2) = New Point(area.X + gh * 2, area.Y + area.Height - (hadj \ 3))
        pts(3) = New Point(area.X + gh * 3, area.Y + area.Height - (hadj \ 2))
        pts(4) = New Point(area.X + area.Width, area.Y + area.Height - hadj)
        gp.AddCurve(pts)

        gp.AddLine(New PointF(area.X + area.Width, area.Y + (rect.Height \ 3) + 9), New PointF(area.X + area.Width, area.Y + area.Height - hadj))
        Return gp
    End Function
End Class

【问题讨论】:

    标签: vb.net winforms graphics gdi+ drawing2d


    【解决方案1】:

    试试下面的。默认情况下,GraphicsPath 使用交替填充模式,交替添加/减去填充。缠绕填充模式使用方向从填充中增加(顺时针)或减少(逆时针)。

    Private Function CreatePath(ByVal area As Rectangle) As GraphicsPath
        '* Set fill mode to winding (see FillMode Help)
        Dim gp As New GraphicsPath(FillMode.Winding)
    
        Dim rect As Rectangle = New Rectangle(area.Location, New Size(area.Width, area.Height \ 3))
        gp.AddEllipse(rect)
    
        '* Reorder points so that path goes clockwise (see FillMode.Winding Help)
    
        Dim hadj As Integer = area.Height \ 4
        'Left side bottom -> top
        'gp.AddLine(New Point(area.X, area.Y + area.Height - hadj), New Point(area.X, area.Y + (rect.Height \ 3) + 8))
    
        '* Right side top -> bottom (clockwise)
        '* NOTE: Top Y value was a bit too high, adjusted by -3.  Adjust calculation or maybe use floating point math and used rounding, ceil, or floor
        gp.AddLine(New PointF(area.X + area.Width, area.Y + (rect.Height \ 3) + 9 - 3), New PointF(area.X + area.Width, area.Y + area.Height - hadj))
    
        Dim gh As Integer = area.Width \ 4
        Dim pts(4) As PointF
        'pts(0) = New PointF(area.X, area.Y + area.Height - hadj)
        'pts(1) = New Point(area.X + gh, area.Y + area.Height - (hadj \ 2))
        'pts(2) = New Point(area.X + gh * 2, area.Y + area.Height - (hadj \ 3))
        'pts(3) = New Point(area.X + gh * 3, area.Y + area.Height - (hadj \ 2))
        'pts(4) = New Point(area.X + area.Width, area.Y + area.Height - hadj)
        '* Reordered points (clockwise)
        pts(0) = New Point(area.X + area.Width, area.Y + area.Height - hadj)
        pts(1) = New Point(area.X + gh * 3, area.Y + area.Height - (hadj \ 2))
        pts(2) = New Point(area.X + gh * 2, area.Y + area.Height - (hadj \ 3))
        pts(3) = New Point(area.X + gh, area.Y + area.Height - (hadj \ 2))
        pts(4) = New PointF(area.X, area.Y + area.Height - hadj)
        gp.AddCurve(pts)
    
        'Right side top -> bottom
        'gp.AddLine(New PointF(area.X + area.Width, area.Y + (rect.Height \ 3) + 9), New PointF(area.X + area.Width, area.Y + area.Height - hadj))
    
        '* Left side bottom -> top (clockwise)
        '* NOTE: Top Y value was a bit too high, adjusted by -2.  Adjust calculation or maybe use floating point math and used rounding, ceil, or floor
        gp.AddLine(New Point(area.X, area.Y + area.Height - hadj), New Point(area.X, area.Y + (rect.Height \ 3) + 8 - 2))
    
        Return gp
    End Function
    

    【讨论】:

      【解决方案2】:

      另一种方法,只是为了展示GraphicsPath对象的Reset()方法。
      由于圆柱体可以看作是两个省略号和一个矩形的组合(透视创建了 3D 对象的错觉),因此这里首先填充这些形状,然后是外部部分(形状边框)是独立绘制的。

      这最终将允许在需要时为图形使用不同的画笔。

      结果示例:


      Private upperRect As Rectangle = New Rectangle(New Point(10, 10), New Size(180, 80))
      Private lowerRect As Rectangle = New Rectangle(New Point(10, 100), New Size(180, 80))
      
      Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
          e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
      
          Dim middleRect As Rectangle = CylinderMiddleRect(upperRect, lowerRect)
      
          Using gp As New GraphicsPath(FillMode.Winding)
              gp.AddEllipse(upperRect)
              gp.AddRectangle(middleRect)
              gp.AddEllipse(lowerRect)
              e.Graphics.FillPath(Brushes.LightBlue, gp)
              gp.Reset()
      
              gp.AddArc(lowerRect, 0, 180)
              gp.AddEllipse(upperRect)
              gp.AddLine(New Point(middleRect.X, middleRect.Y), New Point(upperRect.X, middleRect.Bottom))
              gp.CloseFigure()
              gp.AddLine(New Point(middleRect.Right, middleRect.Y), New Point(middleRect.Right, middleRect.Bottom))
              gp.CloseFigure()
              e.Graphics.DrawPath(Pens.Black, gp)
          End Using
      End Sub
      
      Private Function CylinderMiddleRect(upperRect As Rectangle, lowerRect As Rectangle) As Rectangle
          Dim distance = (lowerRect.Y + (lowerRect.Height \ 2)) - (upperRect.Y + (upperRect.Height \ 2))
      
          Return New Rectangle(New Point(upperRect.X, upperRect.Y + (upperRect.Height \ 2)),
                               New Size(upperRect.Width, distance))
      End Function
      

      【讨论】:

      • 很好,比我的好多了
      • 只是抗锯齿:e.Graphics.SmoothingMode = SmoothingMode.AntiAlias :)
      • 是的,我知道这一点。但是你的看起来还是更好看。有什么方法可以接受输入矩形并以此为基础进行绘制?
      • 实际上,我在 Paint 事件之外声明了 upperRectlowerRect 矩形只是为了这个。 CylinderMiddleRect 方法然后计算两个矩形之间的距离。该距离用于构建内部矩形,其边提供连接线。所以,是的,您可以使用两个任意大小的矩形(这是有道理的)。这里,upperRectlowerRect 之间的区别只是Y 的位置。
      • 啊,矩形除了位置是一样的。
      猜你喜欢
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2012-06-17
      • 2019-11-12
      • 2019-02-09
      相关资源
      最近更新 更多