主頁 > .NET開發 > 【WPF學習】第四十三章 路徑和幾何圖形

【WPF學習】第四十三章 路徑和幾何圖形

2020-09-11 05:21:52 .NET開發

  前面四章介紹了繼承自Shape的類,包括Rectangle、Ellipse、Polygon以及Polyline,但還有一個繼承自Shape的類尚未介紹,而且該類是到現在為止功能最強大的形狀類,即Path類,Path類能夠包含任何簡單形狀、多組形狀以及更復雜的要素,如曲線,

  Path類提供了Data屬性,該屬性接受一個Geometry物件,該物件定義路徑包含的一個或多個圖形,不能直接創建Geometry物件,因為Geometry是抽象類,而且需要使用下表中列出的7個派生類的一個進行創建,

表 幾何圖形類

 

 

   現在,可能會好奇路徑和幾何圖形之間到底有什么區別,幾何圖形定義形狀,而路徑用于繪制形狀,因此,Geometry物件為形狀定義了坐標和尺寸等細節,而Path物件提供了用于繪制形狀的Stroke和Fill畫刷,Path類還提供了繼承自UIElement基礎架構的特性,如果滑鼠和鍵盤處理,

  然而,幾何圖形并不像看起來那么簡單,原因之一是他們都繼承自Freezable類(通過Geometry基類),所以支持更改通知,因此,如果使用集合圖形創建路徑,然后修改幾何圖形,就會自動被重新繪制路徑,還可以使用幾何圖形類來定義能夠通過畫刷應用的圖畫,從而為繪制不需要Path類所具有的用戶互動功能的復雜內容提供一種簡單方法,

一、直線、矩形和橢圓圖形

  LineGeometry、RectangleGeometry以及EllipseGeometry類直接對應于Line、Rectangle以及Ellipse形狀,例如,可將下面使用Rectangle元素的標記:

<Rectangle Fill="Yellow" Stroke="Blue" Width="100" Height="50"></Rectangle>

  轉換為下面使用Path元素的標記:

<Path Fill="Yellow" Stroke="Blue">
            <Path.Data>
                <RectangleGeometry Rect="0 0 100,50"></RectangleGeometry>
            </Path.Data>
</Path>

  唯一的實質性區別是Rectangle形狀使用的是Height和Width值,而RectangleGeometry圖形使用4個數值來描述矩形的尺寸和位置,前兩個數值描述左上角的X和Y坐標,而后兩個數值設定為矩形的寬度和高度,可在(0,0)點開始繪制矩形,從而得到與普通的Rectangle元素相同的效果,或者使用不同的值偏移矩形,RectangleGeometry類還提供了RadiuX和RadiuY屬性,這兩個屬性用于圓滑拐角,

  類似地,可將下面的Line形狀:

 <Line Stroke="Blue" X1="0" Y1="0" X2="50" Y2="10"></Line>

  轉變成下面的LineGeometry圖形:

<Path Stroke="Blue" Fill="Yellow">
            <Path.Data>
                <LineGeometry StartPoint="0,0" EndPoint="50,10"></LineGeometry>
            </Path.Data>
        </Path>

  也可將如下的Ellipse形狀:

<Ellipse Fill="Yellow" Stroke="Blue" Width="100" Height="50" HorizontalAlignment="Left"></Ellipse>

  轉變成下面的EllipseGeometry圖形:

<Path Fill="Yellow" Stroke="Blue">
            <Path.Data>
                <EllipseGeometry RadiusX="50" RadiusY="25" Center="50,25"></EllipseGeometry>
            </Path.Data>
</Path>

  注意,兩個半徑值只是寬度和高度值得一半,還可使用Center屬性偏移橢圓的位置,在該例中,中心被設定為橢圓外包圍框的正中心位置,所以使用與繪制Ellipse形狀完全相同的方式來繪制橢圓圖形,

  總之,這些簡單圖形和對應的形狀使用相同的作業方式,雖然具有額外的可偏移矩形和橢圓的功能,但如果在Canvas面板上放置形狀,該功能是沒有必要的,因為已經具有將形狀定位到特定位置的能力,實際上,如果這就是圖形所能完成的所有內容,可能覺得使用Path元素很煩人,

二、使用GeometryGroup組合形狀

  組合圖形最簡單的方法是使用GeometryGroup物件,該物件在內部嵌套其他Geometry類的派生類物件,下面的示例在一個正方形的旁邊放置了一個橢圓:

<Path Fill="Yellow" Stroke="Blue" Margin="5" Canvas.Top="10" Canvas.Left="10" >
            <Path.Data>
                <GeometryGroup>
                    <RectangleGeometry Rect="0 0 100 100"></RectangleGeometry>
                    <EllipseGeometry Center="50 50" RadiusX="35" RadiusY="25"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
</Path>

  效果圖如下所示:

 

 

   上面標記的效果和如下兩個Path元素的效果相同,其中一個Path元素具有RectangleGeometry,而另一個Path元素具有EllipseGeometry(而且像是改用Rectangle和Ellipse形狀),然而,這兩種方法有一個優點,用一個元素替代了兩個元素,這意味著降低了用戶界面的開銷,通常,使用數量更少的較復雜集合圖形元素的視窗比具有大量較簡單集合圖形元素的視窗的性能要高,在只有幾十個形狀的視窗中這一效果并不明顯,但對于需要幾百或幾千個形狀的視窗,這一問題就會變得更重要了,

  當然,將多個幾何圖形組合成單獨的Path元素也存在缺點——不能單獨為不同的形狀執行事件處理,反而,Path元素將引發所有的滑鼠事件,不過,仍可以獨立地控制嵌套的RectangleGeometry和EllipseGeometry物件,從而改變整個路徑,例如,每個幾何圖形都提供了Transform屬性,可使用該屬性拉伸、扭曲和選擇路徑的回應部分,

  幾何圖形的另一個優點是可在幾個獨立的Path元素中重用相同的幾何圖形,這不需要使用代碼——只需要在Resources結合中定義集合圖形,并使用StaticExtension或DynamicExtension標記擴展在路徑中進行參考,下面的例子對前面顯示的例子進行了重寫,在Canvas容器的兩個不同位置使用兩種相同顏色來顯示CombinedGeometry實體:

<Window x:Class="Drawing.CombiningShapes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CombiningShapes" Height="300" Width="300">
    <Window.Resources>
        <GeometryGroup x:Key="Geometry">
            <RectangleGeometry Rect="0,0 100,100"></RectangleGeometry>
            <EllipseGeometry Center="150,50" RadiusX="35" RadiusY="25"></EllipseGeometry>
        </GeometryGroup>
    </Window.Resources>
    <Canvas>
        <Path Fill="Yellow" Stroke="Blue" Margin="5" Canvas.Top="10" Canvas.Left="10"
              Data="{StaticResource Geometry}">
        </Path>
        <Path Fill="Yellow" Stroke="Blue" Margin="5" Canvas.Top="150" Canvas.Left="10"
              Data="{StaticResource Geometry}">
        </Path>
    </Canvas>
</Window>
CombiningShapes

 

 

   當形狀相互交叉時,GeometryGroup將更有趣,這時不能將圖畫簡單地作為固定形狀的組合對待,GeometryGroup使用FillRule屬性(該屬性可設定為EventOdd或Nonzero)決定填充哪些形狀,如果采用如下方式改變前面顯示的標記,在正方形的上面放置橢圓,分析一下會出現什么情況:

<Path Fill="Yellow" Stroke="Blue" Margin="5" Canvas.Top="10" Canvas.Left="10" >
            <Path.Data>
                <GeometryGroup>
                    <RectangleGeometry Rect="0 0 100 100"></RectangleGeometry>
                    <EllipseGeometry Center="50 50" RadiusX="35" RadiusY="25"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path>

  現在,上面的標記創建了一個正方形,這個正方形的內部有一個橢圓形狀的空洞,如果將FillRule屬性修改為Nonezero,在純色正方形的上面就會有一個純色的橢圓,橢圓和正方形都使用黃色填充,

  通過在正方形的上面重疊以白色填充的橢圓,可創建有洞得正方形,然而,如果在下面有內容,GeometryGroup類會變得更有用處,因為在你的形狀中橢圓被視為洞,后面的內容都可透過該洞顯示,如下示例所示:

 <Canvas>
        <TextBlock Canvas.Top="50" Canvas.Left="20" FontSize="25" FontWeight="Bold">Hello There</TextBlock>

        <Path Fill="Yellow" Stroke="Blue" Margin="5" Canvas.Top="10" Canvas.Left="10" >
            <Path.Data>
                <GeometryGroup>
                    <RectangleGeometry Rect="0 0 100 100"></RectangleGeometry>
                    <EllipseGeometry Center="50 50" RadiusX="35" RadiusY="25"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path>

    </Canvas>
GroupGeometry

 

 

 三、使用CombinedGeometry融合幾何圖形

  對于通過基本圖元(矩形、橢圓和直線)構建復雜形狀,GeometryGroup類是非常有價值的工具,但它也有明顯的局限性,如果是繪制形狀,并在其內部“減去”另一個形狀來創建新的形狀,GeometryGroup類可以作業的很好,然而,如果形狀的邊界相互交叉,就很難得到所希望的結果了,并且如果希望移除形狀的一部分,GeometryGroup類就不能提供任何幫助了,

  CombinedGeometry類專門用于組合重疊到一起并且不相互包含的形狀,與GeometryGroup類不同,CombinedGeometry類只使用兩個幾何圖形,通過Geometry1和Geometry2屬性提供這兩個幾何圖形,CombinedGeometry類沒有包含FillRule屬性,反而具有功能更強大的GeometryCombineMode屬性,該屬性可以使用4個值中的一個,下表列出了這4個值,

表 GeometryCombineMode列舉值

 

 

   例如,下面的示例演示了GeometryCombineMode:

<Window x:Class="Drawing.CombineGeometryShapes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CombineGeometryShapes" Height="481" Width="341">
    <Window.Resources>
        <RectangleGeometry x:Key="rect" Rect="0 0 100 100"></RectangleGeometry>
        <EllipseGeometry x:Key="ellipse" Center="85 50" RadiusX="65" RadiusY="35"></EllipseGeometry>
    </Window.Resources>
    <Grid Margin="5" TextBlock.FontSize="16">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Path Fill="Yellow" Stroke="Blue" Margin="5">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Union"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
                </CombinedGeometry>
            </Path.Data>
        </Path>
        <TextBlock Grid.Column="1" Margin="10" VerticalAlignment="Center">Union</TextBlock>

        <Path Grid.Row="1" Fill="Yellow" Stroke="Blue" Margin="5">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Intersect"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
                </CombinedGeometry>
            </Path.Data>
        </Path>
        <TextBlock Grid.Row="1" Grid.Column="1" Margin="10" VerticalAlignment="Center">Intersect</TextBlock>

        <Path Grid.Row="2" Fill="Yellow" Stroke="Blue" Margin="5">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Xor"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
                </CombinedGeometry>
            </Path.Data>
        </Path>
        <TextBlock Grid.Row="2" Grid.Column="1" Margin="10" VerticalAlignment="Center">Xor</TextBlock>

        <Path Grid.Row="3" Fill="Yellow" Stroke="Blue" Margin="5">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Exclude"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
                </CombinedGeometry>
            </Path.Data>
        </Path>
        <TextBlock Grid.Row="3" Grid.Column="1" Margin="10" VerticalAlignment="Center">Exclude</TextBlock>

    </Grid>
</Window>
CombineGeometryShapes

 

 

   為理解這種組合的作業原理,下圖中顯示的簡單的“no"符合(一個有斜杠貫穿其中的圓),盡管任何一個WPF基本元都與該形狀不同,但可以用CombinedGeometry物件很快裝配出該符號,

<Window x:Class="Drawing.NoSymbol"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="NoSymbol" Height="300" Width="300">
    <StackPanel Margin="5">

        <Path Fill="Yellow" Stroke="Blue">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Union">
                    <CombinedGeometry.Geometry1>
                        <CombinedGeometry GeometryCombineMode="Exclude">
                            <CombinedGeometry.Geometry1>
                                <EllipseGeometry Center="50 50" RadiusX="50" RadiusY="50"></EllipseGeometry>
                            </CombinedGeometry.Geometry1>
                            <CombinedGeometry.Geometry2>
                                <EllipseGeometry Center="50 50" RadiusX="40" RadiusY="40"></EllipseGeometry>
                            </CombinedGeometry.Geometry2>
                        </CombinedGeometry>
                    </CombinedGeometry.Geometry1>
                    <CombinedGeometry.Geometry2>
                        <RectangleGeometry Rect="44 5 10 90">
                            <RectangleGeometry.Transform>
                                <RotateTransform Angle="45" CenterX="50" CenterY="50"></RotateTransform>
                            </RectangleGeometry.Transform>
                        </RectangleGeometry>
                    </CombinedGeometry.Geometry2>
                </CombinedGeometry>
            </Path.Data>
        </Path>


    </StackPanel>
