【WPF學習】第四十一章 變換

来源:https://www.cnblogs.com/Peter-Luo/archive/2020/02/15/12312445.html

通過使用變換(transform),許多繪圖任務將更趨簡單;變換是通過不加通告地切換形狀或元素使用的坐標系統來改變形狀或元素繪製方式的對象。在WPF中,變換由繼承自System.Windows.Media.Transform抽象類的類表示。下表列出了這些類。 表 變換類 從技術角度看,所有變換都使用 ...


  通過使用變換(transform),許多繪圖任務將更趨簡單;變換是通過不加通告地切換形狀或元素使用的坐標系統來改變形狀或元素繪製方式的對象。在WPF中,變換由繼承自System.Windows.Media.Transform抽象類的類表示。下表列出了這些類。

表 變換類

   從技術角度看,所有變換都使用矩陣數學改變形狀的坐標。不過,使用預先構建好的變換,如TranslateTransform、RotateTransform、ScaleTransform以及SkewTransform,比使用MatrixTransform並嘗試為希望執行的操作構造正確的矩陣更簡單的多。當使用TransformGroup執行一系列變換時,WPF將所有變換融合到單獨的MatrixTransform變換中以確保獲得最佳性能。

  所有變換(通過Transform類)繼承自Freezable類,這意味著它們支持自動更改通知功能。如果改變了在形狀中使用的變換,形狀會立即重新繪製自身。

  變換是那些在不同上下文中非常有用的古怪概念中的一個。下麵例舉幾個例子:

  •   傾斜形狀。到目前為止已經介紹了水平對齊的矩形、橢圓、直線以及多邊形。使用RotateTransform變換,可轉動坐標系統,使創建特定的形狀更容易。
  •   重覆形狀。許多圖畫是在不同的位置使用類似的形狀構建的。使用變換,可先繪製一個形狀,然後移動、旋轉、縮放該形狀,以及執行其他操作。
  •   動畫。通過變換,可創建大量精緻的效果。例如,旋轉形狀、將形狀從一個地方移到另一個地方,以及動態扭曲形狀。

一、變換形狀

  為變換形狀,將RenderTransform屬性指定為希望使用的變換隊形。根據使用的變換隊形,需要填充不同的屬性以配置變換隊形。

  例如,如果旋轉形狀,需要使用RotateTransform變換,並以度為單位提供旋轉角度。下麵的示例將舉行旋轉25°:

 <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="100">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="25" />
            </Rectangle.RenderTransform>
        </Rectangle>

  採用這種方式旋轉形狀時,是圍繞形狀的原點進行旋轉的(左上角)。下圖演示了繞形狀原點旋轉25°、50°、75°以及100°的效果。

<Window x:Class="Drawing.RotateShape"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateShape" Height="427" Width="332"
    >
    <Canvas>
        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
          Canvas.Left="100" Canvas.Top="100">
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="100">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="25" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
          Canvas.Left="100" Canvas.Top="100">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="50" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="100">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="75" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="100">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="100" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>

</Window>
RotateShape

  有時候希望繞不同的點旋轉形狀。與其他許多變換類一樣,RotateTransform變換也提供了CenterX和CentertY屬性。可以用這些屬性指定將進行旋轉的中心。下麵的矩形使用該方法繞其中心點旋轉自身25°:

<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="25" CenterX="45" CenterY="5" />
            </Rectangle.RenderTransform>
        </Rectangle>

  採用這種方式旋轉形狀時,是圍繞形狀的原點進行旋轉的(中心)。下圖演示了繞形狀原點旋轉25°、50°、75°以及100°的效果。

<Window x:Class="Drawing.RotateShape"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateShape" Height="427" Width="332"
    >
    <Canvas>
        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
          Canvas.Left="100" Canvas.Top="300">
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="25" CenterX="45" CenterY="5" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="50" CenterX="45" CenterY="5" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="75" CenterX="45" CenterY="5" />
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300">
            <Rectangle.RenderTransform>
                <RotateTransform Angle="100" CenterX="45" CenterY="5" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>

</Window>
RotateShape

 

   使用RotateTransform的CenterX和CenterY屬性時存在明顯的限制。這些屬性是使用絕對坐標定義的,這意味著需要瞭解繪製內容的中心店的準確位置。如果正在顯示動態內容(例如,可變維度的圖片或改變尺寸的元素),就會出現問題。幸運的是,WPF通過方便的RenderTransformOrigin屬性,為這個問題提供瞭解決方法,所以形狀都支持RenderTransformOrign屬性。該屬性使用相對坐標系統設置中心點,下該對坐標系統在兩個方向上的範圍都是從0到1。換句話說,點(0,0)被指定為左上角,點(1,1)表示右下角(如果形狀區域不是正方形,那麼會相應地拉伸坐標系統)。

  藉助於RenderTransformOrigin屬性,可使用如下所示的標記,繞中心點旋轉任意形狀:

<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow" 
      Canvas.Left="100" Canvas.Top="300" RenderTransformOrigin="0.5,0.5">
      <Rectangle.RenderTransform>
        <RotateTransform Angle="75" CenterX="45" CenterY="5" />
      </Rectangle.RenderTransform>
    </Rectangle>

  因為不管形狀的尺寸是多少,點(0.5,0.5)都表示形狀中心,所以上面的標記可以工作。實際上,RenderTransformOrigin屬性通常比CenterX和CenterY屬性更有用,儘管根據需要可以使用兩者中的一個,或者同時使用兩者。

二、變換元素

  RenderTransform和RenderTransformOrigin屬性並不限制只能用於形狀。實際上,Shape類的這些屬性從UIElement類繼承而來,這意味著所有WPF元素都支持這兩個屬性,包括按鈕、文本框、TextBlock控制項、充滿內容的整個佈局容器等。令人感到驚訝的是,可旋轉、扭曲以及縮放WPF用戶界面中的任意一部分。  

  RenderTransform不是在WPF基類中定義的唯一與變換相關的屬性。FrameworkElement類還定義了LayoutTransform屬性。LayoutTransform屬性以相同的方式變換元素,但在佈局之前執行其工作。這種情況的開銷雖然更大些,但如果使用佈局容器為一組控制項提供自動佈局功能,這種方式是很關鍵的(Shape類也提供了LayoutTransform屬性,但很少需要使用該屬性,因此通常使用容器(如Canvas面板)明確地放置形狀,而不是使用自動佈局)。

  為理解兩者的區別,分析下圖中顯示的視窗,該視窗包含兩個StackPanel容器(由陰影區域表示),這兩個容器都包含一個選擇過的按鈕和一個正常的按鈕。在第一個StackPanel容器中,選擇的按鈕使用RenderTransform方法。該StackPanel容器在對兩個按鈕進行佈局時,第一個按鈕正常定位,並且在即將呈現之前旋轉該按鈕。因此,選擇過的按鈕被重疊在下麵。在第二個StackPanel容器中,選擇過的按鈕使用LayoutTransform方法。StackPanel容器獲取到選項後按鈕所需的邊界,並相應地佈局第二個按鈕。

<Window x:Class="Drawing.RotateElement"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="RotateElement" Height="314" Width="305"
    >
  <StackPanel>
    <StackPanel  Margin="25"  Background="LightYellow">
      <Button Padding="5" HorizontalAlignment="Left">
        <Button.RenderTransform>
          <RotateTransform Angle="35" CenterX="45" CenterY="5" />
        </Button.RenderTransform>
        <Button.Content>I'm rotated 35 degrees</Button.Content>
      </Button>
      <Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
    </StackPanel>

    <StackPanel  Margin="25"  Background="LightYellow">
      <Button Padding="5" HorizontalAlignment="Left">
        <Button.LayoutTransform>
          <RotateTransform Angle="35" CenterX="45" CenterY="5" />
        </Button.LayoutTransform>
        <Button.Content>I'm rotated 35 degrees</Button.Content>
      </Button>
      <Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
    </StackPanel>
  </StackPanel>
