在JavaFX中,当我使用TreeView时,每当我点击主菜单(有子菜单)时,有时它们会“卡住”并且不会显示它们的子菜单。
在10次点击中,7次没关系,3次没有。我观察到,如果我点击我所在的另一个主菜单,问题就会出现。例如:
>File
New File
Open File
Close
>Tools
Settings
所以,如果我点击:文件,它会显示它的子菜单(新建,打开,关闭)。如果我再次单击它,它会关闭子菜单。的 BUT!
当我点击另一个子菜单时,就像“设置”一样,点击文件后(展开或折叠它的子菜单),我收到以下错误信息:
java.lang.NullPointerException
at utiokos_program.FoablakController$1.changed(FoablakController.java:166)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
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.SelectionModel.setSelectedItem(SelectionModel.java:101)
at javafx.scene.control.MultipleSelectionModelBase$1.invalidated(MultipleSelectionModelBase.java:65)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:195)
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:161)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163)
at javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:67)
at javafx.scene.control.MultipleSelectionModelBase.shiftSelection(MultipleSelectionModelBase.java:253)
at javafx.scene.control.TreeView$TreeViewBitSetSelectionModel$2.handle(TreeView.java:1114)
at javafx.scene.control.TreeView$TreeViewBitSetSelectionModel$2.handle(TreeView.java:1059)
at com.sun.javafx.scene.control.WeakEventHandler.handle(WeakEventHandler.java:62)
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
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.control.TreeItem.fireEvent(TreeItem.java:713)
at javafx.scene.control.TreeItem.access$300(TreeItem.java:197)
at javafx.scene.control.TreeItem$5.invalidated(TreeItem.java:529)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:127)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:161)
at javafx.beans.property.BooleanProperty.setValue(BooleanProperty.java:81)
at javafx.scene.control.TreeItem.setExpanded(TreeItem.java:509)
at com.sun.javafx.scene.control.behavior.TreeCellBehavior.doSelect(TreeCellBehavior.java:192)
at com.sun.javafx.scene.control.behavior.TreeCellBehavior.mousePressed(TreeCellBehavior.java:122)
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:335)
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.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:3369)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3209)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3164)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1582)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2267)
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:530)
at com.sun.glass.ui.View.notifyMouse(View.java:924)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67)
at java.lang.Thread.run(Thread.java:744)
我再次点击它,它没关系,它再次显示它是潜艇! (现在文件是我点击的最后一个而不是设置)
//一种可能的解决方案是禁用树视图的崩溃,然后我每次都在扩展模式下使用它。是否可以在JavaFX Treeview中禁用折叠?
//我根据要求复制整个FoablakController.java
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.application.Platform;
import javafx.scene.layout.StackPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Node;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.Event;
import javafx.event.EventDispatchChain;
import javafx.event.EventDispatcher;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
public class FoablakController implements Initializable {
public Windows operation = null;
private final Node fileicon = new ImageView(new Image(getClass().getResourceAsStream("file.png")));
private final Node editicon = new ImageView(new Image(getClass().getResourceAsStream("edit.png")));
private final Node windowsicon = new ImageView(new Image(getClass().getResourceAsStream("windows.png")));
private final Node toolsicon = new ImageView(new Image(getClass().getResourceAsStream("tools.png")));
private final Node helpicon = new ImageView(new Image(getClass().getResourceAsStream("help.png")));
@FXML
public static StackPane menuholder;
@FXML
public static StackPane main_right;
@FXML
public static StackPane help_right;
@FXML
public static StackPane contact_right;
@FXML
public static StackPane settings_right;
@FXML
public static StackPane contrast_right;
@FXML
public static StackPane comments_right;
@FXML
public static StackPane nice_right;
@FXML
public static StackPane faq_right;
@FXML
public TextArea summary;
@FXML
public static TextArea textArea_help_summary;
@FXML
public Button btn_print;
@FXML
public void Quitgomb (ActionEvent event) {
Platform.exit();
}
public void ClearScreen(){
main_right.setVisible(false);
help_right.setVisible(false);
settings_right.setVisible(false);
contrast_right.setVisible(false);
contact_right.setVisible(false);
comments_right.setVisible(false);
nice_right.setVisible(false);
faq_right.setVisible(false);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
TreeItem<String> treeItemRoot1 = new TreeItem<> ("Menu");
TreeItem<String> nodeItemA = new TreeItem<>("File",fileicon);
TreeItem<String> nodeItemB = new TreeItem<>("Edit",editicon);
TreeItem<String> nodeItemC = new TreeItem<>("Windows",windowsicon);
TreeItem<String> nodeItemD = new TreeItem<>("Tools",toolsicon);
TreeItem<String> nodeItemE = new TreeItem<>("Help",helpicon);
treeItemRoot1.getChildren().addAll(nodeItemA, nodeItemB, nodeItemC,nodeItemD,nodeItemE);
nodeItemA.setExpanded(true);
nodeItemB.setExpanded(true);
nodeItemC.setExpanded(true);
nodeItemD.setExpanded(true);
nodeItemE.setExpanded(true);
TreeItem<String> nodeItemA1 = new TreeItem<>("New File");
TreeItem<String> nodeItemA2 = new TreeItem<>("Open");
TreeItem<String> nodeItemA3 = new TreeItem<>("Quit");
nodeItemA.getChildren().addAll(nodeItemA1, nodeItemA2, nodeItemA3);
TreeItem<String> nodeItemB1 = new TreeItem<>("Edit A");
TreeItem<String> nodeItemB2 = new TreeItem<>("Edit B");
TreeItem<String> nodeItemB3 = new TreeItem<>("Edit C");
TreeItem<String> nodeItemB4 = new TreeItem<>("Edit D");
TreeItem<String> nodeItemB5 = new TreeItem<>("Edit E");
TreeItem<String> nodeItemB6 = new TreeItem<>("Edit F");
nodeItemB.getChildren().addAll(nodeItemB1, nodeItemB2, nodeItemB3, nodeItemB4, nodeItemB5, nodeItemB6);
TreeItem<String> nodeItemC1 = new TreeItem<>("Windows Settings");
TreeItem<String> nodeItemC2 = new TreeItem<>("Windows Brightness");
TreeItem<String> nodeItemC3 = new TreeItem<>("Windows Quit");
nodeItemC.getChildren().addAll(nodeItemC1, nodeItemC2, nodeItemC3);
TreeItem<String> nodeItemD1 = new TreeItem<>("Settings");
TreeItem<String> nodeItemD2 = new TreeItem<>("Print");
nodeItemD.getChildren().addAll(nodeItemD1, nodeItemD2);
TreeItem<String> nodeItemE1 = new TreeItem<>("Help");
TreeItem<String> nodeItemE2 = new TreeItem<>("FAQ");
nodeItemE.getChildren().addAll(nodeItemE1, nodeItemE2);
TreeView<String> treeView = new TreeView<>(treeItemRoot1);
treeView.setShowRoot(false);
menuholder.getChildren().add(treeView);
//
treeView.getSelectionModel().selectedItemProperty().addListener( new ChangeListener() {
public void changed(ObservableValue observable, Object oldValue,
Object newValue) {
operation = new Windows();
TreeItem<String> selectedItem = (TreeItem<String>) newValue;
String actualmenu;
**actualmenu = selectedItem.getValue();**
if (null != actualmenu) {
switch (actualmenu) {
case "File":
try{
selectedItem.setExpanded(true);
}
catch (Exception ex) {
Logger.getLogger(FoablakController.class.getName()).log(Level.SEVERE, null, ex);
}
break;
case "Edit":
selectedItem.setExpanded(true);
break;
case "Windows":
selectedItem.setExpanded(true);
break;
case "Tools":
selectedItem.setExpanded(true);
break;
case "Help":
selectedItem.setExpanded(true);
break;
case "New File":
try {
menuholder.setDisable(true);
textArea_help_summary.setDisable(true);
operation.first();
} catch (Exception ex) {
Logger.getLogger(FoablakController.class.getName()).log(Level.SEVERE, null, ex);
}
break;
case "Open":
System.out.println("OK");
break;
case "Quit":
System.out.println("OK");
break;
case "Edit A":
System.out.println("OK");
break;
case "Edit B":
ClearScreen();
contrast_right.setVisible(true);
case "Edit C":
break;
case "Edit D":
System.out.println("OK");
break;
case "Edit E":
System.out.println("OK");
break;
}
}
}
});
}
}
答案 0 :(得分:2)
<强>爵士; 强>
解决方案1
这就是我认为正在发生的事情,ChangeListener
听取更改事件,当您点击TreeView
中的某个项目时,当您点击其中的子项目时,它也是触发,当你尝试折叠一个项时,它会被触发两次,但是一次没有返回任何值的折叠(因此你的newValue为null所以当你尝试将一个对象赋值为null时,它是null,因此在空对象上调用函数会导致NPE),而TreeItem
选择调用第二个函数会将子TreeItem
作为值返回。所以快速修复我的更改侦听器在类型参数方面与您的有点不同,但它没什么大不了的
ChangeListener<TreeItem<String>>() {
public void changed(ObservableValue<? extends TreeItem<String>> observable,TreeItem<String> oldValue, TreeItem<String> newValue) {
TreeItem<String> selectedItem;
if(newValue != null){
selectedItem = newValue;
}else{
selectedItem = oldValue; // here it s null so i am assigning it
// to the old value
}
// add the other codes
解决方案2
实际上这个解决方案2转到你的问题“一个可能的解决方案是禁用树视图的崩溃,然后我每次都在扩展模式下使用它。是否可以在JavaFX Treeview中禁用折叠? “答案是肯定的......这里
yourTreeItem.addEventHandler(TreeItem.branchCollapsedEvent(),
new EventHandler<TreeModificationEvent<String>>() {
@Override
public void handle(TreeModificationEvent<String> event) {
event.getTreeItem().setExpanded(true);
}
});
希望有所帮助