</Window>
NoSymbol

 

 

 四、使用PathGeometry繪制曲線和直線

  PathGeometry是功能超級強大的圖形,它能繪制其他所有幾何圖形能夠繪制的內容,也能繪制其他所有幾何圖形所不能繪制的內容,它的唯一缺點是語法比較長(并且在某種程度上更加復雜),

  每個PathGeometry物件都是由一個或多個PathFigure物件構建的(存盤在PathGeometry.Figures集合中),每個PathFigure物件是一系列相互連接的直線和曲線,可閉合也可不閉合,如果圖形中最后一條直線的終點連接到了第一條直線的起點,那么圖形就是閉合的,

  PathFigure類包含4個重要屬性,如下表所示,

表 PathFigure屬性

 

 

   PathFigure物件是由包含大量線段的不間斷線潭訓制的形狀,然而,技巧是有幾種型別的線段,它們都繼承自PathSegment類,其中一些類比較簡單,如繪制直線的LineSegment類,而另外一些類(如BezierSegment類)較為復雜,可以繪制曲線,

  可自由地混合并匹配不同的線段來構建圖形,下表列出了可供使用的線段類,

表 PathSegment類

  名   稱    說    明 
LineSegment 在兩點之間創建直線
ArcSegment 在兩點之間創建橢圓形弧線
BezierSegment 在兩點之間創建貝塞爾曲線
QuadraticBezierSegment 創建形式更簡單的貝塞爾曲線,只有一個控制點而不是兩個控制點,并且計算速度更快
PolyLineSegment 創建一系列直線,可使用多個LineSegment物件得到相同的效果,但使用單個PolyLineSegment物件更簡明
PolyBezierSegment 創建一系列貝塞爾曲線
PolyQuadraticBezierSegment 創建一系列更簡單的二次貝塞爾曲線

  1、直線

  使用LineSegment和PathGeometry類創建簡單的線條非常容易,只需要設定StartPoint屬性,并為線條中的每部分增加一條LineSegment直線段,LineSegment.Point屬性標識每條線段的結束點,

  例如,下面的標記是從點(10,100)開始,繪制一條到點(100,100)的直線,然后從點(100,100)開始繪制到點(100,50)的直線,因為PathFigure.IsClosed屬性設定為true,所以添加的最后一條線段將點(100,50)連接到點(0,0),最后的結果是直角三角形,

<Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True" StartPoint="0,100">
                        <LineSegment Point="100,100"/>
                        <LineSegment Point="100,50"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

  效果圖如下所示:

 

 

   2、弧線

  弧線比直線更有趣,就像使用LineSegment類時一樣,使用ArcSegment.Point屬性指定弧線段終點,不過,PathFigure從起點(或前一條線段的終點)向弧線的終點繪制一條曲線,這條彎曲的連接線實際是橢圓邊緣的一部分,

  顯然,為了繪制弧線,只有終點是不夠的,因為有許多曲線(一些彎曲程度較緩和,另一些彎曲的程度更大)能夠連接這兩點,還需要指定用于繪制弧線的假想橢圓的尺寸,可使用ArgSegment.Size屬性完成作業,該屬性提供了橢圓的X半徑和Y半徑,假想的橢圓越大,邊緣曲線就越緩和,

  下面的示例創建了弧線,

<Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="0,100" IsClosed="False">
                        <ArcSegment Point="200,100" Size="200,300"></ArcSegment>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

 

 

   到目前為止,弧線聽起來似乎很簡單,然而,即使提供了起點、終點以及橢圓的尺寸,也仍不具備明確繪制弧線所需的全部資訊,上面的示例還依賴與兩個默認值,如果喜歡的話,也可以使用其他值,

  為了理解該問題,需要分析能連接相同兩點的弧線的其他方式,如果繪制橢圓上的兩個點,顯示可以由兩種方式連接它們——通過沿著短邊連接兩點,或沿著長邊連接兩點,

  可用ArgSegment.IsLargeArc屬性何止弧線的方向,可將該屬性設定為true或false,默認是false,這意味著使用兩潭訓線中較短的一條,

  即使設定了方向,也還有一點需要明確——橢圓位于何處,設想繪制一潭訓線連接左邊的一點或右邊的一點,并使用盡可能短的弧線,連接這兩個點的曲線可被向下拉伸,然后向上拉上拉伸;也可以翻轉該弧線,從而先向上彎曲,然后向下彎曲,得到的弧線依賴與定義弧線的兩點的順序以及ArgSegment.SweepDirection屬性,該屬性可以是Counterclockwise(默認值)或Clockwise,

  3、貝塞爾曲線

  貝塞爾曲線使用更復雜的數學公式連接兩條線段,該公式包含的兩個控制點決定了曲線的性質,實際上,貝塞爾曲線是每個矢量繪圖程式都會創建的要素,因為他們非常靈活,只需要使用起點、終點和兩個控制點,就可以創建出令人稱奇的各種光滑曲線(包括回線(loop)),如下圖所示,顯示了一條經典的貝塞爾曲線,兩個小圓指示了控制點而曲線將每個控制點連接到受控制點影響最大的線條端點,