</Window>
RotateElement

 

   只有很少幾個元素不能被變換,因為他們的呈現工作並非由WPF本身負責。不能被變換的元素的兩個例子是WindowsFormHost和WebBrower元素,WindowsFormHost元素用於在WPF視窗中放置Windows窗體控制項,WebBrower元素用於顯示HTML內容。

  在一定程度上,當設置LayoutTransform或RenderTransform屬性時,WPF元素不知道它們正在被修改。特別是,變換不會影響元素的ActualHeight和ActualWidth屬性,它們仍記錄著變換之前的值。這正是WPF能夠保證流失佈局以及外邊距繼續以相同的方式工作的部分原理,即使應用了一個或多個變換也同樣如此。

 


您的分享是我們最大的動力!

更多相關文章
  • 好久時間沒有做Django的項目了,今天創建項目竟然報Non-zero exit code(1)錯誤 查明原因是因為pip不是最新版本,需要執行以下命令:python -m pip install --upgrade pip 但還是沒有成功,提示超時,估計源有問題 使用豆瓣源進行安裝,問題解決了 命 ...
  • 前言最近由於疫情被困在家,於是準備每天看點專業知識,準備寫成博客,不定期發佈。博客大概會寫5~7篇,主要是“解剖”一些深度學習的底層技術。關於深度學習,電腦專業的人多少都會瞭解,知道Conv\Pool的過程,也看過論文,做過實驗或是解決方案。在寫的各種捲積網路 時候,有沒有問問自己:這些網路到底是... ...
  • 為什麼要用函數 現在python屆發生了一個大事件,len方法突然不能直接用了。。。 然後現在有一個需求,讓你計算'hello world'的長度,你怎麼計算? 這個需求對於現在的你其實不難,我們一起來寫一下。 s1 = "hello world" length = 0 for i in s1: l ...
  • 慕課網-悟空-玩轉Java併發工具,精通JUC,成為併發多面手-筆記 微雲:https://share.weiyun.com/81aa12bb98016e200add31fb8e191cdf百度網盤:鏈接:https://pan.baidu.com/s/1IiClTkQwFJgBL2NqlptKbA ...
  • 一、前言 從學單片機開始鼓搗C語言,到現在為了學CV鼓搗Python,期間在CSDN、簡書、博客園和github這些地方得到了很多幫助,所以也想把自己做的一些小東西分享給大家,希望能幫助到別人。記錄人生的第一篇博客,mark。 二、圖像檢測步驟 1. 讀取兩張圖片 第一張是需要檢測的小物體,第二章圖 ...
  • 多態的體現 父類的引用指向了自己的子類對象。 父類的引用也可以接受自己的子類對象。 代碼體現 運行結果 多態的前提 必須是類與類之間有關係。要麼是繼承關係,要麼實現。 存在覆寫關係。 多態利弊 利處 多態的出現大大地提高了程式的拓展性。 弊端 提高了拓展性,但是只能使用父類的引用訪問父類中的成員,不 ...
  • 今天給大家翻譯一篇由ASP.NET首席開發工程師 "James Newton King" 前幾天發表的一篇博客,文中帶來了一個實驗性的產品gRPC Web。大家可以點擊文末的討論帖進行相關反饋。我會在文章末尾給出原文鏈接。全部譯文如下: 我很高興宣佈通過.NET對gRPC Web進行實驗性支持。gR ...
  • .NET Core WebAPI post參數傳遞時後端的接收方式 1. 實體類 2. dynamic動態類型 3. JObject參數 4. 單值參數(字元串參數) A.前端Post請求代碼 B.後端接收參數方式 1. 實體類 實體類是比較簡單的一種傳參方式,使用頻率非常高。 1. 添加實體類 2 ...
一周排行
  • 《ASP.NET MVC 企業級實戰》 [作者] (中) 鄒瓊俊[出版] 清華大學出版社[版次] 2017年04月 第1版[印次] 2019年08月 第6次 印刷[定價] 89.00元 【第01章】 (P021) 只有在 Lambda 有一個輸入參數時,括弧才是可選的,否則括弧是必需的。 使用空括弧 ...
  • 上一篇(https://www.cnblogs.com/meowv/p/12971041.html)使用HtmlAgilityPack抓取壁紙數據成功將圖片存入資料庫,本篇繼續來完成一個全網各大平臺的熱點新聞數據的抓取。 同樣的,可以先預覽一下我個人博客中的成品:https://meowv.com/ ...
  • 前言 請了一天假後回公司,同事跟我說使用Newtonsoft.json序列化TreeView對象的時候出現報錯; 啊!什麼?這個類庫不是能夠序列化所有東西嗎?真的很懵逼,也是我第一次使用這個類庫出現問題! 問題異常 異常信息 : Newtonsoft.Json.JsonSerializationEx ...
  • 簡單瞭解下麵詞語的意思 節點:二叉樹中每個元素都稱為節點 葉子節點(簡稱:葉子):度為0的節點,葉子節點就是樹中最底段的節點,葉子節點沒有子節點,也叫終端結點 分枝節點:度不為0的結點 節點的度:二叉樹的度代表某個節點的孩子或者說直接後繼的個數,簡單說就是一個節點擁有的子樹數 樹的度: 樹中最大的結 ...
  • C# 中的LINQ 提供了兩種操作方式,查詢表達式和查詢操作符,所有的查詢表達式都有對應的查操作符類替代,查詢表達式有點“類” SQL,在代碼中寫SQL,總覺得不夠“優雅”,使用查詢操作符就顯得“優雅”很多, 本系列就來對所有的LINQ 標準操作符進行一個全面的總結,這些操作符和我上篇文章總結的Rx ...
  • 在Startup ConfigureServices 註冊本地化所需要的服務AddLocalization和 Configure<RequestLocalizationOptions> public void ConfigureServices(IServiceCollection services ...
  • 為什麼需要持久化,以及Redis持久化的RDB方式在這篇文章講的已經很透徹了,足以弔打面試官了。而且此篇內容需要RDB文章的內容支持,所以建議先看下:看完這篇還不懂Redis的RDB持久化,你們來打我! 一、什麼是AOF 它也是Redis持久化的重要手段之一,aof->Append Only Fil ...
  • 先上圖: @IT程式猿 微博網友評論: @迢書:前同事的,親眼見過 @AvenGeeker:Bug 404 @科技州:這是要逼死強迫症 @小島一瞥:哈哈哈哈哈我老家的車 最後小編整理了一套技術資料不僅能精準消除技術盲點、累計面試經驗,更可以攻剋JVM、Spring、分散式、微服務等技術難題。 海量電 ...
  • 概括來說,分三步: 1,首先找到是哪個進程的CPU占有率飆到了100%。 2,根據進程號pid,定位到是哪個線程,找到對應線程的tid。 3,導出對應線程的dump日誌文件,分析日誌文件定位具體代碼。 要解決這個問題,你應該具備以下技能: 1,linux的top命令。 2,jvm監控工具jps。 3 ...
  • 寫在最後 程式員為何害怕【別人的代碼】呢?這讓我想起一個段子。 寫這段代碼時 只有上帝和我知道他是幹嘛的 現在 只有上帝知道了 別人的代碼,似乎總意味著冗長、晦澀、凌亂,給人一種不想靠近的感覺。搞笑的是,對於一些程式員而言,即使是自己的代碼,在一段時間之後自己再拿來看,也成了【別人的代碼】... 作 ...