简体   繁体   中英

Error in javaFX tableview

I make TableView in javaFX that contain two TableColumns . The width of TableView Span more than the width Of all TableColumn , but its not the problem. What I did not understand Is when I click in area outside the row that contain data, and outside area of column (red area), I get an error. Can anyone explain to me why this error occur?

run:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.handleSelectedCellsListChangeEvent(TableView.java:2657)
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.clearAndSelect(TableView.java:2180)
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.clearAndSelect(TableView.java:2140)
at com.sun.javafx.scene.control.behavior.TableRowBehavior.doSelect(TableRowBehavior.java:196)
at com.sun.javafx.scene.control.behavior.TableRowBehavior.mousePressed(TableRowBehavior.java:88)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:204)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3689)
at javafx.scene.Scene$MouseHandler.access$1800(Scene.java:3414)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1676)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2467)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:314)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:243)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:345)
at com.sun.glass.ui.View.handleMouseEvent(View.java:526)
at com.sun.glass.ui.View.notifyMouse(View.java:898)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
at java.lang.Thread.run(Thread.java:744)
BUILD SUCCESSFUL (total time: 5 seconds)

在此输入图像描述

This is my code: (btw this code based on javaFX default sample, and in that sample the error also occur)

package fjr.java.proyek.tex;

//import java.awt.TextField;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ChangeCurrentFrame  extends Application{

    double width = 400; 
    double height = 400; 

    public void start(Stage stage) throws Exception {
        Group root = new Group(); 
        stage.setScene(new Scene (root , width, height)); 
        root.getChildren().add(getTable()); 
        stage.show();
    }

    public TableView<CurrentFrame > getTable(){
        TableView<CurrentFrame> tabel = new TableView<CurrentFrame>(); 
        TableColumn<CurrentFrame, Boolean> stateColumn = new TableColumn<CurrentFrame, Boolean>(); 
        stateColumn.setText("Is Compile"); 
        stateColumn.setMinWidth(60);        
        stateColumn.setCellValueFactory(new PropertyValueFactory<CurrentFrame, Boolean>("enable")) ; 
        stateColumn.setCellFactory(new Callback<TableColumn<CurrentFrame, Boolean>, 
                TableCell<CurrentFrame, Boolean>>(){
            @Override
            public TableCell<CurrentFrame, Boolean> call(
                    TableColumn< CurrentFrame, Boolean> p ){
                return new TableCell<CurrentFrame, Boolean>(){
                    private CheckBox checkBox; 
                    private ObservableValue<Boolean>  ov; 

                    {
                        checkBox = new CheckBox(); 
                        checkBox.setAlignment(Pos.CENTER); 
                        setAlignment(Pos.CENTER); 
                        setGraphic(checkBox);
                    }

                    @Override public void updateItem(Boolean item, boolean empty){
                        super.updateItem(item, empty); 
                        if(empty){
                            setText(null);
                            setGraphic(null);
                        }else{
                            setGraphic(checkBox);
                            if(ov instanceof BooleanProperty){
                                checkBox.selectedProperty(). unbindBidirectional((BooleanProperty) ov);
                            }
                            ov = getTableColumn().getCellObservableValue(getIndex()); 
                            if(ov instanceof BooleanProperty){
                                checkBox.selectedProperty(). bindBidirectional((BooleanProperty) ov);
                            }
                        }
                    }
                };
            }
        }); 

        TableColumn<CurrentFrame, String> nameColumn = new TableColumn<CurrentFrame, String>(); 
        nameColumn.setText("Label"); 
        nameColumn.setMinWidth(80); 
        nameColumn.setCellValueFactory(new PropertyValueFactory<CurrentFrame, String>("name"));
        nameColumn.setCellFactory(new Callback<TableColumn<CurrentFrame, String>, 
                TableCell<CurrentFrame, String>>() {
                    @Override
                    public TableCell<CurrentFrame, String> call(
                            TableColumn<CurrentFrame, String> arg0) {
                        return new TableCell<CurrentFrame,String>(){

                            private TextField textField; 

                            @Override public void startEdit(){
                                super.startEdit();
                                if(textField == null){
                                    createTextField();
                                }
                                setText(null);
                                setGraphic(textField);
                                textField.selectAll();
                            }

                            @Override public void cancelEdit(){
                                super.cancelEdit(); 
                                setText((String) getItem()); 
                                setGraphic(null); 
                            }

                            @Override public void updateItem(String item, boolean empty){
                                super.updateItem(item, empty);
                                if(empty){
                                    setText(null); 
                                    setGraphic(null);
                                }else{
                                    if(isEditing()){
                                        if(textField != null){
                                            textField.setText(getString());
                                        }
                                        setText(null);
                                        setGraphic(textField);
                                    }else{
                                        setText(getString()); 
                                        setGraphic(null);
                                    }
                                }
                            }

                            private String getString(){
                                return getItem() == null ? "" : getItem().toString(); 
                            }

                            private void createTextField(){
                                textField = new TextField(getString()); 
                                textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
                                textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
                                    @Override
                                    public void handle(KeyEvent t) {
                                        if(t.getCode() == KeyCode.ENTER){
                                            commitEdit(textField.getText());
                                        }else if(t.getCode() == KeyCode.ESCAPE){
                                            cancelEdit();
                                        }
                                    }
                                });
                            }

                        };
                    }
        });

        nameColumn.setOnEditCommit(new EventHandler<CellEditEvent<CurrentFrame, String >>() {
            @Override
            public void handle(CellEditEvent<CurrentFrame, String> t) {
                   ((CurrentFrame) t.getTableView().getItems().get(
                            t.getTablePosition().getRow())).setName(t.getNewValue());
            }
        });


        tabel.setItems(getData());
        tabel.setEditable(true); 
        tabel.getColumns().addAll(stateColumn, nameColumn);  

        return tabel ; 
    }

    public  ObservableList<CurrentFrame> getData(){
        return FXCollections.observableArrayList(
                new CurrentFrame(true, "makan"), 
                new CurrentFrame(false, "siang"), 
                new CurrentFrame(false, "jangan"), 
                new CurrentFrame(true, "suka"), 
                new CurrentFrame(false, "ribut")) ; 
    }

    public static  class CurrentFrame { // ini harus publik ya.... 
        private BooleanProperty  isEnable; 
        private StringProperty framename; 

        private  CurrentFrame(boolean enable, String name){
            this.isEnable = new SimpleBooleanProperty(enable); 
            this.framename = new SimpleStringProperty(name);    
            isEnable.addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0,
                        Boolean t2, Boolean t1) {
                    System.out.println(nameProperty().get()+" enable "+ t1 ); 
                }
            });
        }

        public void setEnable(boolean state){
            isEnable.set(state);
        }

        public void setName(String name){
            this.framename.set(name);
        }

        public BooleanProperty enableProperty(){
            return isEnable; 
        }

        public StringProperty nameProperty(){
            return framename; 
        }
    }   

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

}

The bug is still present in Java 8u11, but there is a workaround:

table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

this prevents the area right to all the columns from being visible, thus no more stack traces. The downside of this is that all columns will be resized to fit the table width.

I believe I found an existing bug report for this:

https://javafx-jira.kenai.com/browse/RT-35338

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM