`Scene` 在 JavaFX 中的默认布局管理器是 `Pane`。

huangapple go评论110阅读模式
英文:

What is the default layout manager for a `Scene` in JavaFX?

问题

这是我根据JavaFX/OpenJFX中TableView的Javadoc中示例代码的版本。(Person类是一个只读的record。)

package work.basil.example.jfxexample;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

import java.util.List;

public class HelloApplication extends Application
{
    @Override
    public void start ( Stage stage )
    {
        TableView < Person > tableViewPersons = new TableView <> ( );
        ObservableList < Person > persons = FXCollections.observableArrayList ( this.fetchPersons ( ) );
        tableViewPersons.setItems ( persons );

        TableColumn < Person, String > firstNameCol = new TableColumn <> ( "First Name" );
        firstNameCol.setCellValueFactory (   ( TableColumn.CellDataFeatures < Person, String > p ) -> new SimpleStringProperty (p.getValue().getFirstName ()));

        TableColumn < Person, String > lastNameCol = new TableColumn <> ( "Last Name" );
        lastNameCol.setCellValueFactory (   ( TableColumn.CellDataFeatures < Person, String > p ) -> new SimpleStringProperty (p.getValue().getLastName ()));

        List < TableColumn < Person, ? > > columns = List.of ( firstNameCol , lastNameCol );  // <--- Adding this line to make explicit the parameterized type of `TableColumn` to resolve the "Unchecked generics" warning.
        tableViewPersons.getColumns ( ).setAll ( columns );

        Scene scene = new Scene ( tableViewPersons , 320 , 240 );
        stage.setTitle ( "JavaFX Example" );
        stage.setScene ( scene );
        stage.show ( );
    }

    private List < Person > fetchPersons ( )
    {
        return List.of (
                new Person ( "William" , "Reed" ) ,
                new Person ( "James" , "Michaelson" ) ,
                new Person ( "Julius" , "Dean" ) );
    }

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

这个应用程序展示了一个填满窗口的表格视图。调整窗口大小会导致TableView控件也被调整大小,以继续填充窗口。

👉🏼 这个示例中Scene的默认布局管理器是什么?

英文:

Here is my version of the example code shown in the Javadoc for TableView in JavaFX/OpenJFX. (The Person class is a record, read-only.)

package work.basil.example.jfxexample;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

import java.util.List;

public class HelloApplication extends Application
{
    @Override
    public void start ( Stage stage )
    {
        TableView &lt; Person &gt; tableViewPersons = new TableView &lt;&gt; ( );
        ObservableList &lt; Person &gt; persons = FXCollections.observableArrayList ( this.fetchPersons ( ) );
        tableViewPersons.setItems ( persons );

        TableColumn &lt; Person, String &gt; firstNameCol = new TableColumn &lt;&gt; ( &quot;First Name&quot; );
        firstNameCol.setCellValueFactory (   ( TableColumn.CellDataFeatures &lt; Person, String &gt; p ) -&gt; new SimpleStringProperty (p.getValue().getFirstName ()));

        TableColumn &lt; Person, String &gt; lastNameCol = new TableColumn &lt;&gt; ( &quot;Last Name&quot; );
        lastNameCol.setCellValueFactory (   ( TableColumn.CellDataFeatures &lt; Person, String &gt; p ) -&gt; new SimpleStringProperty (p.getValue().getLastName ()));

        List &lt; TableColumn &lt; Person, ? &gt; &gt; columns = List.of ( firstNameCol , lastNameCol );  // &lt;--- Adding this line to make explicit the parameterized type of `TableColumn` to resolve the &quot;Unchecked generics&quot; warning.
        tableViewPersons.getColumns ( ).setAll ( columns );

        Scene scene = new Scene ( tableViewPersons , 320 , 240 );
        stage.setTitle ( &quot;JavaFX Example&quot; );
        stage.setScene ( scene );
        stage.show ( );
    }

    private List &lt; Person &gt; fetchPersons ( )
    {
        return List.of (
                new Person ( &quot;William&quot; , &quot;Reed&quot; ) ,
                new Person ( &quot;James&quot; , &quot;Michaelson&quot; ) ,
                new Person ( &quot;Julius&quot; , &quot;Dean&quot; ) );
    }

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

This app presents a window filled with the table view. Resizing the window results in the TableView control being resized as well, to continue filling the window.

`Scene` 在 JavaFX 中的默认布局管理器是 `Pane`。

👉🏼 What is the default layout manager of the Scene in this example?

答案1

得分: 7

在JavaFX中没有布局管理器。
Scence API文档说明了Scene在调整大小时的行为:

如果使用Group作为根节点,场景图的内容将被场景的宽度和高度裁剪,而场景的大小变化(如果用户调整舞台大小)不会改变场景图的布局。如果将可调整大小的节点(布局区域或控件)设置为根节点,则根节点的大小将跟踪场景的大小,必要时重新布局内容。

由于TableView是一个Control,所以你得到的是后一种行为,也是你所看到的行为。

英文:

There are no layout managers in JavaFX.
The Scence API documentation states how Scene behaves on resizing:
> If a Group is used as the root, the contents of the scene graph will be clipped by the scene's width and height and changes to the scene's size (if user resizes the stage) will not alter the layout of the scene graph. If a resizable node (layout Region or Control) is set as the root, then the root's size will track the scene's size, causing the contents to be relayed out as necessary.

Since TableView is a Control, the latter behavior is what you get and what you see.

答案2

得分: 4

正如在另一个答案中指出的那样,JavaFX没有显式的布局管理器(与AWT和因此Swing不同),并且在调整Scene的大小时的行为(例如,当用户调整包含它的窗口的大小)在API文档中有描述。

将问题

> 这个示例中Scene的默认布局管理器是什么?

更一般地理解为“Scene默认如何执行布局”,实际上当场景改变大小时,它会在根节点上调用resize(...),传入新的宽度和高度。

(请注意,尽管这是“默认”行为,但它也是唯一的行为:它无法更改。)

Node中定义的resize(...)的实际实现是一个空操作,这被ParentGroup继承。因此,如果根节点是Group的实例,则实际上什么都不会发生。

另一方面,Region重写了resize(...),将其宽度和高度设置为传入的值,从而导致作为Region实例的根节点的大小跟踪场景的大小。更改大小会触发对下一个渲染脉冲中的layout()的调用。

layout()是一个final方法,首先调用layoutChildren()(可重写并应调整子节点的大小和位置),然后迭代调用任何作为Parent实例的子节点的layout()

因此,调整根节点为Region实例的Scene的实际效果取决于该根节点的layoutChildren()的实现。对于Control(例如TableView),它被委托给skinSkin还定义了一个layoutChildren()方法,其实现确定控件的各个组件在新的宽度和高度下的布局方式。

因此,在您的示例中,TableView的大小设置为控件的大小(由Regionresize()的实现),然后根据TableViewSkin的实现对表视图进行布局。

英文:

As pointed out in another answer, JavaFX does not have explicit layout managers (as AWT, and consequently Swing, does), and the behavior when resizing a Scene (for example, when the user resizes the window containing it) is described in the API documentation.

Taking the question

> What is the default layout manager of the Scene in this example?

to more generally mean "how does a Scene perform layout by default", what actually happens when a scene changes size is that it invokes resize(...) on the root node, passing in its new width and height.

(Note that while this is the "default" behavior, it is also the only behavior: it cannot be changed.)

The actual implementation of resize(...) defined in Node is a no-op, and this is inherited by both Parent and Group. So if the root node is an instance of Group, nothing actually happens.

Region, on the other hand, overrides resize(...) to set its width and height to the values passed in, thereby causing the size of a root that is an instance of Region to track the size of the scene. Changing the size triggers a call to layout() on the next rendering pulse.

layout(), which is a final method, is defined to first call layoutChildren() (which is overridable and should resize and position the child nodes), and then iteratively call layout() on any child nodes which are instances of Parent.

So the actual effect of resizing the Scene whose root is an instance of Region is determined by the implementation of layoutChildren() for that root. In the case of a Control, such as TableView, it is delegated to the skin. Skin additionally defines a layoutChildren() method whose implementation determines how the various components of the control are laid out in the new width and height.

Consequently in your example, the size of the TableView is set to the size of the control (by the implementation of resize() in Region), and the table view is then laid out according to the implementation of TableViewSkin.

huangapple
  • 本文由 发表于 2023年8月9日 15:02:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76865337.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定