简单的javafx事件处理程序抛出异常

时间:2013-07-26 19:34:27

标签: exception event-handling treeview javafx

从示例13-3“实现单元工厂” http://docs.oracle.com/javafx/2/ui_controls/tree-view.htm 并添加行

box.addEventHandler(EventType.ROOT, new EventHandler<Event>() {
@Override
    public void handle(Event event) {
         System.out.println("event "+event);
    }
});
方法中,双击时会抛出以下异常 员工节点:

java.lang.ClassCastException: javafx.scene.layout.VBox cannot be cast to javafx.scene.control.TreeView
    at javafx.scene.control.TreeView$EditEvent.getSource(TreeView.java:988)
    at javafx.scene.control.TreeView$EditEvent.getSource(TreeView.java:965)
    at com.sun.javafx.event.EventHandlerManager.fixEventSource(EventHandlerManager.java:225)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:216)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:6863)
    at javafx.scene.control.TreeCell.startEdit(TreeCell.java:315)
    at test.TreeViewSample$TextFieldTreeCellImpl.startEdit(TreeViewSample.java:100)
    at javafx.scene.control.TreeCell.updateEditing(TreeCell.java:435)
    at javafx.scene.control.TreeCell.access$500(TreeCell.java:67)
    at javafx.scene.control.TreeCell$6.invalidated(TreeCell.java:151)
    at javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:80)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:359)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
    at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163)
    at javafx.scene.control.TreeView.setEditingItem(TreeView.java:573)
    at javafx.scene.control.TreeView.edit(TreeView.java:771)
    at com.sun.javafx.scene.control.behavior.TreeCellBehavior.simpleSelect(TreeCellBehavior.java:257)
    at com.sun.javafx.scene.control.behavior.TreeCellBehavior.doSelect(TreeCellBehavior.java:213)
    at com.sun.javafx.scene.control.behavior.TreeCellBehavior.mouseReleased(TreeCellBehavior.java:132)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3328)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3168)
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3123)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2265)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
    at com.sun.glass.ui.View.notifyMouse(View.java:922)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
    at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
    at java.lang.Thread.run(Unknown Source)

这是一个错误还是我错了?

完整的示例代码(您需要在同一目录中包含“root.png”和“department.png”文件):

package test;

import java.util.*;

import javafx.application.*;
import javafx.beans.property.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.stage.*;
import javafx.util.*;

public class TreeViewSample extends Application {

private final Node rootIcon = 
    new ImageView(new Image(getClass().getResourceAsStream("root.png")));
private final Image depIcon = 
    new Image(getClass().getResourceAsStream("department.png"));
List<Employee> employees = Arrays.<Employee>asList(
        new Employee("Ethan Williams", "Sales Department"),
        new Employee("Emma Jones", "Sales Department"),
        new Employee("Michael Brown", "Sales Department"),
        new Employee("Anna Black", "Sales Department"),
        new Employee("Rodger York", "Sales Department"),
        new Employee("Susan Collins", "Sales Department"),
        new Employee("Mike Graham", "IT Support"),
        new Employee("Judy Mayer", "IT Support"),
        new Employee("Gregory Smith", "IT Support"),
        new Employee("Jacob Smith", "Accounts Department"),
        new Employee("Isabella Johnson", "Accounts Department"));
TreeItem<String> rootNode = 
    new TreeItem<String>("MyCompany Human Resources", rootIcon);

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

@Override
public void start(Stage stage) {
    rootNode.setExpanded(true);
    for (Employee employee : employees) {
        TreeItem<String> empLeaf = new TreeItem<String>(employee.getName(), new ImageView(depIcon));
        boolean found = false;
        for (TreeItem<String> depNode : rootNode.getChildren()) {
            if (depNode.getValue().contentEquals(employee.getDepartment())){
                depNode.getChildren().add(empLeaf);
                found = true;
                break;
            }
        }
        if (!found) {
            TreeItem<String> depNode = new TreeItem<String>(
                employee.getDepartment(), 
                new ImageView(depIcon)
            );
            rootNode.getChildren().add(depNode);
            depNode.getChildren().add(empLeaf);
        }
    }

    stage.setTitle("Tree View Sample");
    VBox box = new VBox();
    final Scene scene = new Scene(box, 400, 300);
    scene.setFill(Color.LIGHTGRAY);

    TreeView<String> treeView = new TreeView<String>(rootNode);
    treeView.setEditable(true);
    treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){
        @Override
        public TreeCell<String> call(TreeView<String> p) {
            return new TextFieldTreeCellImpl();
        }
    });

    box.getChildren().add(treeView);
    stage.setScene(scene);
    stage.show();

    box.addEventHandler(EventType.ROOT, new EventHandler<Event>() {
        @Override
        public void handle(Event event) {
            System.out.println("event "+event);
        }
    });
}

private final class TextFieldTreeCellImpl extends TreeCell<String> {

    private TextField textField;

    public TextFieldTreeCellImpl() {
    }

    @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(getTreeItem().getGraphic());
        System.out.println(" item canceled "+getItem());
    }

    @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(getTreeItem().getGraphic());
            }
        }
    }

    private void createTextField() {
        textField = new TextField(getString());
        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();
                }
            }
        });
    }

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

public static class Employee {

    private final SimpleStringProperty name;
    private final SimpleStringProperty department;

    private Employee(String name, String department) {
        this.name = new SimpleStringProperty(name);
        this.department = new SimpleStringProperty(department);
    }

    public String getName() {
        return name.get();
    }

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

    public String getDepartment() {
        return department.get();
    }

    public void setDepartment(String fName) {
        department.set(fName);
    }
}

}

1 个答案:

答案 0 :(得分:1)

确实他们的代码存在一些问题。 您可以通过删除以下行来避免此异常:

    box.addEventHandler(EventType.ROOT, new EventHandler<Event>() {
         @Override
         public void handle(Event event) {
                System.out.println("event "+event);
         }
    });

这是问题的根源。 Vbox捕获每个抛出的事件(因为你告诉它使用EventType.ROOT)。我怀疑它会在你双击时捕获TreeCell或TreeView抛出的事件。

使用它会更好,因为它只会捕获用户的输入事件:

    box.addEventHandler(InputEvent.ANY , new EventHandler<InputEvent>()