2013-04-01 47 views
4

這個職位是一個套件來回答我要提問時作:Transforming a shape仿射變換的圖形,沒有文字和標籤

這裏是像我想:

The text is horizontal

這裏是生成一個簡單的程序,就像你看到文本被旋轉一樣。我想水平文本:

The text is rotated

畫布進行縮放,平移,旋轉,做拉伸,因此不horizo​​ntaly顯示文本和字體大小必須極度降低(1.4)。該程序是用Java編寫的(awt和JavaFX),但問題不在於語言或技術相關,因此任何建議都是值得歡迎的。

這裏是簡單的程序:

import javafx.application.Application; 
import javafx.geometry.VPos; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.paint.Color; 
import javafx.scene.text.Font; 
import javafx.scene.text.TextAlignment; 
import javafx.stage.Stage; 

public class TransRotScale extends Application { 

    private static void drawGraph(GraphicsContext g) { 
     //--- 
     g.scale(10.0, 10.0); 
     g.rotate(Math.toDegrees(Math.atan2(-15.0, 40.0))); 
     g.translate(-8, -10); 
     //--- 
     g.setStroke(Color.DARKRED); 
     g.setLineWidth(LINE_WIDTH); 
     g.strokeLine(10, 20, 10, 30); 
     g.strokeLine(10, 30, 50, 30); 
     g.strokeLine(50, 30, 50, 35); 
     //--- 
     g.setFill(Color.BLACK); 
     g.fillOval(50-ENDPOINT_RADIUS, 35-ENDPOINT_RADIUS, 
     ENDPOINT_DIAMETER, ENDPOINT_DIAMETER); 
     g.fillOval(10-ENDPOINT_RADIUS, 20-ENDPOINT_RADIUS, 
     ENDPOINT_DIAMETER, ENDPOINT_DIAMETER); 
     //--- 
     g.setFill(Color.LIGHTSALMON); 
     g.fillOval(10-ENDPOINT_RADIUS, 30-ENDPOINT_RADIUS, 
     ENDPOINT_DIAMETER, ENDPOINT_DIAMETER); 
     g.fillOval(50-ENDPOINT_RADIUS, 30-ENDPOINT_RADIUS, 
     ENDPOINT_DIAMETER, ENDPOINT_DIAMETER); 
     //--- 
     g.setStroke(Color.DARKGRAY); 
     g.setFont(Font.font(Font.getDefault().getFamily(), 1.4)); 
     g.setLineWidth(0.1); 
     g.setTextAlign(TextAlignment.CENTER); 
     g.setTextBaseline(VPos.BOTTOM); 
     g.strokeText("[10, 20]", 10, 20-ENDPOINT_RADIUS); 
     g.setTextBaseline(VPos.TOP); 
     g.strokeText("[10, 30]", 10, 30+ENDPOINT_RADIUS); 
     g.setTextBaseline(VPos.BOTTOM); 
     g.strokeText("[50, 30]", 50, 30-ENDPOINT_RADIUS); 
     g.setTextBaseline(VPos.TOP); 
     g.strokeText("[50, 35]", 50, 35+ENDPOINT_RADIUS); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     BorderPane bp = new BorderPane(); 
     Canvas canvas = new Canvas(540, 240); 
     bp.setCenter(canvas); 
     drawGraph(canvas.getGraphicsContext2D()); 
     primaryStage.setScene(new Scene(bp)); 
     primaryStage.centerOnScreen(); 
     primaryStage.show(); 
    } 

    public static final double ENDPOINT_RADIUS = 2.0; 
    public static final double ENDPOINT_DIAMETER = 2.0*ENDPOINT_RADIUS; 
    public static final double LINE_WIDTH  = 1.0; 

    public static void main(String[] args) { 
     launch(); 
    } 
} 

在用於顯示第一圖像(目標)中的程序,我使用兩個畫布,第一畫布縮放,平移,旋轉,以進行繪製而沒有任何文本,第二個畫布僅用於水平繪製標籤,使用java.awt.geom.AffineTransform來計算座標以匹配顯示在第一個畫布中的項目。兩幅油畫都疊加顯示,透明。

+0

上午,你看OBJECTPROPERTY rotationAxisProperty(),它定義該節點的旋轉軸。 JavaFX的Node類的?這是一個屬性,你可以設置爲一個線,通過圓的中心,並將文本節點的旋轉屬性綁定到一些值... –

+0

@AlexanderKirov:我已經爲你發佈了一個答案,請檢查它。 – Aubin

回答

1

這是什麼建議Alexander Kirov,如果我沒有理解好:

import javafx.application.Application; 
import javafx.geometry.VPos; 
import javafx.scene.Scene; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Circle; 
import javafx.scene.shape.Polyline; 
import javafx.scene.text.Font; 
import javafx.scene.text.Text; 
import javafx.scene.text.TextAlignment; 
import javafx.stage.Stage; 

public class TransRotScal extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     Pane pane = new Pane(); 
     pane.setScaleX(10.0); 
     pane.setScaleY(10.0); 
     pane.setRotate(theta); 
     pane.setTranslateX(468.0); 
     pane.setTranslateY(152.0); 
     Polyline line = new Polyline(10,20, 10,30, 50,30, 50,35); 
     line.setStroke(Color.DARKRED); 
     Circle c0 = new Circle(10, 20, 2, Color.BLACK); 
     Circle c1 = new Circle(10, 30, 2, Color.LIGHTSALMON); 
     Circle c2 = new Circle(50, 30, 2, Color.LIGHTSALMON); 
     Circle c3 = new Circle(50, 35, 2, Color.BLACK); 
     Text  t0 = createText(10, 20, "[10,20]", VPos.BOTTOM); 
     Text  t1 = createText(10, 30, "[10,30]", VPos.TOP); 
     Text  t2 = createText(50, 30, "[50,30]", VPos.BOTTOM); 
     Text  t3 = createText(50, 35, "[50,35]", VPos.TOP); 
     pane.getChildren().addAll(line, c0, c1, c2, c3, t0, t1, t2, t3); 
     primaryStage.setScene(new Scene(pane)); 
     primaryStage.centerOnScreen(); 
     primaryStage.setWidth (580); 
     primaryStage.setHeight(280); 
     primaryStage.show(); 
    } 

    private Text createText(int x, int y, String label, VPos vPos) { 
     Text text = new Text(x, y, label); 
     text.setFill(Color.DARKGRAY); 
     text.setFont(Font.font(Font.getDefault().getFamily(), 1.4)); 
     text.rotateProperty().set(-theta); 
     text.textAlignmentProperty().setValue(TextAlignment.CENTER); 
     text.setX(text.getX() - text.getBoundsInLocal().getWidth()/2.0); 
     text.textOriginProperty().set(vPos); 
     if(vPos == VPos.BOTTOM) { 
     text.setY(text.getY() - 2); 
     } 
     else { 
     text.setY(text.getY() + 2); 
     } 
     return text; 
    } 

    private final double theta = Math.toDegrees(Math.atan2(-15.0, 40.0)); 

    public static void main(String[] args) { 
     launch(); 
    } 
} 

它的工作原理,但它代替畫布使用節點和文本被反覆嘗試獲得的值進行調整;(很多!) 我不知道如何計算它們

亞歷山大,你可以編輯這篇文章或張貼你自己的來完成它,在後面的情況下,我會刪除這個。

下面是結果,注意文字的周圍盤的近似位置:

Alexander Kirov answer

0

不是將字符串直接繪製到Graphics對象上,而是從字符串中創建GlyphVector,然後將其繪製到Graphics對象上?這種方法的優點是GlyphVector可以有自己的變換,你可以用它來有效地取消畫布的旋轉。我不記得創建字形的確切細節,但是您需要一個Font和一個FontRenderContext ...這兩個對象都已經可用於Graphics上下文。

+0

感謝您的建議。我會在[亞歷山大基洛夫]的建議後研究它(http://stackoverflow.com/users/1951882/alexander-kirov)。 – Aubin