2013-04-01 18 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