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 回答