3

JavaFX 2.1 でペイン上に Rectangles を動的に作成する必要があります。次に、Text を Rectangle の上で中央揃え/折り返し/切り捨てる必要があります。テキストは長方形内に収まる必要があります。次のコードを使用して、テキストを中央に配置して折り返すことができますが、テキストの長さが長すぎると、四角形からはみ出してしまいます。私は StackPane 内で Label のような動作を作成したいと考えています。基本的に、Rectangle が大きくなると Text もそれに合わせて大きくなりますが、常に Rectangle の中心に留まり、Text が Rectangle 内に収まらない場合はそれに応じて切り捨てられます。

Rectangle r;

Text t;

...

//center and wrap text within rectangle

t.wrappingWidthProperty().bind(rect.widthProperty().multiply(0.9);

t.xProperty().bind(rect.xProperty().add(rect.widthProperty().subtract(t.boundsInLocalProperty().getValue().getWidth().divide(2)));

t.yProperty().bind(rect.yProperty().add(rect.heightProperty().divide(2)));

t.setTextAlignment(TextAlignment.CENTER);

t.setTextOrigin(VPos.CENTER);

それを達成するためにどのプロパティを使用できますか、またはこれを行うためのより良い方法はありますか?

4

1 に答える 1

6

代替実装のサンプルを次に示します。

バインディング API ではなくGroup、実装でのサブクラスを使用します。layoutChildren

import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.geometry.VPos;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.*;
import javafx.stage.Stage;

public class TextInRectangle extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  public void start(final Stage stage) throws Exception {
    TextBox text = new TextBox("All roads lead to Rome", 100, 100);
    text.setLayoutX(30);
    text.setLayoutY(20);
    final Scene scene = new Scene(text, 160, 140, Color.CORNSILK);
    stage.setScene(scene);
    stage.show();
  }

  class TextBox extends Group {
    private Text text;
    private Rectangle rectangle;
    private Rectangle clip;
    public StringProperty textProperty() { return text.textProperty(); }

    TextBox(String string, double width, double height) {
      this.text = new Text(string);
      text.setTextAlignment(TextAlignment.CENTER);
      text.setFill(Color.FORESTGREEN);
      text.setTextOrigin(VPos.CENTER);
      text.setFont(Font.font("Comic Sans MS", 25));
      text.setFontSmoothingType(FontSmoothingType.LCD);

      this.rectangle = new Rectangle(width, height);
      rectangle.setFill(Color.BLACK);

      this.clip = new Rectangle(width, height);
      text.setClip(clip);

      this.getChildren().addAll(rectangle, text);
    }

    @Override protected void layoutChildren() {
      final double w = rectangle.getWidth();
      final double h = rectangle.getHeight();
      clip.setWidth(w);
      clip.setHeight(h);
      clip.setLayoutX(0);
      clip.setLayoutY(-h/2);

      text.setWrappingWidth(w * 0.9);
      text.setLayoutX(w / 2 - text.getLayoutBounds().getWidth() / 2);
      text.setLayoutY(h / 2);
    }
  }
}

サンプル アプリの出力例:

ここに画像の説明を入力

いくつかのメモ:

  1. 通常Label、ラベルの機能の一部を再作成しようとするよりも、 を使用することをお勧めします。

  2. アプローチのレイアウトはlayoutChildren、JavaFX コントロール ライブラリを実装する際に JavaFX チームが使用するものと似ています。layoutChildrenレイアウトのためにバインディングではなく 使用する理由があると思われますが、それらすべての理由が何であるかはわかりません。

  3. 単純なレイアウトの場合、JavaFX ライブラリのビルド済みコントロールとレイアウト マネージャーを使用するのが最適です (たとえば、上記のコントロールは、StackPane のラベルまたはテキストのみを使用して実装できます)。組み込みのレイアウトから必要なレイアウトを完全に取得できない場合は、それらの使用法をバインドで補います。これも非常に簡単に操作できます。そんなに使う必要はありませんlayoutChildren。おそらく、複雑なノード グループをレイアウトするためにスケールアップするだけの問題です。layoutChildrenメソッドで計算を行うと、パフォーマンスが向上し、複雑なノード グループに適用すると、操作やデバッグが容易になる可能性があります。

  4. Textのようにテキスト サイズを計算して余分な文字を a から削除することで切り詰めるStringのではなくLabel、コードsetClipはテキスト ノードを呼び出して、視覚的に四角形のサイズにクリップします。Text代わりにのように切り捨てたい場合は、切り取られたテキストの計算を行うJavaFX ユーティリティ クラスLabelのコードを参照できます。

  5. 問題のサンプル コードは、式に角かっこがなく、バインド式内でandメソッドをwrappingWidthProperty使用しているため、コンパイルされません。これは不可能です。代わりに、でリスナーを使用する必要があります。getValuegetWidthboundsInLocalProperty

また、バインディングを介してラベル付きの長方形の x、y 位置を正確に制御して、長方形の背景を持つラベルに配置されたテキストをペインに追加するデモを行う小さなサンプル アプリを作成しました。

于 2012-05-17T01:58:45.633 に答える