java - JavaFX resizable canvas problems -


i've problem what's partially solved, curious (better) solutions.. want canvas fills entire window , resizes if window resized.

option 1 (partial solution):

according this: https://dlemmermann.wordpress.com/2014/04/10/javafx-tip-1-resizable-canvas/ , this: how make canvas resizable in javafx? i've created (copied) class:

public class resizablecanvas extends canvas {      public resizablecanvas() {         widthproperty().addlistener(evt -> draw());         heightproperty().addlistener(evt -> draw());     }      private void draw() {         double width = getwidth();         double height = getheight();          graphicscontext gc = getgraphicscontext2d();         gc.clearrect(0, 0, width, height);          gc.setstroke(color.red);         gc.strokeline(0, 0, width, height);         gc.strokeline(0, height, width, 0);     }      @override     public boolean isresizable() {         return true;     }      @override     public double prefwidth(double height) {         return getwidth();     }      @override     public double prefheight(double width) {         return getheight();     } } 

and placed following content viewfield.fxml file:

<?xml version="1.0" encoding="utf-8"?>  <?import javafx.scene.canvas.canvas?> <?import javafx.scene.layout.stackpane?> <?import blahblahblah.resizablecanvas?>  <stackpane fx:id="pane" minheight="500.0" minwidth="500.0" style="-fx-background-color: white; -fx-border-color: black;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="blahblahblah.viewfieldcontroller">    <children>       <resizablecanvas fx:id="resizablecanvas" />    </children> </stackpane> 

my controller (attached fxml file) viewfieldcontroller.java:

import javafx.beans.property.readonlydoubleproperty; import javafx.fxml.fxml; import javafx.scene.canvas.graphicscontext; import javafx.scene.layout.stackpane; import javafx.scene.paint.color; import javafx.stage.stage;  public class viewfieldcontroller {      private stage dialogstage;      @fxml     private stackpane pane;      @fxml     private resizablecanvas resizablecanvas;      @fxml     private void initialize() {          graphicscontext gc = resizablecanvas.getgraphicscontext2d();          readonlydoubleproperty widthproperty = pane.widthproperty();         readonlydoubleproperty heightproperty = pane.heightproperty();         resizablecanvas.widthproperty().bind(widthproperty);         resizablecanvas.heightproperty().bind(heightproperty);          drawarea(gc);     }      public void setdialogstage(stage dialogstage) {         this.dialogstage = dialogstage;     }      private void drawarea(graphicscontext gc) {          gc.setstroke(color.black);         gc.setlinewidth(1);         gc.strokeline(0, 0, resizablecanvas.getwidth(), resizablecanvas.getheight());         gc.strokeline(0, resizablecanvas.getheight(), resizablecanvas.getwidth(), 0);     }  } 

the windows loaded main controller mainapp.java:

public class mainapp extends application {  public static void main(string[] args) {     launch(args); } //...  public void showviewfield() {     try {         fxmlloader loader = new fxmlloader();         loader.setlocation(mainapp.class.getresource("view/viewfield.fxml"));         stackpane pane = (stackpane) loader.load();          stage stage = new stage();         stage.settitle("view field");         scene scene = new scene(pane);         stage.setscene(scene);          viewfieldcontroller controller = loader.getcontroller();         controller.setdialogstage(stage);          stage.show();      } catch (ioexception e) {         e.printstacktrace();     } }  } 

this solution works ("big x" appears on canvas, drawarea() method). problem solution after placing resisablecanvas class fxml file can't use scenebuilder more on file, because following exception:

java.io.ioexception: javafx.fxml.loadexception:  ...      @ com.oracle.javafx.scenebuilder.kit.fxom.fxomloader.load(fxomloader.java:92)     @ com.oracle.javafx.scenebuilder.kit.fxom.fxomdocument.<init>(fxomdocument.java:82)     @ com.oracle.javafx.scenebuilder.kit.fxom.fxomdocument.<init>(fxomdocument.java:97)     @ com.oracle.javafx.scenebuilder.kit.editor.editorcontroller.updatefxomdocument(editorcontroller.java:2384)     @ com.oracle.javafx.scenebuilder.kit.editor.editorcontroller.setfxmltextandlocation(editorcontroller.java:664)     @ com.oracle.javafx.scenebuilder.app.documentwindowcontroller.loadfromfile(documentwindowcontroller.java:381)     @ com.oracle.javafx.scenebuilder.app.scenebuilderapp.performopenfiles(scenebuilderapp.java:554)     @ com.oracle.javafx.scenebuilder.app.scenebuilderapp.handleopenfilesaction(scenebuilderapp.java:424)     @ com.oracle.javafx.scenebuilder.app.scenebuilderapp.handlelaunch(scenebuilderapp.java:403)     @ com.oracle.javafx.scenebuilder.app.appplatform.requeststartgeneric(appplatform.java:139)     @ com.oracle.javafx.scenebuilder.app.appplatform.requeststart(appplatform.java:106)     @ com.oracle.javafx.scenebuilder.app.scenebuilderapp.start(scenebuilderapp.java:353)     @ com.sun.javafx.application.launcherimpl.lambda$launchapplication1$163(launcherimpl.java:863)     @ com.sun.javafx.application.platformimpl.lambda$runandwait$176(platformimpl.java:326)     @ com.sun.javafx.application.platformimpl.lambda$null$174(platformimpl.java:295)     @ java.security.accesscontroller.doprivileged(native method)     @ com.sun.javafx.application.platformimpl.lambda$runlater$175(platformimpl.java:294)     @ com.sun.glass.ui.invokelaterdispatcher$future.run(invokelaterdispatcher.java:95)     @ com.sun.glass.ui.win.winapplication._runloop(native method)     @ com.sun.glass.ui.win.winapplication.lambda$null$149(winapplication.java:191)     @ java.lang.thread.run(thread.java:745) caused by: javafx.fxml.loadexception:  ...      @ javafx.fxml.fxmlloader.constructloadexception(fxmlloader.java:2601)     @ javafx.fxml.fxmlloader.importclass(fxmlloader.java:2848)     @ javafx.fxml.fxmlloader.processimport(fxmlloader.java:2692)     @ javafx.fxml.fxmlloader.processprocessinginstruction(fxmlloader.java:2661)     @ javafx.fxml.fxmlloader.loadimpl(fxmlloader.java:2517)     @ javafx.fxml.fxmlloader.load(fxmlloader.java:2425)     @ com.oracle.javafx.scenebuilder.kit.fxom.fxomloader.load(fxomloader.java:89)     ... 20 more caused by: java.lang.classnotfoundexception: blahblahblah.resizablecanvas     @ java.lang.classloader.findclass(classloader.java:530)     @ java.lang.classloader.loadclass(classloader.java:424)     @ java.lang.classloader.loadclass(classloader.java:357)     @ javafx.fxml.fxmlloader.loadtypeforpackage(fxmlloader.java:2916)     @ javafx.fxml.fxmlloader.loadtype(fxmlloader.java:2905)     @ javafx.fxml.fxmlloader.importclass(fxmlloader.java:2846)     ... 25 more 

option 2 (partial solution):

my second solution uses same resizablecanvas class, there no fxml file or controller class.

public class mainapp extends application {      //...      public void showviewfield2() {          resizablecanvas canvas = new resizablecanvas();         stackpane pane = new stackpane();         pane.getchildren().add(canvas);          stage stage = new stage();         stage.settitle("view field");         scene scene = new scene(pane);         stage.setscene(scene);          canvas.widthproperty().bind(pane.widthproperty());         canvas.heightproperty().bind(pane.heightproperty());          stage.show();     }  } 

this solution works (big x present on screen), same problem appears here: can't open fxml file in screenbuilder different reason (there no fxml file @ all).

option 3 (my original solution, not working):

i've replaced resizablecanvas class in viewfield.fxml file original canvas class:

<?xml version="1.0" encoding="utf-8"?>  <?import javafx.scene.canvas.canvas?> <?import javafx.scene.layout.stackpane?>  <stackpane fx:id="pane"  minheight="500.0" minwidth="500.0" style="-fx-background-color: white; -fx-border-color: black;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="blahblahblah.viewfieldcontroller">    <children>       <canvas fx:id="regularcanvas" />    </children> </stackpane> 

my viewfieldcontroller.java looks this:

import javafx.beans.property.readonlydoubleproperty; import javafx.fxml.fxml; import javafx.scene.canvas.canvas; import javafx.scene.canvas.graphicscontext; import javafx.scene.layout.stackpane; import javafx.scene.paint.color; import javafx.stage.stage;  public class viewfieldcontroller {      private stage dialogstage;      @fxml     private stackpane pane;      @fxml     private canvas regularcanvas;      @fxml     private void initialize() {          graphicscontext gc = regularcanvas.getgraphicscontext2d();          readonlydoubleproperty widthproperty = pane.widthproperty();         readonlydoubleproperty heightproperty = pane.heightproperty();         regularcanvas.widthproperty().bind(widthproperty);         regularcanvas.heightproperty().bind(heightproperty);          drawarea(gc);     }      public void setdialogstage(stage dialogstage) {         this.dialogstage = dialogstage;     }      private void drawarea(graphicscontext gc) {          gc.setstroke(color.black);         gc.setlinewidth(1);         gc.strokeline(0, 0, regularcanvas.getwidth(), regularcanvas.getheight());         gc.strokeline(0, regularcanvas.getheight(), regularcanvas.getwidth(), 0);     }  } 

but screen empty here. there no "big x" drawn on canvas. if resize window, dont't know if canvas resized or not, it's possible load fxml file scenebuilder further work..

it's not better if give height , width canvas (result same).

<stackpane fx:id="pane" minheight="500.0" minwidth="500.0" style="-fx-background-color: white; -fx-border-color: black;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="blahblahblah.viewfieldcontroller">    <children>       <canvas fx:id="regularcanvas" height="300.0" width="300.0" />    </children> </stackpane> 

my questions are:

  1. why "big x" not appeared int 3rd case?
  2. what modifications should make 3rd case work?
  3. is there other solution solves problems?
  4. why did exception in 1st case?
  5. why impossible "fit parent" canvas in scenebuilder?
  6. why "resisable" option disabled in scenebuilder?

you can make option 1 work scene builder bundling custom canvas jar file , importing scene builder library. see this question, example.

option 3 not work because ever call drawarea() initialize() method. @ point, canvas not part of scene, , not displayed in window; consequently hasn't undergone layout , has 0 width , height. can fix option adding listeners width , height , redrawing when change, in option 1:

@fxml private void initialize() {      graphicscontext gc = regularcanvas.getgraphicscontext2d();      readonlydoubleproperty widthproperty = pane.widthproperty();     readonlydoubleproperty heightproperty = pane.heightproperty();     regularcanvas.widthproperty().bind(widthproperty);     regularcanvas.heightproperty().bind(heightproperty);      regularcanvas.widthproperty().addlistener((obs, oldwidth, newwidth) -> drawarea(gc));     regularcanvas.heightproperty().addlistener((obs, oldheight, newheight) -> drawarea(gc));      drawarea(gc); } 

Comments

Popular posts from this blog

Django REST Framework perform_create: You cannot call `.save()` after accessing `serializer.data` -

Why does Go error when trying to marshal this JSON? -