JavaFX TableView列适合内容

JavaFX TableView列适合内容,java,javafx,tableview,Java,Javafx,Tableview,我想调整一些TableView列的大小,因为javafx中缺少实现这一点的方法,我设法找到了MainApp.GUIUtil.fitColumns(TableView TableView) 我的问题是:当用户操作调用此解决方案时,它可以正常工作,但在进行任何用户干预之前,我找不到在启动时运行此方法的方法。 我想在表中显示安装了列的表。 如您所见,我截获了引起我头痛的异常(PersonTableController.setMainApp第32行),打印堆栈跟踪,然后让程序在控制给用户后继续证明fit

我想调整一些
TableView
列的大小,因为javafx中缺少实现这一点的方法,我设法找到了
MainApp.GUIUtil.fitColumns(TableView TableView)

我的问题是:当用户操作调用此解决方案时,它可以正常工作,但在进行任何用户干预之前,我找不到在启动时运行此方法的方法。
我想在表中显示安装了列的表。
如您所见,我截获了引起我头痛的
异常(PersonTableController.setMainApp第32行),打印堆栈跟踪,然后让程序在控制给用户后继续证明fit方法有效。
一旦显示tableview,如何通过代码调整列的大小

    Exception in Application start method
java.lang.reflect.InvocationTargetException
    ...
Caused by: java.lang.RuntimeException: Exception in Application start method
    ...
Caused by: java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at columnstofit.MainApp$GUIUtil.fitColumns(MainApp.java:120)
    at columnstofit.PersonTableController.setMainApp(PersonTableController.java:35)
    at columnstofit.MainApp.showPersonTable(MainApp.java:79)
    at columnstofit.MainApp.start(MainApp.java:65)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    ... 1 more
Exception running application columnstofit.MainApp
这是我的密码:

package columnstofit;

import com.sun.javafx.scene.control.skin.TableViewSkin;
import java.awt.AWTException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class MainApp extends Application {

    private       PersonTableController controller;
    public static Stage                 primaryStage;
                  AnchorPane            personTable;

    private ObservableList<Person> personData = FXCollections.observableArrayList();

    /**
     * Constructor
     */
    public MainApp() {
        // i am entering this name just to force the resizing of the column
        personData.add(new Person("Hansgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg", "Muster"));
        personData.add(new Person("Ruth", "Mueller"));
        personData.add(new Person("Heinz", "Kurz"));
        personData.add(new Person("Cornelia", "Meier"));
        personData.add(new Person("Werner", "Meyer"));
        personData.add(new Person("Lydia", "Kunz"));
        personData.add(new Person("Anna", "Best"));
        personData.add(new Person("Stefan", "Meier"));
    }

    /**
     * Returns the data as an observable list of Persons. 
     * @return
     */
    public ObservableList<Person> getPersonData() {
        return personData;
    }

    @Override
    public void start(Stage primaryStage) throws AWTException  {

        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("Names Table");

        showPersonTable();
    }

    public void showPersonTable() throws AWTException {

        try 
        {
            // Load root layout from fxml file.
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("PersonTable.fxml"));
            personTable = (AnchorPane) loader.load();

            // Give the controller access to the main app.
            controller = loader.getController();
            controller.setMainApp(this);

            Scene scene = new Scene(personTable);
            primaryStage.setScene(scene);
            primaryStage.show();
        } 
        catch (IOException e) { e.printStackTrace(); }
    }

    /**
     * Returns the main stage.
     * @return
     */
    public Stage getPrimaryStage() {
        return primaryStage;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }


    public static class GUIUtil {
        private static Method columnToFitMethod;

        static 
        {
            try 
            {
                columnToFitMethod = TableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
                columnToFitMethod.setAccessible(true);
            } 
            catch (NoSuchMethodException e) {e.printStackTrace();}
        }

        public static void fitColumns(TableView tableView) {
            for (Object column : tableView.getColumns()) 
            {
                try { columnToFitMethod.invoke(tableView.getSkin(), column, -1); } 
                catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }
            }
        }
    }

    public class Person {
        private final StringProperty firstName;
        private final StringProperty lastName;

        public Person() {
            this(null, null);
        }

        public Person(String firstName, String lastName) {
            this.firstName  = new SimpleStringProperty(firstName);
            this.lastName   = new SimpleStringProperty(lastName);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String firstName) {
            this.firstName.set(firstName);
        }

        public StringProperty firstNameProperty() {
            return firstName;
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String lastName) {
            this.lastName.set(lastName);
        }

        public StringProperty lastNameProperty() {
            return lastName;
        }
    }
}  
package-columnstofit;
导入com.sun.javafx.scene.control.skin.TableViewSkin;
导入java.awt.AWTException;
导入java.io.IOException;
导入java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.fxml.fxmloader;
导入javafx.scene.scene;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.layout.ancorpane;
导入javafx.stage.stage;
公共类MainApp扩展应用程序{
私有PersonTableController;
公共静态阶段初级阶段;
可人的锚烷;
私有ObservableList personData=FXCollections.observableArrayList();
/**
*建造师
*/
公共MainApp(){
//我输入此名称只是为了强制调整列的大小
添加(新的人(“Hansggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg;
新增(新人(“露丝”、“米勒”);
添加(新人物(“亨氏”、“库尔兹”);
添加(新人物(“科妮莉亚”、“梅尔”);
添加(新的人(“沃纳”、“迈耶”);
添加(新人物(“莉迪亚”、“昆兹”);
添加(新人物(“安娜”,“最佳”));
添加(新人物(“Stefan”、“Meier”);
}
/**
*将数据作为可观察的人员列表返回。
*@返回
*/
公共观察列表getPersonData(){
返回个人数据;
}
@凌驾
public void start(Stage primaryStage)抛出AWTException{
this.primaryStage=primaryStage;
this.primaryStage.setTitle(“名称表”);
showPersonTable();
}
public void showPersonTable()引发AWTExException{
尝试
{
//从fxml文件加载根布局。
FXMLLoader=新的FXMLLoader();
setLocation(MainApp.class.getResource(“PersonTable.fxml”);
personTable=(AnchorPane)loader.load();
//让控制器访问主应用程序。
controller=loader.getController();
controller.setMainApp(这个);
场景=新场景(personTable);
初级阶段。场景(场景);
primaryStage.show();
} 
catch(IOE异常){e.printStackTrace();}
}
/**
*返回主阶段。
*@返回
*/
公共阶段getPrimaryStage(){
返回初级阶段;
}
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
发射(args);
}
公共静态类GUIUtil{
私有静态方法columnToFitMethod;
静止的
{
尝试
{
ColumntOffitMethod=TableViewSkin.class.getDeclaredMethod(“ResizeColumntOffitContent”,TableColumn.class,int.class);
columnToFitMethod.setAccessible(true);
} 
catch(NoSuchMethodException){e.printStackTrace();}
}
公共静态列(TableView TableView){
for(对象列:tableView.getColumns())
{
请尝试{columnToFitMethod.invoke(tableView.getSkin(),column,-1);}
catch(IllegalAccessException | InvocationTargetException e){e.printStackTrace();}
}
}
}
公共阶层人士{
私有财产名;
私有财产姓氏;
公众人士(){
这个(空,空);
}
公众人物(字符串名、字符串名){
this.firstName=新的SimpleStringProperty(firstName);
this.lastName=新的SimpleStringProperty(lastName);
}
公共字符串getFirstName(){
返回firstName.get();
}
public void setFirstName(字符串firstName){
this.firstName.set(firstName);
}
public StringProperty firstNameProperty(){
返回名字;
}
公共字符串getLastName(){
返回lastName.get();
}
public void setLastName(字符串lastName){
this.lastName.set(lastName);
}
公共StringProperty lastNameProperty(){
返回姓氏;
}
}
}  
下面是FXML文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="columnstofit.PersonTableController">
    <TableView fx:id="tableView" layoutX="-39.0" layoutY="39.0" onKeyPressed="#fitColumns" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                    <columns>
                      <TableColumn fx:id="firstNameColumn" editable="false" minWidth="-1.0" prefWidth="-1.0" text="First Name" />
                      <TableColumn fx:id="lastNameColumn" editable="false" minWidth="-1.0" prefWidth="-1.0" text="Last Name" />
                    </columns>
                     <columnResizePolicy>
                        <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                     </columnResizePolicy>
                  </TableView>
</AnchorPane>


,但如果我这样做,什么也不会发生。

所以,区别在于您添加了

try
{
    fitColumns();
}
catch (Exception e) {
    e.printStackTrace();
}
在控制器的
setMainApp
方法中。 正如所指出的,抛出null指针异常是因为此时尚未安装皮肤

您可以使用控制器中的更新
setMainApp
方法解决此问题,例如:

public void setMainApp(MainApp mainApp) {
    this.mainApp = mainApp;
    tableView.setItems(mainApp.getPersonData());
    if(mainApp.primaryStage.isShowing())
        fitColumns();
    else {
        mainApp.primaryStage.showingProperty().addListener((obs, oldVal, newVal) -> {
            if(newVal)
                fitColumns();
        });
    }
}
这将检查
应用程序的
阶段是否显示,若显示,
public void setMainApp(MainApp mainApp) {
    this.mainApp = mainApp;
    tableView.setItems(mainApp.getPersonData());
    if(mainApp.primaryStage.isShowing())
        fitColumns();
    else {
        mainApp.primaryStage.showingProperty().addListener((obs, oldVal, newVal) -> {
            if(newVal)
                fitColumns();
        });
    }
}