英文:
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 < 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 ( );
}
}
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.
👉🏼 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(...)
的实际实现是一个空操作,这被Parent
和Group
继承。因此,如果根节点是Group
的实例,则实际上什么都不会发生。
另一方面,Region
重写了resize(...)
,将其宽度和高度设置为传入的值,从而导致作为Region
实例的根节点的大小跟踪场景的大小。更改大小会触发对下一个渲染脉冲中的layout()
的调用。
layout()
是一个final
方法,首先调用layoutChildren()
(可重写并应调整子节点的大小和位置),然后迭代调用任何作为Parent
实例的子节点的layout()
。
因此,调整根节点为Region
实例的Scene
的实际效果取决于该根节点的layoutChildren()
的实现。对于Control
(例如TableView
),它被委托给skin。Skin
还定义了一个layoutChildren()
方法,其实现确定控件的各个组件在新的宽度和高度下的布局方式。
因此,在您的示例中,TableView
的大小设置为控件的大小(由Region
中resize()
的实现),然后根据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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论