我有一个ScreenController类,该类可以轻松切换JavaFX程序中的根窗格。它使用HashMap进行此操作,该HashMap使用String键存储Pane值。
我试图进行设置,以便每当将新Panes添加到SceneController对象时,它都会创建给定Pane的全屏版本,并将其添加到第二个HashMap中,该HashMap具有与第一个相同的String键。
但是,每当我现在切换屏幕时,总是使用全屏版本的窗格。
即使Java是按值传递的,我用来创建全屏窗格版本的goFullscreen()
方法似乎也在修改这两个方法。
如何在我的ScreenController类windowedRootMap中获取HashMap属性,而不用全屏缩放返回原始窗格?
/**
* Creates an appropriately scaled fullscreen version of the argument Pane object.
*
* @param contentPane The Pane to create a fullscreen version of.
* @return Pane
*/
private static Pane goFullscreen(Pane contentPane) {
// get original dimensions and their ratio.
final double windowedWidth = 1280.0;
final double windowedHeight = 800.0;
final double windowedRatio = windowedWidth / windowedHeight;
// get fullscreen width and height from monitor dimensions
final double fullscreenWidth = Screen.getPrimary().getBounds().getWidth();
final double fullscreenHeight = Screen.getPrimary().getBounds().getHeight();
// find how much to scale by
double scaleFactor;
if (fullscreenWidth / fullscreenHeight > windowedRatio)
scaleFactor = fullscreenHeight / windowedHeight;
else
scaleFactor = fullscreenWidth / windowedWidth;
// scale the contents of the Pane appropriately
Scale scale = new Scale(scaleFactor, scaleFactor);
contentPane.getTransforms().setAll(scale);
contentPane.setPrefWidth(fullscreenWidth / scaleFactor);
contentPane.setPrefWidth(fullscreenHeight / scaleFactor);
return contentPane;
}
/**
* Allows switching root nodes easily.
*/
private class ScreenController {
private HashMap<String, Pane> windowedRootMap = new HashMap<>();
private HashMap<String, Pane> fullscreenRootMap = new HashMap<>();
private Scene currentScene;
private ScreenController(Scene currentScene) {
this.currentScene = currentScene;
}
private void addScreen(String name, Pane pane) {
this.windowedRootMap.put(name, pane);
this.fullscreenRootMap.put(name, goFullscreen(pane));
}
private void activate(String name) {
this.currentScene.setRoot(this.windowedRootMap.get(name));
}
}
答案 0 :(得分:2)
您是正确的,Java是按值传递,但是传递“值”是错误的。在Java中,它是对复制对象的引用,但是新引用仍然指向同一对象 instance 。以下问题的许多出色答案对此进行了详细解释:
假设您不想维护两个不同的Pane
实例,一种选择是根据所处的模式简单地设置属性。我不确定要显示的代码是什么像最后一样,但看起来可能像这样:
import java.util.Map;
import java.util.HashMap;
import javafx.geometry.Dimension2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Scale;
public class ScreenController {
private final Map<String, Foo> map = new HashMap<>();
private final Scene scene;
public ScreenController(Scene scene) {
this.scene = scene;
}
public void register(String name, Pane pane) {
map.put(name, pane);
}
public void activate(String name) {
scene.setRoot(map.get(name).pane);
}
private static class Foo {
private final Pane pane;
private final Dimension2D normalSize;
private final Dimension2D fullScreenSize;
private final Scale scale;
private Foo(Pane pane) {
this.pane = pane;
// set the other fields...
}
private void enterFullScreenMode() {
pane.setPrefSize(fullScreenSize.getWidth(), fullScreenSize.getHeight());
pane.getTransforms().add(scale);
}
private void exitFullScreenMode() {
pane.setPrefSize(normalSize.getWidth(), normalSize.getHeight());
pane.getTransforms().remove(scale);
}
}
}
注意:我未包含任何参数或状态验证。
但是请记住,Scene
的根的大小与场景图中“常规”节点的大小不同。设置首选大小可能不会起作用。来自documentation。
应用程序必须通过设置
Node
属性来为场景图指定根root
。如果将Group
用作根,则场景图的内容将被场景的宽度和高度限制,并且更改场景的大小(如果用户调整舞台的大小)将不会更改场景图的布局。如果将可调整大小的节点(布局Region
或Control
)设置为根,则根的大小将跟踪场景的大小,从而根据需要中继内容。
如果只有一定数量的屏幕,请考虑使用enum
作为Map
的键,而不是String
。还可以看看java.util.EnumMap
。