<Window x:Class="Drawing.BezierCurve"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="BezierCurve" Height="300" Width="300">
    <Canvas>
        <Path Stroke="Blue" StrokeThickness="5" Canvas.Top="20">
            <Path.Data>
                <PathGeometry>
                    <PathGeometry.Figures>
                        <PathFigure StartPoint="10,10">
                            <BezierSegment Point1="130,30" Point2="40,140" Point3="150,150"></BezierSegment>
                        </PathFigure>
                    </PathGeometry.Figures>
                </PathGeometry>
            </Path.Data>
        </Path>
        <Path Stroke="Green" StrokeThickness="2" StrokeDashArray="5 2" Canvas.Top="20">
            <Path.Data>
                <GeometryGroup>
                    <LineGeometry StartPoint="10,10" EndPoint="130,30"></LineGeometry>
                    <LineGeometry StartPoint="40,140" EndPoint="150,150"></LineGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path>
        <Path Fill="Red" Stroke="Red" StrokeThickness="8"  Canvas.Top="20">
            <Path.Data>
                <GeometryGroup>
                    <EllipseGeometry Center="130,30"></EllipseGeometry>
                    <EllipseGeometry Center="40,140"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path>
    </Canvas>
</Window>
BezierCurve

 

 

 

   即使不理解貝塞爾曲線的數學原理,也很容易”感覺“出貝塞爾曲線的作業原理,本質上,兩個控制點是所有問題的關鍵,他們以兩種方式影響曲線:

  •   在起點,貝塞爾曲線和從第一個控制點到起點之間的直線相切,在終點,貝塞爾曲線和連接終點與最后一個點的直線相切(在中間是曲線)
  •   彎曲程度由到兩個控制點的距離決定,如果一個控制點更遠,該控制點會更強地”拉“貝塞爾曲線,

  為在標記中定義貝塞爾曲線,需要提供三個點,前兩個點(BezierSegment.Point1和BezierSegment.Point2)是控制點,第三個點(BezierSegment.Point3)是曲線的終點,同樣,起點是路徑的起點或前一條線段的終點,

五、微語言幾何圖形

  到目前為止看到的幾何圖形都比較簡明,只用了少數幾個點,更復雜的集合圖形在該概念上與此相同,只不過動輒就需要幾百條線段,在復雜路徑中定義每條直線、弧線以及曲線非常繁瑣而且不是必需的——畢竟,復雜曲線可能由設計工具生成,而不是通過手工撰寫,所以保持標記的清晰性并不是最重要的,為此,WPF創作人員為定義幾何圖形增加了一種更簡明的替換語法,通過該語法可用更少的標記表示詳細的圖形,這種語法通常稱為圖形微語言(geometry mini-language),并且由于應用于Path元素,因此有時候稱為路徑微語言,

  為理解微語言,需要認識到它在本質上包含一系列命令的長字串,這些命令由型別轉換器讀取,然后創建回應的幾何圖形,每個命令都是單獨的字母,后面可選地跟隨一些由空格分隔的數字資訊(如X和Y坐標),每個命令也使用空格與前面的命令隔開,

  例如,在前面使用具有兩條線路的閉合路徑創建了一個基本三角形,下面是繪制這個三角形的標記:

<Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True" StartPoint="10,100">
                        <LineSegment Point="100,100" />
                        <LineSegment Point="100,50" />
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

  使用微語言創建該圖形,英按如下方式撰寫標記:

