簡體   English   中英

Graphics2D的transform方法有什么作用?

[英]What does Graphics2D's transform method do?

在Java的Graphics2D類中,它具有轉換方法。

public abstract void transform(AffineTransform Tx)

這是根據文檔的描述:

根據后指定先應用的規則,在此Graphics2D中用Transform組成一個AffineTransform對象。 如果當前Transform為Cx,則使用Tx合成的結果為新的Transform Cx'。 Cx'成為此Graphics2D的當前Transform。 通過更新的Transform Cx'轉換點p等效於首先通過Tx轉換p,然后通過原始Transform Cx轉換結果。 換句話說,Cx'(p)= Cx(Tx(p))。 如果需要,可以復制Tx,因此對Tx的進一步修改不會影響渲染。

我已經讀過好幾次了,但我仍然不明白它的作用。 我也嘗試過尋找其他來源,但是g2d的transform方法沒有太多內容。

所以我的問題是 :轉換到底能做什么? 我們什么時候使用它?

如果有人可以簡化的方式解釋它,那就太好了。

可能的答案范圍非常廣泛,從“它按照JavaDoc所說的做”到完全引用圖形編程聖經的幾章。 我將嘗試給出一個介於兩者之間的答案。 它更接近第一個選項,但是某些鏈接導致的信息可能比掌握基本概念所必需的信息更為詳細。

Graphics2D的變換是AffineTransform ,它描述在繪制對象之前應如何變換對象。 這樣的AffineTransform是一個矩陣 ,可以將其想象為修改繪制對象所有點的位置的對象。 例如,它可以是旋轉矩陣,以便在繪制對象之前先旋轉它們。

一個示例:當您處於某些JPanelpaintComponent方法中並獲得Graphics2D ,可以執行繪圖操作:

protected void paintComponent(Graphics gr) {
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;
    ...

    // Draw a rectangle
    g.drawRect(0,0,50,100);
}

在此繪制的矩形將寬50像素,高100像素。

現在,您可以在繪制之前對Graphics2D對象應用新的變換:

protected void paintComponent(Graphics gr) {
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;
    ...

    // Obtain an AffineTransform that describes a scaling
    AffineTransform scalingTransform =      
        AffineTransform.getScaleInstance(2,2);

    // Apply the transform to the graphics
    g.transform(scalingTransform );

    // Draw a rectangle. 
    g.drawRect(0,0,50,100);
}

由於將所有內容縮放2倍的變換,現在在此處繪制的矩形將寬100像素,高200像素。您還可以使用執行旋轉的變換,例如

g.transform(AffineTransform.getRotateInstance(Math.toDegrees(45)));

以便將矩形旋轉45度。

關於API及其效果,基本上這就是transform方法所做的事情。

旁注:的確, Graphics2Drotate(...)translate(...)shear(...)scale(...)方法只是方便的方法。 代替

g.transform(AffineTransform.getRotateInstance(Math.toDegrees(45)));

你可以簡單地打電話

g.rotate(Math.toDegrees(45));

達到同樣的效果。 transform方法非常通用,因為它可以接收可能在其他位置組成的任意變換矩陣-例如,在某些其他方法中, Graphics2D對象根本不可用。


如果您想知道該方法在內部執行的操作 :這實際上很簡單。 它只是執行矩陣乘法 它將Graphics2D包含的AffineTransform與傳遞給transform方法的AffineTransform相乘。

可以想象這樣的變換矩陣的乘法以相反的順序應用相應的變換:

AffineTransform scalingByFactor2 = 
    AffineTransform.getScaleInstance(2,2);

AffineTransform rotationBy45degrees = 
    AffineTransform.getRotateInstance(Math.toDegrees(45));

g.transform(rotationBy45degrees);
g.transform(scalingByFactor2);
g.drawRect(0,0,50,100);

結果,將繪制一個矩形,即

  1. 首先在x和y方向縮放2倍
  2. 然后旋轉45度

因此,結果將是一個更大的旋轉矩形。

如果您應用了這樣的操作

g.transform(scalingByFactor2);
g.transform(rotationBy45degrees);

那么矩形將看起來像一個大的菱形物體。

根據評論進行編輯:

對象看起來不同的原因是,轉換是獨立應用的。 即,它們被應用於可能已經被其他轉換轉換的對象。 我認為矩形(或正方形)的示例在這里可能很直觀:

TransformationOrder

這與通常的繪畫或繪圖程序基本相同,在該程序中,您先將一個轉換應用於一個對象,然后再將另一個應用於對象,然后轉換的順序會影響結果。


關於transformsetTransform方法之間的區別已經有一些猜測。 正如MadProgrammer最終指出的那樣:

transform方法將圖形對象的當前變換與新transform連接在一起(即:它與矩陣相乘)。 您可以使用它來“組成”多個轉換,如上面的旋轉和縮放示例所示。

與此相反, Graphics2D#setTransform方法具有完全不同的目的,並且文檔中包含相應的警告:

警告: 永遠不要使用此方法在現有轉換之上應用新的坐標轉換

如JavaDoc示例所示,在transform調用序列之后,僅應將其用於恢復圖形的原始轉換。

您可以使用此方法修改Graphics2D對象在呈現到設備空間(例如屏幕或一張紙)中之前的顯示方式。 例如,您可以使用它來執行縮放,旋轉和剪切圖像等操作,以響應用戶按下應用程序中的“縮放/旋轉/剪切”按鈕。

Graphics2D對象帶有用於跟蹤變換的字段,該字段表示將在其中渲染對象的“設備空間”(例如1920 x 1080)的近似值。 計算此轉換並將其在運行時應用於對象,以使其在可用的屏幕不動產(或打印機頁面或投影儀顯示器等)中正確呈現。

通過應用transform(AffineTransform Tx)方法,您告訴系統要更改Graphics2D對象最終呈現時的外觀。 例如縮放或旋轉對象。 該文檔的意思是, 將原始轉換應用於適合於運行JVM的設備的顯示器之前 ,新轉換將應用於Graphics2D對象。 所有這些都發生在渲染之前。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM