2017-04-07 6 views
0

今後の愚かな質問については、事前にお詫び申し上げます。JavaFXのスイングペイントコンポーネント

JPanelがjavaFX用に持っているpaintComponentsメソッドの代わりがありますか? Swingに埋め込まれているJFXPanelを使用するだけですか?

たとえば、TimelineはSwingのTimerと同じであると考えましたが、Panel/paintComponentsの対応するものは何ですか?

EDIT: たとえば、x-y座標から別の座標に円をアニメーション化するにはどうすればよいですか? (もちろん、TranslateTransitionを使わないで)

私はキャンバスで絵を描こうとしましたが、Swingでrepaint()を呼び出すのと同じように、キャンバスを常に更新する方法がわかりませんでしたか?

+0

JavaFx Canvasを使用する必要があります。 – Sedrick

+1

JavaFXのグラフィックスプリミティブは、プリズムを介して実行されます。プリズムは、多くの場合ネイティブグラフィックスツールキットに移行します。したがって、 'paintComponent'に直接相当するものはありません(ペイントする' Graphics'オブジェクトへの一般的なアクセスがないため)。 @SedrickJeffersonの示唆しているように、['Canvas'](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/Canvas.html)を使用するか、またはおそらく'子ノードとして 'Shape'と' Text'要素を必要に応じて使用して 'layoutChildren()'をオーバーライドします(次元を決定するメソッドと一緒に)。 –

+0

あなたがしようとしていることをより具体的にすることができれば、より有益な提案が得られるかもしれません。 –

答えて

1

単純なバインディングを使用して自動的にサイズ変更されるグリッドの例です。あなたはこのために使用できる様々なアプローチの束があります

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class GridTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Grid grid = new Grid(10,10); 
     Scene scene = new Scene(grid.getView()); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.scene.layout.Pane; 
import javafx.scene.shape.Line; 

public class Grid { 
    private final Pane view = new Pane(); 

    private final int numColumns ; 
    private final int numRows ; 

    // arbitrary defaults of 20: 
    private final DoubleProperty prefColumnWidth = new SimpleDoubleProperty(20); 
    private final DoubleProperty prefRowHeight = new SimpleDoubleProperty(20); 

    public Grid(int numColumns, int numRows) { 
     this.numColumns = numColumns ; 
     this.numRows = numRows ; 

     for (int x = 0 ; x <= numColumns ; x++) { 
      Line line = new Line(); 
      line.startXProperty().bind(view.widthProperty().multiply(x).divide(numColumns)); 
      line.endXProperty().bind(line.startXProperty()); 
      line.setStartY(0); 
      line.endYProperty().bind(view.heightProperty()); 
      view.getChildren().add(line); 
     } 

     for (int y = 0 ; y <= numRows ; y++) { 
      Line line = new Line(); 
      line.startYProperty().bind(view.heightProperty().multiply(y).divide(numRows)); 
      line.endYProperty().bind(line.startYProperty()); 
      line.setStartX(0); 
      line.endXProperty().bind(view.widthProperty()); 
      view.getChildren().add(line); 
     } 

     view.prefWidthProperty().bind(prefColumnWidth.multiply(numColumns)); 
     view.prefHeightProperty().bind(prefRowHeight.multiply(numRows)); 
    } 

    public final DoubleProperty prefColumnWidthProperty() { 
     return this.prefColumnWidth; 
    } 


    public final double getPrefColumnWidth() { 
     return this.prefColumnWidthProperty().get(); 
    } 


    public final void setPrefColumnWidth(final double prefColumnWidth) { 
     this.prefColumnWidthProperty().set(prefColumnWidth); 
    } 


    public final DoubleProperty prefRowHeightProperty() { 
     return this.prefRowHeight; 
    } 


    public final double getPrefRowHeight() { 
     return this.prefRowHeightProperty().get(); 
    } 


    public final void setPrefRowHeight(final double prefRowHeight) { 
     this.prefRowHeightProperty().set(prefRowHeight); 
    } 

    public Pane getView() { 
     return view; 
    } 

    public int getNumColumns() { 
     return numColumns; 
    } 

    public int getNumRows() { 
     return numRows; 
    } 

} 

は、ここで簡単なテストです。あなただけのウィンドウを作成する方法書くことができるので、上記のアプローチは本当にすべてでサブクラス化を必要としないことに注意してください:あなたは物事のAWT /春の道に近い何かを望んでいた場合、

