1

境界ペインの中央の子としてペイン (test_) があります。ウィンドウが期待どおりに引き伸ばされると、子はその領域を埋めて成長します。

次に、test_ をスケーリングします。通常はその領域の中央に配置されますが、私はそれを望まないので、その領域の左上隅に戻します。

しかし、ウィドウを引き伸ばすと、その領域の左上隅から test_ が引き離されます。なぜこれが起こるのか誰か説明できますか?以下のサンプルには、test_ のスケールを調整するスライダーが組み込まれています。

ありがとうございました。

package fxuicontrols;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ScaleTest
    extends Application
    implements ChangeListener<Number>
{
    private final Pane  test_    = new Pane();

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

    @Override
    public void start(Stage stage) throws Exception
    {
        test_.setStyle( "-fx-background-color: blue;" );

        Text    text    = new Text( "Upper left corner" );
        text.setFill( Color.WHITE );
        text.relocate( 0, 0 );
        test_.getChildren().add( text  );

        final Slider    scaler  = new Slider( .25, 1, 1 );
        scaler.valueProperty().addListener( this );
        test_.scaleXProperty().bind( scaler.valueProperty() );
        test_.scaleYProperty().bind( scaler.valueProperty() );

        BorderPane  root    = new BorderPane();
        root.setPrefSize( 250, 250 );
        root.setCenter( test_ );
        root.setBottom( scaler );

        stage.setScene( new Scene( root ) );
        stage.show();
    }

    @Override
    public void
    changed( ObservableValue<? extends Number> oVal,
                Number oldNm,
                Number newNum
    )
    {
        double  scale   = newNum.doubleValue();
        Bounds  bounds  = test_.getLayoutBounds();
        double  width   = bounds.getWidth();
        double  height  = bounds.getHeight();
        test_.setTranslateX( (scale * width - width) / 2 );
        test_.setTranslateY( (scale * height - height) / 2 );
    }
}
4

1 に答える 1

3

シーンのサイズが変更されたときにソリューションが失敗する理由は、ペインがサイズ変更可能なノードであるため、ペインのサイズが変更されるとペインのレイアウト境界が変化するためですが、変換計算ではそれを考慮していません。

以下では、Scale および Translate 変換を直接使用して、サイズ変更に関連する問題を回避しています。このサンプル コードは目的を果たしていますか?

import javafx.application.Application;
import javafx.beans.value.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.scene.transform.*;
import javafx.stage.Stage;

// demonstrates scaling a test pane with content in it.
// slide the slider at the bottom of the scene around to shrink and grow the content.
public class ScaleTest extends Application {
  public static void main(String[] args) { launch(); }
  @Override public void start(Stage stage) throws Exception {
    // create a test pane for scaling.
    Pane testPane = new Pane();
    // make the test pane background a different color if you want to see the extent of the pane.
    testPane.setStyle("-fx-background-color: blue;");

    // create some text content to place in the test pane.
    Text text = new Text("Upper left corner");
    text.setStyle("-fx-font-size: 30px;");
    text.setFill(Color.WHITE);
    text.setTextOrigin(VPos.TOP);
    testPane.getChildren().add(text);
    Scale scaleTransform = new Scale();
    testPane.getTransforms().addAll(scaleTransform, new Translate(0, 0));

    // slider to scale the test pane.
    final Slider scaler = new Slider(.25, 3, 1);
    scaleTransform.xProperty().bind(scaler.valueProperty());
    scaleTransform.yProperty().bind(scaler.valueProperty());

    // stackpane added to pad out empty space when testPane is scaled small.
    // stackpane also clips the zoomed content when it gets larger than it's standard layout.
    final StackPane stack = new StackPane();
    stack.getChildren().addAll(testPane);
    StackPane.setAlignment(testPane, Pos.TOP_LEFT);
    stack.setStyle("-fx-background-color: blue;");

    final Rectangle clip = new Rectangle();
    testPane.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
      @Override public void changed(ObservableValue<? extends Bounds> observable, Bounds oldBounds, Bounds bounds) {
        clip.setWidth(bounds.getWidth());
        clip.setHeight(bounds.getHeight());
      }
    });
    stack.setClip(clip);

    // layout everything.
    VBox layout = new VBox();
    layout.setPrefSize(250, 250);
    layout.getChildren().setAll(stack, scaler);
    VBox.setVgrow(stack, Priority.ALWAYS);

    // show the stage.
    stage.setScene(new Scene(layout));
    stage.show();
  }
}
于 2012-05-22T19:48:48.513 に答える