<Path Stroke="Blue" Data="M 10,100 L 100,100 L 100,50 Z"/>

  這個路徑使用一個包含4個命令的命令序列,第一個命令(M)創建PathFigure,并將起點設定為(10,100),接下來的兩個命令(L)創建線段,最后一個命令(Z)結束PathFigure,并將IsClosed屬性設定為True,這個字串中的逗號是可選的,同樣,命令及其引數之間的空格也是可選的,但在相鄰的兩個引數之間以及命令之間至少要保留一個空格,這意味著可以進一步精簡語法,形成下面這種更難度的形式:

<Path Stroke="Blue" Data="M10 100 L100 100 L100 50 Z"/>

  當使用微語言創建集合圖形時,實際上是創建了StreamGeometry物件而不是PathGeometry物件,因此,以后在代碼中不能修改圖形,如果這是不能接受的,可顯示地創建PathGeometry物件,但使用相同的語法定義其PathFigure物件集合,如下所示:

<Path Stroke="Blue">
            <Path.Data>
                <PathGeometry Figures="M 10,100 
          L 100,100 L 100,50 Z"></PathGeometry>
            </Path.Data>
        </Path>

  微語言幾何圖形很容易理解,它使用下表中詳細描述的一小組命令,引數以斜體顯示:

表 微語言圖形命令

 

 

 六、使用幾何圖形進行裁剪

  幾何圖形是創建形狀的最強大方法,然而,幾何圖形不僅可用于Path元素,也可為任何需要的地方提供抽象的圖形定義(而不是在視窗中繪制真實的具體形狀),

  幾何圖形的另一個用途是用于設定Clip屬性,所有元素都提供了該屬性,可以通過Clip屬性約束元素的外邊界以符合特定的幾何圖形,可使用Clip屬性創建大量的特殊效果,盡管該屬性通常用于修剪Image元素中的影像內容,但也可將Clip屬性應用于任何元素,唯一的限制是,如果確實希望看到一些內容——而不僅是用處不大的單獨曲線和線段,需要使用閉合的幾何圖形,

  下面的示例定義了一個集合圖形,該集合圖形用于裁剪兩個元素,一個是包含一副位圖的Image元素,另一個是標準的Button元素,

 

 

   下面是該例的標記:

<Window.Resources>
        <GeometryGroup x:Key="clipGeometry" FillRule="Nonzero">
            <EllipseGeometry RadiusX="75" RadiusY="50" Center="100,150"></EllipseGeometry>
            <EllipseGeometry RadiusX="100" RadiusY="25" Center="200,150"></EllipseGeometry>
            <EllipseGeometry RadiusX="75" RadiusY="130" Center="140,140"></EllipseGeometry>
        </GeometryGroup>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Button Clip="{StaticResource clipGeometry}">A button</Button>
        <Image Grid.Column="1" Clip="{StaticResource clipGeometry}" 
           Stretch="None"  Source="creek.jpg"></Image>
    </Grid>
Clip

  使用裁剪存在限制,設定的裁剪不會考慮元素的尺寸,換句話說,當改變視窗尺寸時,不管上圖中顯示的按鈕變大還是變小,裁剪區域仍保留原樣,并顯示按鈕的不同部分,一種可能的解決方案是在Viewbox控制元件中封裝元素,以便提供自動重新縮放功能,但這會導致所有內容都按比例地改變尺寸,包括希望改變尺寸的一些細節(裁剪區域和按鈕表面)以及那些可能不希望改變的內容,

  如下示例使用Viewbox控制元件所示:

<Window.Resources>
        <GeometryGroup x:Key="clipGeometry" FillRule="Nonzero">
            <EllipseGeometry RadiusX="75" RadiusY="50" Center="100,150"></EllipseGeometry>
            <EllipseGeometry RadiusX="100" RadiusY="25" Center="200,150"></EllipseGeometry>
            <EllipseGeometry RadiusX="75" RadiusY="130" Center="140,140"></EllipseGeometry>
        </GeometryGroup>
    </Window.Resources>
    <Grid>
        <Viewbox >
            <Button Width="350" Height="350" Clip="{StaticResource clipGeometry}">A button</Button>
        </Viewbox>
    </Grid>
ClippingWithViewbox

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/4469.html

標籤:WPF

上一篇:【WPF學習】第四十二章 透明

下一篇:[WPF 自定義控制元件]創建包含CheckBox的ListBoxItem

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more