private Pane createGrid(int numColumns, int numRows) { 

    Pane view = new Pane(); 

    for (int x = 0 ; x <= numColumns ; x++) { 
     Line line = new Line(); 
     line.startXProperty().bind(view.widthProperty().multiply(x).divide(numColumns)); 
     line.endXProperty().bind(line.startXProperty()); 
     line.setStartY(0); 
     line.endYProperty().bind(view.heightProperty()); 
     view.getChildren().add(line); 
    } 

    for (int y = 0 ; y <= numRows ; y++) { 
     Line line = new Line(); 
     line.startYProperty().bind(view.heightProperty().multiply(y).divide(numRows)); 
     line.endYProperty().bind(line.startYProperty()); 
     line.setStartX(0); 
     line.endXProperty().bind(view.widthProperty()); 
     view.getChildren().add(line); 
    } 

    view.setPrefSize(20*numColumns, 20*numRows); 
    return view ; 
} 

をまたは、 Regionをサブクラス化し、Canvasを使用して、Region.layoutChildren()を上書きすることができます。 layoutChildren()メソッドはレイアウトパスの一部として呼び出されます(リージョンがサイズを変更するとトリガーされます)。

import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.layout.Region; 

public class Grid extends Region { 

    private Canvas canvas ; 
    private final int numColumns ; 
    private final int numRows ; 

    public Grid(int numColumns, int numRows) { 
     this.numColumns = numColumns ; 
     this.numRows = numRows ; 
     canvas = new Canvas(); 
     getChildren().add(canvas); 
    } 

    @Override 
    protected void layoutChildren() { 
     double w = getWidth() - getPadding().getLeft() - getPadding().getRight() ; 
     double h = getHeight() - getPadding().getTop() - getPadding().getBottom() ; 

     canvas.setWidth(w+1); 
     canvas.setHeight(h+1); 

     canvas.setLayoutX(getPadding().getLeft()); 
     canvas.setLayoutY(getPadding().getRight()); 

     GraphicsContext gc = canvas.getGraphicsContext2D(); 
     gc.clearRect(0, 0, w, h); 

     for (int i = 0 ; i <= numColumns ; i++) { 

      // adding 0.5 here centers the line in the physical pixel, 
      // making it appear crisper: 
      double x = w*i/numColumns + 0.5; 

      gc.strokeLine(x, 0, x, h); 
     } 

     for (int j = 0 ; j <= numRows ; j++) { 
      double y = h*j/numRows + 0.5 ; 
      gc.strokeLine(0, y, w, y); 
     } 
    } 

    @Override 
    protected double computePrefWidth(double height) { 
     return 20 * numColumns; 
    } 

    @Override 
    protected double computePrefHeight(double width) { 
     return 20 * numRows ; 
    } 

} 

は、ここでは、このためのテストです:私はパディングのためのサポートを追加しました。この1でのJavaFXで

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class GridTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Grid grid = new Grid(10,10); 
     grid.setPadding(new Insets(20)); 
     Scene scene = new Scene(grid, 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

あなたがこれに与えた努力を感謝し、ありがとう、しかし、私はまだrepaint()を呼び出すことができず、それをやり遂げることができないので、なぜこれから多くの努力をしなければならないのか分かりません。 JavaFXにはSwingよりも多くの改良点があります。Swingは非常に面倒ですが、これは私にとっては大変なことでした。 – Random

+0

@MertDuman私は、行の位置を計算する 'repaint()'メソッドの定義が、行の位置をバインディングとして表現するよりも簡単であるとは思わない。コードは本質的に同一ではありませんか?ここでの利点は、このグリッドを再描画する必要があることをJavaFXが自動的に認識することです。その必要はなく、JavaFXフレームワークは再描画を最大限に最適化できます(つまり、何かが変更された場合にのみ再描画し、すべての行が変更されたときにレイアウトを再計算しません)。 –

+0

@MertDumanもう一度、私の最初のコメントで述べたように、ここの行は、おそらくネイティブ(ハードウェアアクセラレーション)グラフィックスを使用して実際に描画されたものです(おそらく、プラットフォームによって異なります)。明示的にそれらをJavaコードで描画して、実行できない場合。 –

0

、GraphicsContext描画面を持っている唯一のものはキャンバスです。キャンバスを拡張し、Canas.getGraphicsContext2D()を取得し、そこから独自のペイントを行うrepaint()メソッドを追加することができます。

さらに、ペインを拡張し、オーバーレイされたキャンバスを子ノードとして持つことができます(ペインとキャンバスの幅と高さのプロパティを一緒にバインドします)。 SwingのJPanelと同じように、カスタムペイントをサポートする(そしてキャンバスイベントを介してマウスイベントに反応する)親コンポーネントがあります。

+0

このrepaint()メソッドが最初に行うべきことは、clearRect(0、0、getWidth ()、getHeight())をキャンバスのGraphicsContextに配置します。それ以外の場合は、以前のrepaint()呼び出しで行われたすべての図面からアーティファクトを取得します。 – BinaryDigit09

+0

必要に応じて 'repaint()'メソッドが呼び出されたことを確認する方法を見つける必要があります。自動的には発生しません。 –