I have 4 ComboBox in each of them there are 5 elements: " ", "1", "2", "3", "4".
I have to make if the item "1" is selected in a ComboBox, it is automatically excluded from other .And if the item " " is selected in the ComboBoxinsame
it is automatically returned to the other. So same need for other items except " ".
I tried to do this Here's the code:
public void vubadditems(ComboBox<String> vub1,ComboBox<String> vub2,ComboBox<String> vub3,ComboBox<String> vub4){
vub1.getItems().addAll(" ","1","2","3","4");
vub2.getItems().addAll(" ","1","2","3","4");
vub3.getItems().addAll(" ","1","2","3","4");
vub4.getItems().addAll(" ","1","2","3","4");
}
public void vubact(ComboBox<String> vub1,ComboBox<String> vub2,ComboBox<String> vub3,ComboBox<String> vub4){
if(vub1.getSelectionModel().getSelectedItem()!=" "){
vub2.getItems().remove(vub1.getSelectionModel().getSelectedItem());
vub3.getItems().remove(vub1.getSelectionModel().getSelectedItem());
vub4.getItems().remove(vub1.getSelectionModel().getSelectedItem());
s=vub1.getSelectionModel().getSelectedItem();
}else{
}
if(vub2.getSelectionModel().getSelectedItem()!=" "){
vub1.getItems().remove(vub2.getSelectionModel().getSelectedItem());
vub3.getItems().remove(vub2.getSelectionModel().getSelectedItem());
vub4.getItems().remove(vub2.getSelectionModel().getSelectedItem());
}
if(vub3.getSelectionModel().getSelectedItem()!=" "){
vub1.getItems().remove(vub3.getSelectionModel().getSelectedItem());
vub2.getItems().remove(vub3.getSelectionModel().getSelectedItem());
vub4.getItems().remove(vub3.getSelectionModel().getSelectedItem());
}
if(vub4.getSelectionModel().getSelectedItem()!=" "){
vub1.getItems().remove(vub4.getSelectionModel().getSelectedItem());
vub2.getItems().remove(vub4.getSelectionModel().getSelectedItem());
vub3.getItems().remove(vub4.getSelectionModel().getSelectedItem());
}
}
public void vubq1ac(){
vubact(q1vub1,q1vub2,q1vub3,q1vub4);
}
public void initialize(){
vubadditems(q1vub1,q1vub2,q1vub3,q1vub4);
vubadditems(q2vub1,q2vub2,q2vub3,q2vub4);
vubadditems(q3vub1,q3vub2,q3vub3,q3vub4);
vubadditems(q4vub1,q4vub2,q4vub3,q4vub4);
vubadditems(q5vub1,q5vub2,q5vub3,q5vub4);
}
q1vub1, q1vub2, q1vub3, q1vub4 is loaded from FXML_file ComboBox's
I add vubq1ac as action listiner on ComboBox
But I have some Exception and program works incorrect
Exception:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136)
at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:242)
at com.sun.javafx.scene.control.behavior.ListViewBehavior.lambda$new$177(ListViewBehavior.java:269)
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75)
at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(MultipleSelectionModelBase.java:378)
at javafx.scene.control.ListView$ListViewBitSetSelectionModel.clearAndSelect(ListView.java:1403)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.simpleSelect(CellBehaviorBase.java:256)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.doSelect(CellBehaviorBase.java:220)
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:150)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)
If you follow your current approach your code will be quite long and rather hard to debug. Currently it seems that:
You only remove and never return items.
You don't store the previously selected value. Imagine that in your first ComboBox "1" was selected (and subsequently, excluded from other components), and you decide to change it back to " ". You can't get the previous value directly from the ComboBox, because .getSelectedItem() will only return the current value, which would be " " already.
I'll present you my approach and tell you briefly how it works.
public class JavaFXApplication extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
FlowPane root = new FlowPane();
ArrayList<String> items = new ArrayList<>();
Collections.addAll(items, " ", "1", "2", "3", "4");
List<ComboBox> comboBoxList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
ComboBox c = new ComboBox(FXCollections.observableArrayList(items));
c.setValue(c.getItems().get(0));
c.valueProperty().addListener(removeFromOtherCombo(comboBoxList, c));
comboBoxList.add(c);
}
root.getChildren().addAll(comboBoxList);
Scene scene = new Scene(root, 200, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static ChangeListener removeFromOtherCombo(List<ComboBox> boxes, ComboBox current) {
return (o, oldVal, newVal) -> {
if (newVal.equals(oldVal)) {
return;
}
if (!oldVal.equals(" ")) {
boxes.stream()
.filter(c -> !c.equals(current))
.forEach((ComboBox) -> {
ComboBox.getItems().add(oldVal);
});
}
if (!newVal.equals(" ")) {
boxes.stream()
.filter(c -> !c.equals(current))
.forEach((ComboBox) -> {
ComboBox.getItems().remove(newVal);
});
}
};
}
}
For each ComboBox I create a ChangeListener that's aware of every other ComboBox and the ComboBox to which it's assigned.
c.valueProperty().addListener(removeFromOtherCombo(comboBoxList, c));
The ChangeListener is notified every time you pick a new value, and fortunately for us it receives both old and new value.
If old value is equal to new value then there's nothing for us to do.
if (newVal.equals(oldVal)) {
return;
}
If old value is a number (e.g. we're changing from "1" to "2") then we have to return the previously selected number to every ComboBox except one, which was filtered.
if (!oldVal.equals(" ")) {
boxes.stream()
.filter(c -> !c.equals(current))
.forEach((ComboBox) -> {
ComboBox.getItems().add(oldVal);
});
}
The same approach is taken when we're changing to a number, but this time we have to remove it from every ComboBox except one.
Related
I would like to do a small test using JavaFX and Serenity BDD, unfortunately with failure.
-when my code calls manually from the "TestSer" class it works fine.
-when calls from the GUI unfortunately does not work.
It seems to me that I am making a simple mistake with calling this class but I lack this knowledge
I present to you my code and please help.
Test class
#RunWith(SerenityRunner.class)
public class TestSer extends PageObject {
public Logger logger = LoggerFactory.getLogger(this.getClass());
#Managed
public WebDriver driver;
#FindBy(id = "b-7")
private WebElementFacade inputNumber;
#FindBy(id = "b-8")
private WebElementFacade buttonCheck;
#FindBy(id = "b-9")
private WebElementFacade buttonClean;
#FindBy(id = "caption2_b-3")
private WebElementFacade result;
Page page = new Page();
String[] arr = {"1230391507", "1230943800","1230705176", "1230943800", "1231069185", "1230500907", "1231079746"};
#Test
public void dodo() throws Exception {
page.open();
for (int i = 0; i < arr.length; i++) {
page.check( arr[i] );
System.out.println( arr[i] );
}
}
public void check(String numer) throws Exception {
String teraz = Teraz();
waitFor( inputNumber ).waitUntilEnabled();
inputNumber.type( numer );
waitFor( buttonCheck ).isClickable();
buttonCheck.click();
this.takeSnapShot(getDriver(), "C:\\Users\\smyha\\OneDrive\\Pulpit\\z\\"+numer+ teraz+ ".png") ;
waitFor( buttonClean ).isClickable();
buttonClean.click();
pause( 2000 );
}
public static void takeSnapShot(WebDriver webdriver, String fileWithPath) throws Exception{
TakesScreenshot scrShot =((TakesScreenshot)webdriver);
File SrcFile=scrShot.getScreenshotAs( OutputType.FILE);
File DestFile=new File(fileWithPath);
FileUtils.copyFile(SrcFile, DestFile);
}
public void pause(Integer milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String Teraz (){
Date date = new Date(); //
SimpleDateFormat hh = new SimpleDateFormat("HH");
SimpleDateFormat mm = new SimpleDateFormat("mm");
SimpleDateFormat ss = new SimpleDateFormat("ss");
String h = hh.format(date);
String m = mm.format(date);
String s = ss.format(date);
String teraz = "_"+h+"_"+m+"_"+s;
return teraz;
}
Controller class
#RunWith(SerenityRunner.class)
public class Controller implements Initializable {
public static final String dane = "1230391507\n" +
"1230500907\n" +
"1230705176\n" +
"1230943800\n" +
"1231069185\n" +
"1231079746\n";
public String [] arr ;
public String outDir;
private Window stage;
public String dirdir;
public String[] getArr() {
return arr;
}
public void setArr(String[] arr) {
this.arr = arr;
}
#FXML
private JFXTextArea txtFiield;
#FXML
private JFXTextField txtWhere;
#FXML
private JFXButton btnWhere, btnRun;
#Override
public void initialize(URL location, ResourceBundle resources) {
txtFiield.setText( dane );
}
public void doWhere(ActionEvent actionEvent) {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(stage);
if(selectedDirectory == null){
}else{
txtWhere.setText( selectedDirectory.getAbsolutePath() + "\\");
dirdir = selectedDirectory.getAbsolutePath() + "\\";
}
if (txtFiield.getLength() >0 && txtWhere.getLength() >0){
// btnWhere.setDisable( false );
btnRun.setDisable( false );
}
}
#Test
public void doRun(ActionEvent actionEvent) throws Exception {
TestSer t = new TestSer();
t.dodo();
}
public void parseField(String wejsciowe){
setArr( null );
setArr( wejsciowe.split( "\n" ));
System.out.println(arr.length);
String[] a = getArr();
for(int i = 0; i < a.length; i++){
if(a[i].length() != 10){
infoBox( "nieprawidłowa długość NIPu w lini : ", "Niepoprawne dane", "Błąd", i+1 );
}
}
}
public static void infoBox(String infoMessage, String headerText, String title, int line){
Alert alert = new Alert( Alert.AlertType.CONFIRMATION);
alert.setContentText(infoMessage + line);
alert.setTitle(title);
alert.setHeaderText(headerText);
alert.showAndWait();
}
}
Errors:
log4j:WARN No appenders could be found for logger (net.thucydides.core.util.PropertiesFileLocalPreferences).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8411)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
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 sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
... 52 more
Caused by: java.lang.NullPointerException
at net.serenitybdd.core.pages.PageObject.openPageAtUrl(PageObject.java:902)
at net.serenitybdd.core.pages.PageObject.open(PageObject.java:803)
at net.serenitybdd.core.pages.PageObject.open(PageObject.java:791)
at com.sub.serenity.TestSer.dodo(TestSer.java:48)
at com.sub.Controller.doRun(Controller.java:81)
... 62 more
I don't have time to search and I took a shortcut. I ran the test from the console.
public void cmd(String command) throws IOException {
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "cd \"C:\\Program Files\\Microsoft SQL Server\" &&" + command);
builder.redirectErrorStream(true);
builder.start();
}
and...
#Test
public void doRun(ActionEvent actionEvent) throws Exception {
infoBox( "Czyszczenie projektu SerenityBDD ", "Krok 1- prosze czekac", "Uwaga", 1);
cmd("mvn clean");
infoBox( "Wykonanie testu", "Krok 2 - prosze czekac ", "Uwaga", 2 );
cmd("mvn clean verify");
}
In this way, at the moment I was able to test correctly, but in a very ugly way
I get this error message, when i try calling a method "undo" in the object invoker of class Invoker:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at view.MainWindow.lambda$2(MainWindow.java:112)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Unknown Source)
I'm guessing the problem has to do with the javafx thread? I have tried using Platform.runLater, but the problem persisted.
I'm launching a JavaFX window through this:
public static void main(String[] args) {
Board board = new Board();
Invoker invoker = new Invoker();
TileBoardController tbc = new TileBoardController();
MainWindow mainWindow = new MainWindow();
com.sun.javafx.application.PlatformImpl.startup(()->{});
mainWindow.launch(board, tbc.CreateTiles(board), invoker);
com.sun.javafx.application.PlatformImpl.exit();
}
And the event that crashes the program lies in a menu bar in that "MainWindow" class:
menuOptions.setOnAction(e -> invoker.undo());
Strange thing is, the invoker class works, and is successfully used in another part of the same "MainWindow" object:
tileBoardStatic[rank][file].setOnAction( e -> this.onTileClick(finalRank, finalFile));
private void onTileClick(int rank, int file) {
invoker.storeAndExecute(new MovePiece(board, activeTile.getSquare(), tileBoardStatic[rank][file].getSquare()));
}
I have tried invoker.undo() in that same method, and that works.
Anyone know what the problem is here?
Here is all the code in MainWindow:
public class MainWindow extends Application{
public static final int TILE_SIZE = 100;
public static final int WIDTH = 8;
public static final int HEIGHT = 8;
private Invoker invoker;
private static Group tileGroup = null;
private static Tile[][] tileBoardStatic = null;
private Tile activeTile;
private Board board;
public void launch(Board board, Tile[][] tileBoard, Invoker invoker) {
this.board = board;
this.tileBoardStatic = tileBoard;
this.invoker = invoker;
tileGroup = new Group();
for (int rank=0; rank<tileBoard.length; rank++) {
for(int file=0; file<tileBoard[rank].length; file++) {
final int finalRank = rank;
final int finalFile = file;
tileBoardStatic[rank][file].setOnAction( e -> this.onTileClick(finalRank, finalFile));
tileGroup.getChildren().add(tileBoard[rank][file]);
}
}
Application.launch(MainWindow.class);
}
//Handles click event for Tiles
private void onTileClick(int rank, int file) {
if (activeTile == null) {
if (tileBoardStatic[rank][file].getSquare().getPiece() == null)
System.out.println("No piece in tile");
else {
if(tileBoardStatic[rank][file].getSquare().getPiece().isWhite() != board.getTurnIsWhite()) {
System.out.println("Not your turn");
} else {
activeTile = tileBoardStatic[rank][file];
activeTile.getStyleClass().add("tile-clicked");
}
}
}
else {
activeTile.getStyleClass().removeAll("tile-clicked");
//Creates and sends command to invoker
invoker.storeAndExecute(new MovePiece(board, activeTile.getSquare(), tileBoardStatic[rank][file].getSquare()));
//Repaints squares
activeTile.paintSquare();
tileBoardStatic[rank][file].paintSquare();
activeTile = null;
}
}
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
primaryStage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("resources/chess.png")));
root.getChildren().addAll(tileGroup);
root.setPrefSize(WIDTH * TILE_SIZE, HEIGHT * TILE_SIZE);
Scene scene = new Scene(root);
primaryStage.setTitle("MainWindow");
primaryStage.setScene(scene);
scene.getStylesheets().add(MainWindow.class.getResource("resources/stylesheet.css").toExternalForm());
//Menu bar
MenuBar menuBar = new MenuBar();
Menu gameMenu = new Menu("Game");
menuBar.getMenus().add(gameMenu);
MenuItem menuExit = new MenuItem("Exit game");
menuExit.setOnAction(e -> exit());
gameMenu.getItems().add(menuExit);
Menu menuOptions = new Menu("Edit");
MenuItem menuUndo = new MenuItem("Undo");
menuOptions.setOnAction(e -> invoker.undo());
menuOptions.getItems().add(menuUndo);
menuBar.getMenus().add(menuOptions);
root.setTop(menuBar);
primaryStage.show();
}
private void exit() {
Platform.exit();
System.exit(0);
}
}
You're launching your application incorrectly. Your main method initializes some objects, including an instance of MainWindow. You then call a method on said instance of MainWindow which sets some fields then calls Application.launch. This is where the problem manifests: The call to Application.launch results in a new, separate instance of MainWindow to be created. It is this instance that is used by the JavaFX runtime.
Since the start(Stage) method is invoked on an instance other than the one you called launch(Board,Tile[][],Invoker) on, none of the instance fields are set properly; this ultimately leads to your NullPointerException. Your solution to make invoker static merely covers up a symptom of the larger problem—initializing objects outside the typical life-cycle.
Try changing your main method to the following:
public static void main(String[] args) {
Application.launch(MainWindow.class, args);
}
Note: If the main method is inside the Application subclss, you can use launch(args) instead.
Then move all the initializing logic to ether Application#init() or Application#start(Stage) (or at least call the appropriate method(s) from inside one of them). Any initializing that requires the JavaFX Application Thread should be done in the start method; the init method is called on the JavaFX-Launcher thread.
Also, using Application.launch will implicitly startup the JavaFX runtime. There's no reason for you to manually call PlatformImpl.startup. You should also avoid using internal code (e.g. com.sun.*) unless there's no other option. If you find yourself needing to use internal code, take a step back and check if you're perhaps doing something wrong.
Fixed! All i had to do was to set my invoker object to static, of course. Stupid miss.
private static Invoker invoker;
I have a leftover project from school that I could not get working as intended. The class had a Connect4 text game, then a GUI (using JavaFX), then a server-client for it.
My standalone GUI will go until the game is won by player, but it crashes at that point if green wins(Long error message but seems to end in IllegalArgumentException related to java's Parent class)
Also I don't know if it is plausible to do a JavaFX server interaction for this, or if I should scrap and do swing, but I really wanted to get this working for my peace of mind. Right now I am struggling with the idea of backend and GUI logic for winning, but it is the only design I could get working to this extent, poor design as it is...
Please let me know if more information is needed, I know this program is a mess as I have not done GUIs before and I am afraid to clean up the program before fixing it. The source file is long but the error seems to be related to an illegal argument exception with a Parent object.
#Override
public void start(Stage primaryStage)
{
GridPane rectangleRoot = new GridPane();
GridPane circleRoot = new GridPane();
makeCircleBoard(rectangleRoot, circleRoot, playerColor);
rectangleRoot.setAlignment(Pos.CENTER);
circleRoot.setAlignment(Pos.CENTER);
Scene scene = new Scene(rectangleRoot, 1000, 1000);
Rectangle gameBoardSpace = new Rectangle(scene.getWidth() / 2, scene.getHeight()
/2, Color.DARKBLUE);
rectangleRoot.getChildren().add(gameBoardSpace);
rectangleRoot.getChildren().add(circleRoot);
primaryStage.setTitle("Connect4");
primaryStage.setScene(scene);
primaryStage.show();
}
public GridPane makeCircleBoard(GridPane rectangleRoot, GridPane circleRoot, String colorPassed)
{
int rowPerCol[] = new int[7]; //for back end 2D array
int turn = 1; //game logic
for(int i = 0; i < ROWMAX; i++)
{
for(int j = 0; j < COLMAX; j++)
{
gridLayout[i][j] = ' ';
}
}
for(int row = 0; row < 6; row++)
{
for(int col = 0; col < 7; col++)
{
GameSlot newCircle = new GameSlot(30, Color.WHITE);
newCircle.setStrokeType(StrokeType.OUTSIDE);
newCircle.setStroke(Color.web("black", 1.0));
newCircle.setStrokeWidth(4);
newCircle.setLocationRow(row);
newCircle.setLocationCol(col);
newCircle.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
if(newCircle.getOccupied() == false)
{
if(playerColor.equals("Yellow"))
{
gridLayout[newCircle.getLocationRow()][newCircle.getLocationCol()] = 'Y';
playerColor = "Green";
newCircle.setFill(Color.YELLOW);
newCircle.setOccupiedTrue();
}
else
{
gridLayout[newCircle.getLocationRow()][newCircle.getLocationCol()] = 'G';
playerColor = "Yellow";
newCircle.setFill(Color.GREEN);
newCircle.setOccupiedTrue();
}
}
if(gameWon(gridLayout))
{
if(playerColor.equals("Green"))
{
final Text actiontarget = new Text();
actiontarget.setFill(Color.CRIMSON);;
actiontarget.setText("YELLOW WON!!!");
actiontarget.setScaleX(10);
actiontarget.setScaleY(10);
actiontarget.setTranslateX(rectangleRoot.getWidth() / 5);
rectangleRoot.getChildren().add(actiontarget);
}
else
{
final Text actiontarget = new Text();
actiontarget.setFill(Color.CRIMSON);;
actiontarget.setText("GREEN WON!!!");
rectangleRoot.getChildren().add(actiontarget);
actiontarget.setScaleX(10);
actiontarget.setScaleY(10);
actiontarget.setTranslateX(rectangleRoot.getWidth() / 5);
rectangleRoot.getChildren().add(actiontarget);
}
}
} //end handle()
});
//circle.setId(Integer.toString(i));
circleRoot.add(newCircle, row, col);
//newCircle.isWon(row, col);
}
}
The checks for Green and Yellow are the same. It checks the different directions for the color characters opposite of the color who is up next. I see no errors for Yellow in any win condition and they have the index checking in gridLayout2.
Exception in thread "JavaFX Application Thread"
java.lang.IllegalArgumentException: Children: duplicate children added: parent = Grid hgap=0.0, vgap=0.0, alignment=CENTER
at javafx.scene.Parent$2.onProposedChange(Parent.java:454)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at Connect4.ui.Connect4GUI$1.handle(Connect4GUI.java:128)
at Connect4.ui.Connect4GUI$1.handle(Connect4GUI.java:1)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:417)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
The error you're getting is an IllegalArgumentException saying you are attempting to add a Node to the same Parent more than once—this is not allowed in JavaFX. If you look at the stack trace, you'll see where in your code this is happening.
java.lang.IllegalArgumentException: Children: duplicate children added: parent = Grid hgap=0.0, vgap=0.0, alignment=CENTER
at javafx.scene.Parent$2.onProposedChange(Parent.java:454)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at Connect4.ui.Connect4GUI$1.handle(Connect4GUI.java:128)
at Connect4.ui.Connect4GUI$1.handle(Connect4GUI.java:1)
The first frame that is not internal JavaFX code is Connect4.ui.Connect4GUI$1.handle(Connect4GUI.java:128) stating that the error is occurring on line 128 of your Connect4GUI class, inside a method named handle. You don't specify what line is line 128 but based on your code and the above information we know to focus on this part of your code:
newCircle.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
if(newCircle.getOccupied() == false)
{
if(playerColor.equals("Yellow"))
{
gridLayout[newCircle.getLocationRow()][newCircle.getLocationCol()] = 'Y';
playerColor = "Green";
newCircle.setFill(Color.YELLOW);
newCircle.setOccupiedTrue();
}
else
{
gridLayout[newCircle.getLocationRow()][newCircle.getLocationCol()] = 'G';
playerColor = "Yellow";
newCircle.setFill(Color.GREEN);
newCircle.setOccupiedTrue();
}
}
if(gameWon(gridLayout))
{
if(playerColor.equals("Green"))
{
final Text actiontarget = new Text();
actiontarget.setFill(Color.CRIMSON);;
actiontarget.setText("YELLOW WON!!!");
actiontarget.setScaleX(10);
actiontarget.setScaleY(10);
actiontarget.setTranslateX(rectangleRoot.getWidth() / 5);
rectangleRoot.getChildren().add(actiontarget);
}
else
{
final Text actiontarget = new Text();
actiontarget.setFill(Color.CRIMSON);;
actiontarget.setText("GREEN WON!!!");
rectangleRoot.getChildren().add(actiontarget);
actiontarget.setScaleX(10);
actiontarget.setScaleY(10);
actiontarget.setTranslateX(rectangleRoot.getWidth() / 5);
rectangleRoot.getChildren().add(actiontarget);
}
}
} //end handle()
});
Looking at the code, the issue can be located inside the else block that is within the if(gameWon(gridLayout)) block:
else
{
final Text actiontarget = new Text();
actiontarget.setFill(Color.CRIMSON);;
actiontarget.setText("GREEN WON!!!");
rectangleRoot.getChildren().add(actiontarget); // DUPLICATE LINE BELOW
actiontarget.setScaleX(10);
actiontarget.setScaleY(10);
actiontarget.setTranslateX(rectangleRoot.getWidth() / 5);
rectangleRoot.getChildren().add(actiontarget); // DUPLICATE: Must be line 128
}
Remove one of those statements and the code should no longer throw the IllegalArgumentException. Notice that the stack trace points you right at the offending line of code, by the way.
I´m trying to display an image on a new windows when I click on a rectangle of my main stage but I receive the following error: "Exception in thread "JavaFX Application Thread" java.lang.NullPointerException"
First controller (ControllerImpl) initializes second controller (ControllerImage) and calls one of its methods (controllerImage.displayImageSel):
#FXML
private ControllerImage controllerImage = new ControllerImage();
public void rectangleSave(Rectangle r, String imagePath) {
r.setOnMousePressed((event) -> {
try {
Stage imageStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/images.fxml"));
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
imageStage.setX(0);
imageStage.setY(0);
imageStage.setHeight(primScreenBounds.getHeight());
imageStage.setWidth(primScreenBounds.getWidth() * 0.7);
imageStage.setTitle("JavaFX Scene Graph Demo");
Scene scene = new Scene(loader.load());
imageStage.setScene(scene);
imageStage.show();
controllerImage.displayImageSel(imagePath);
} catch (IOException e) {
System.out.println("Me cago en el PP");
}
});
}
Second controller contains a stack pane and method called by ControllerImpl:
#FXML
public StackPane Spi;
public void displayImageSel(String imagePath) {
Rectangle ri = new Rectangle();
Spi.getChildren().add(ri);
Image image = new Image(new File(imagePath).toURI().toString());
ri.setFill(new ImagePattern(image));
}
Of course Spi is defined in FXML file:
<StackPane fx:id="Spi"......
Problem is ControllerImage can't find StackPane Spi. I´ve been implementing all kind of solutions I found related to this but no one has worked so far.
Thanks for your help!
EDIT: new error message
javafx.fxml.LoadException: Root value already specified.
/C:/tutorial-app/tutorial-app/target/resources/main/images.fxml
/C:/tutorial-app/tutorial-app/target/resources/main/images.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.createElement(FXMLLoader.java:2755)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2704)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at tutorial.controller.impl.ControllerImpl.lambda$rectangleSave$1(ControllerImpl.java:146)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
You are creating controllerImage yourself, not through FXMLLoader, so the FXML fields never get injected. You also never call load on that loader. Edit: Oops, you do, I just missed it.
Assuming you have the fx:controller set correctly in "images.fxml", remove the assignment of controllerImage and add this line after the call to FXMLLoader#load:
controllerImage = loader.getController();
If you don't have fx:controller set in the FXML you can either set it to the correct class, or instead pass the instance you create to the loader before loading:
loader.setController(controllerImage);
In this case you would of course keep the initialization of controllerImage.
I have a multi level tree view. It has several tree items. I expand only one level when I load. User can expand one by one by clicking on the arrow of that tree Item. As I keep expanding the last node keeps moving down and goes out of the view port. I scroll down, and click on the arrow. I get the error.
#FXML
private void createDescendantsTreeView(TreeView<APerson> thisTreeView) {
AnchorPane.setTopAnchor(thisTreeView, 10.0);
AnchorPane.setBottomAnchor(thisTreeView, 10.0);
AnchorPane.setLeftAnchor(thisTreeView, 5.0);
AnchorPane.setRightAnchor(thisTreeView, 5.0);
thisTreeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
thisTreeView.setPrefHeight(vBoxHt);
thisTreeView.setCellFactory(new Callback<TreeView<APerson>, TreeCell<APerson>>() {
#Override
public TreeCell<APerson> call(TreeView<APerson> thisTreeView) {
return new TreeCell<APerson>() {
protected void updateItem(final APerson thisPerson, boolean empty) {
super.updateItem(thisPerson, empty);
// if the item is not empty and is a root...
if (!empty) {
setTooltip(thisPerson.getToolTip());
// This will set Context menu for the node
if (thisPerson.getFatherID() != 0) {
this.setContextMenu(rightContextMenu);
}
if (thisPerson.getGender().charAt(0) == 'M') {
setText(thisPerson.getPersonName() + " [" + thisPerson.getPersonID() + "]");
ImageView maleIcon = new ImageView(maleImage);
setGraphic(maleIcon);
String cellStyle = " -fx-font-size: 16;\n" + " -fx-font-family: \"Times New Roman\";\n" + "-fx-text-fill: blue;";
setStyle(cellStyle);
} else {
setText(thisPerson.getPersonName() + " [" + thisPerson.getPersonID() + "]");
ImageView femaleIcon = new ImageView(femaleImage);
setGraphic(femaleIcon);
String cellStyle = " -fx-font-size: 16;\n" + " -fx-font-family: \"Times New Roman\";\n" + "-fx-text-fill: red;";
setStyle(cellStyle);
}
} else {
this.setText(null);
this.setGraphic(null);
}
}
};
}
});
childrenTreeView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
Node node = mouseEvent.getPickResult().getIntersectedNode();
System.out.println("Node click: " + node.toString());
if (node instanceof Text || (node instanceof TreeCell && ((TreeCell) node).getText() != null)) {
TreeItem TreeItemAtLocation = new TreeItem();
TreeItemAtLocation = childrenTreeView.getSelectionModel().getSelectedItem();
System.out.println("Child Tree - clicked on : " + TreeItemAtLocation.getValue().toString());
String name = childrenTreeView.getSelectionModel().getSelectedItem().getValue().toString();
APerson tmp = childrenTreeView.getSelectionModel().getSelectedItem().getValue();
if (TreeItemAtLocation.getParent() == null) {
removePicture.setDisable(true);
} else {
removePicture.setDisable(false);
}
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
if (TreeItemAtLocation != null) {
if (childrenTreeView.getRoot() == TreeItemAtLocation) {
addPerson.setDisable(false);
deletePerson.setDisable(true);
deleteThisFamily.setDisable(true);
modifyPerson.setDisable(true);
viewPerson.setDisable(true);
} else {
addPerson.setDisable(false);
deletePerson.setDisable(false);
if (TreeItemAtLocation.isLeaf()) {
deleteThisFamily.setDisable(true);
} else {
deleteThisFamily.setDisable(false);
}
modifyPerson.setDisable(false);
viewPerson.setDisable(false);
}
rightContextMenu.show(myMainApp.getMainStage());
} else {
rightContextMenu.hide();
}
} else {
rightContextMenu.hide();
}
}
}
});
}
This Image shows the screen and the I am talking about the tree in the right hand side. As I keep expanding the nodes, the last Tree Item scrolls down and not visible in this image. I scroll down to see that Tree Item and when I click on the arrow for that Tree item I get the following error.
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Node click: MainWindowController$5$1#1051fb6[styleClass=cell indexed-cell tree-cell]'Daughter [363]'
at familytreev01.MainWindowController$6.handle(MainWindowController.java:510)
at familytreev01.MainWindowController$6.handle(MainWindowController.java:501)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Node click: MainWindowController$5$1#36f8bc[styleClass=cell indexed-cell tree-cell]'null'
Node click: StackPane#b679e7[styleClass=tree-disclosure-node]
Deleting directory D:\JavaFXPrograms\FamilyTreeV01\dist\run8821460
jfxsa-run:
BUILD SUCCESSFUL (total time: 16 minutes 1 second)
However, if I select that Tree Item first and then click on that arrow, I don't get that error. It expands without any hassles. Right click on that Tree Item also works fine.
The error comes in line where I assign the value to a class variable.
childrenTreeView.getSelectionModel().getSelectedItem().getValue();
Why would this happen only to the last node ?
Thanks in advance.