JavaFX - 当屏幕大小改变时调整画布大小

12

我正在处理JavaFX级别编辑器的GUI,希望能够将画布对象调整为新的拆分窗格尺寸。但似乎无论我尝试什么都失败了。这包括传递窗格对象并直接使用其宽度、使用窗口大小监听器以及将宽度和高度属性绑定到拆分窗格上。有任何想法吗?下面是调整尺寸前后的截图:

enter image description here

enter image description here

是否有人有任何想法?该类的代码相当复杂,但此处将包含调整大小的代码:

public Canvas canvas;
public String tabTitle;
public VBox layout;
public GraphicsContext g;
public Core core;

public CanvasTab(Core core, String tabTitle){
    this.core = core;
    this.canvas = new Canvas(core.scene.getWidth() - 70, core.scene.getHeight() - 70);
    layout = VBoxBuilder.create().spacing(0).padding(new Insets(10, 10, 10, 10)).children(canvas).build();
    
    this.g = canvas.getGraphicsContext2D();

    g.setFill(Color.BLACK);
    g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    
    HBox.setHgrow(layout, Priority.ALWAYS);
    
    this.setContent(layout);
    this.setText(tabTitle);
    
    canvas.widthProperty().bind(layout.widthProperty().subtract(20));
    canvas.heightProperty().bind(layout.heightProperty().subtract(20));
}

public CanvasTab(Canvas canvas){
    this.canvas = canvas;
}

1
画布(我假设)正在正确地调整大小,但是在构建画布选项卡时,您会填充黑色矩形以适应画布的大小。如果您要使用画布并希望重新调整大小,则可能需要在调整大小时重新绘制所有内容(或至少某些内容)。 - James_D
2个回答

13
正如James_D所指出的,当改变画布大小时需要重新绘制画布内容。可以通过添加监听器到画布的宽和高属性来实现此操作,代码如下:
InvalidationListener listener = new InvalidationListener(){
    @Override
    public void invalidated(Observable o) {
        redraw();       
    }           
});
canvas.widthProperty().addListener(listener);
canvas.heightProperty().addListener(listener);

或者在Java 8中使用函数接口:

canvas.widthProperty().addListener(observable -> redraw());
canvas.heightProperty().addListener(observable -> redraw());

其中redraw()是您自己的方法,根据您的示例应该长这样(画一个黑色矩形):

private void redraw() {
    g.setFill(Color.BLACK);
    g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
}

2
根据我的有限经验,您需要获取场景的widthProperty和heightProperty,而不是画布(canvas)的:https://blog.idrsolutions.com/2012/11/adding-a-window-resize-listener-to-javafx-scene/ - bbarker

7

要使JavaFx画布可调整大小,只需要覆盖最小/首选/最大方法。将其设置为可调整大小并实现resize方法。

使用此方法无需宽度/高度监听器即可触发重绘。也不再需要将宽度和高度的大小绑定到容器上。

public class ResizableCanvas extends Canvas {

@Override
public double minHeight(double width)
{
    return 64;
}

@Override
public double maxHeight(double width)
{
    return 1000;
}

@Override
public double prefHeight(double width)
{
    return minHeight(width);
}

@Override
public double minWidth(double height)
{
    return 0;
}

@Override
public double maxWidth(double height)
{
    return 10000;
}

@Override
public boolean isResizable()
{
    return true;
}

@Override
public void resize(double width, double height)
{
    super.setWidth(width);
    super.setHeight(height);
    paint();
}

请注意,resize方法不能简单地调用Node.resize(width,height),因为标准实现基本上是空的。

1
这个答案非常棒! - GOXR3PLUS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接