I wrote a few J-unit tests for a class I use in my JavaFX project. I am however, running into a "Tookit not initialized" again and again. I'm new to JavaFX and J-Unit testing, so I'm not sure where to look.
I edited the VM options from -ea to "--module-path C:\Users\myName\Desktop\javafx-sdk-14.0.1\lib --add-modules javafx.controls,javafx.fxml" in order to fix a No suitable pipeline found error.
This is my test class code:
package HHS_PROJ1.models;
import javafx.scene.control.Button;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.*;
class AnimalTest {
private Animal animal;
#BeforeEach
void setUp() {
animal = new Animal(5, "Goat", 32, 10, 0, new Button("bid"));
}
#Test
void setHighestOffer() {
try {
animal.setHighestOffer(8);
fail("Entering a lower offer than current highestOffer should throw an exception");
} catch (IllegalArgumentException e) {
System.out.println("Caught lower offer than current highest in setHighestOffer(): " + e.getMessage());
} catch (Exception e) {
fail("Wrong exception thrown for entering a lower offer than the current highestOffer");
}
}
#Test
void setAmount() {
try {
animal.setAmount(-2);
fail("Entering a negative number should throw an exception");
} catch (IllegalArgumentException e) {
System.out.println("Caught negative number in setAmount(): " + e.getMessage());
} catch (Exception e) {
fail("Wrong exception thrown for entering a negative number");
}
}
}
I would like to be able to run my tests, to see if my code works as intended.
I fixed the issue by creating a private JFXPanel, then adding the following bits to VM options "javafx.web,javafx.media,javafx.swing"
Related
I have been working on it for the past 3-4 days. I have googled it and also saw similar questions' answers but it did not help me.
Exception at Changing Scence:javafx.fxml.LoadException:
address-to-//application/Dashboard.fxml
This is the Exception I am getting when I log into the dashboard from the login page. Usually, I am not getting this exception but when I am trying to display the data in tableView from the xampp server then this exception occurs otherwise it is working fine.
here is the code of Main.java
public class Main extends Application {
private static Stage stg;
#Override
public void start(Stage primaryStage) {
stg = primaryStage;
try {
primaryStage.setResizable(false);
Parent root = FXMLLoader.load(getClass().getResource("/application/Login.fxml"));
primaryStage.setTitle("My Application Title");
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root , 1200,670));
primaryStage.show();
}catch(Exception e) {
System.out.println("Exception Occured: " +e);
}
}
//to change the scene
public void changeScene(String fxml) {
//passing XML file via a string parameter
try {
Parent pane = FXMLLoader.load(getClass().getResource(fxml));
stg.getScene().setRoot(pane);
}catch(Exception e) {
System.out.println("Exception at Changing Scence:" +e);
}
}
public static void main(String[] args) {
launch(args);
}
}
and this is the code on the login button
/*TO CHECK THE LOGIN
* CREDENTIALS STARTS*/
#FXML
public void loginUser(ActionEvent event) {
uname = username.getText().toString();
upass = password.getText().toString();
try {
DbConnectivity db = new DbConnectivity();
pst = db.connect.prepareStatement("SELECT * FROM adminlogin WHERE admin=? AND password=?");
pst.setString(1, uname);
pst.setString(2, upass);
rst = pst.executeQuery();
if(uname.isEmpty() && upass.isEmpty()) {
wronginput.setText("Please Enter Credentials!");
} else if(rst.next()) {
wronginput.setText("Log In Success!");
Main main = new Main();
main.changeScene("/application/Dashboard.fxml");
} else {
wronginput.setText("Wrong Username or Password");
username.setText("");
password.setText("");
username.requestFocus();
}
} catch (SQLException e) {
System.out.println("Prepared Exception: "+e);
}
}
/*TO CHECK LOGIN
* CREDENTIALS ENDS*/
And these are StackTrace
javafx.fxml.LoadException:
address-to-/application/Dashboard.fxml
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2714)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2692)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2555)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3368)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3324)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3292)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3264)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3240)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3233)
at application.Main.changeScene(Main.java:39)
at application.LoginControl.loginUser(LoginControl.java:59)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.base#19.0.2.1/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml#19.0.2.1/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base#19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19.0.2.1/javafx.scene.Node.fireEvent(Node.java:8923)
at javafx.controls#19.0.2.1/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls#19.0.2.1/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
at javafx.controls#19.0.2.1/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base#19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19.0.2.1/javafx.scene.Scene$MouseHandler.process(Scene.java:3894)
at javafx.graphics#19.0.2.1/javafx.scene.Scene.processMouseEvent(Scene.java:1887)
at javafx.graphics#19.0.2.1/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.View.notifyMouse(View.java:937)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TableView.setItems(javafx.collections.ObservableList)" because "this.studentTable" is null
at application.DashboardController.RefreshStudentRecord(DashboardController.java:343)
at application.DashboardController.loadData(DashboardController.java:289)
at application.DashboardController.initialize(DashboardController.java:281)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2662)
... 66 more
For more clarifications
I have DashboardController.java that is implementing Initializable class.
Inside the controller class I have method to implement called initialize.
here is this method
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
loadData();
}
In this method I am using loadData() method that is
private void loadData() {
DbConnectivity db = new DbConnectivity();
conn = db.getConnection();
RefreshStudentRecord();
stsno.setCellValueFactory(new PropertyValueFactory<>("stsno"));
stsname.setCellValueFactory(new PropertyValueFactory<>("stsname"));
stsfname.setCellValueFactory(new PropertyValueFactory<>("stsfname"));
stsid.setCellValueFactory(new PropertyValueFactory<>("stsid"));
stscnic.setCellValueFactory(new PropertyValueFactory<>("stscnic"));
stsphone.setCellValueFactory(new PropertyValueFactory<>("stsphone"));
stsaddress.setCellValueFactory(new PropertyValueFactory<>("stsaddress"));
stsclass.setCellValueFactory(new PropertyValueFactory<>("stsclass"));
}
Inside the loadData() method I am calling another method that is
#FXML
public void RefreshStudentRecord() {
studentDataList.clear();
studentquery = "SELECT * FROM studentdata";
try {
studentPst = conn.prepareStatement(studentquery);
studentRst = studentPst.executeQuery();
while(studentRst.next()) {
studentDataList.add(new StudentsDataController(
studentRst.getInt("S_NO"),
studentRst.getString("studentname"),
studentRst.getString("fathername"),
studentRst.getString("studentid"),
studentRst.getString("studentcnic"),
studentRst.getString("phone"),
studentRst.getString("address"),
studentRst.getString("class")
)
);
studentTable.setItems(studentDataList);
}
} catch (SQLException e) {
System.out.println("Exception at Refresing student data: "+e);
e.printStackTrace();
}
}
I think the problem is somewhere thereby, seeing the StackTrace as it is pointing out that the table is null that's why all of the problems have occurred, but I have no clue why the table is null.
Kindly help me to solve this problem
Before setting the table ArrayList, do a check to check if the ArrayList has some data. Also, move your studentTable.setItems outside the loop such that it looks as follows:
while(studentRst.next()) {
studentDataList.add(new StudentsDataController(
studentRst.getInt("S_NO"),
studentRst.getString("studentname"),
studentRst.getString("fathername"),
studentRst.getString("studentid"),
studentRst.getString("studentcnic"),
studentRst.getString("phone"),
studentRst.getString("address"),
studentRst.getString("class")
)
);
}
if(studentDataList.size()>0){
studentTable.setItems(studentDataList);
}
Thanks to all for taking interest in my Question.
Here is how I solved it.
I created a separate class to handle the stuff for the tableView and made this class the controller of the fxml of tableView.
Then everything went right :)
Problem
I want to add custom made panels, built via javafx scene builder, to a gridpane at runtime. My custom made panel exsits of buttons, labels and so on.
My Attempt
I tried to extend from pane...
public class Celli extends Pane{
public Celli() throws IOException{
Parent root = FXMLLoader.load(getClass().getResource("Cell.fxml"));
this.getChildren().add(root);
}
}
... and then use this panel in the adding method of the conroller
#FXML
private void textChange(KeyEvent event) {
GridPane g = new GridPane();
for (int i=0 : i<100; i++){
g.getChildren().add(new Celli());
}
}
}
It works, but it performs very very poor.
What I am looking for
Is there a way to design panels via javafx scene builder (and as a result having this panels in fxml) and then add it to a gridpane at runtime without make use of this fxmlloader for each instance. I think it performs poor because of the fxml loader. When I add a standard button e.g. whitout fxml it is very much faster.
Short answer: No, it is not (as of JavaFX 2.x and 8.0). It may be in a future version (JFX >8)
Long answer:
The FXMLLoader is currently not designed to perform as a template provider that instantiates the same item over and over again. Rather it is meant to be a one-time-loader for large GUIs (or to serialize them).
The performance is poor because depending on the FXML file, on each call to load(), the FXMLLoader has to look up the classes and its properties via reflection. That means:
For each import statement, try to load each class until the class could successfully be loaded.
For each class, create a BeanAdapter that looks up all properties this class has and tries to apply the given parameters to the property.
The application of the parameters to the properties is done via reflection again.
There is also currently no improvement for subsequent calls to load() to the same FXML file done in the code. This means: no caching of found classes, no caching of BeanAdapters and so on.
There is a workaround for the performance of step 1, though, by setting a custom classloader to the FXMLLoader instance:
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class MyClassLoader extends ClassLoader{
private final Map<String, Class> classes = new HashMap<String, Class>();
private final ClassLoader parent;
public MyClassLoader(ClassLoader parent) {
this.parent = parent;
}
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> c = findClass(name);
if ( c == null ) {
throw new ClassNotFoundException( name );
}
return c;
}
#Override
protected Class<?> findClass( String className ) throws ClassNotFoundException {
// System.out.print("try to load " + className);
if (classes.containsKey(className)) {
Class<?> result = classes.get(className);
return result;
} else {
try {
Class<?> result = parent.loadClass(className);
// System.out.println(" -> success!");
classes.put(className, result);
return result;
} catch (ClassNotFoundException ignore) {
// System.out.println();
classes.put(className, null);
return null;
}
}
}
// ========= delegating methods =============
#Override
public URL getResource( String name ) {
return parent.getResource(name);
}
#Override
public Enumeration<URL> getResources( String name ) throws IOException {
return parent.getResources(name);
}
#Override
public String toString() {
return parent.toString();
}
#Override
public void setDefaultAssertionStatus(boolean enabled) {
parent.setDefaultAssertionStatus(enabled);
}
#Override
public void setPackageAssertionStatus(String packageName, boolean enabled) {
parent.setPackageAssertionStatus(packageName, enabled);
}
#Override
public void setClassAssertionStatus(String className, boolean enabled) {
parent.setClassAssertionStatus(className, enabled);
}
#Override
public void clearAssertionStatus() {
parent.clearAssertionStatus();
}
}
Usage:
public static ClassLoader cachingClassLoader = new MyClassLoader(FXMLLoader.getDefaultClassLoader());
FXMLLoader loader = new FXMLLoader(resource);
loader.setClassLoader(cachingClassLoader);
This significantly speeds up the performance. However, there is no workaround for step 2, so this might still be a problem.
However, there are already feature requests in the official JavaFX jira for this. It would be nice of you to support this requests.
Links:
FXMLLoader should be able to cache imports and properties between to load() calls:
https://bugs.openjdk.java.net/browse/JDK-8090848
add setAdapterFactory() to the FXMLLoader:
https://bugs.openjdk.java.net/browse/JDK-8102624
I have had a similar issue. I also had to load a custom fxml-based component several times, dynamically, and it was taking too long. The FXMLLoader.load method call was expensive, in my case.
My approach was to parallelize the component instantiation and it solved the problem.
Considering the example posted on the question, the controller method with multithread approach would be:
private void textChange(KeyEvent event) {
GridPane g = new GridPane();
// creates a thread pool with 10 threads
ExecutorService threadPool = Executors.newFixedThreadPool(10);
final List<Celli> listOfComponents = Collections.synchronizedList(new ArrayList<Celli>(100));
for (int i = 0; i < 100; i++) {
// parallelizes component loading
threadPool.execute(new Runnable() {
#Override
public void run() {
listOfComponents.add(new Celli());
}
});
}
// waits until all threads completion
try {
threadPool.shutdown();
threadPool.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// seems to be a improbable exception, but we have to deal with it
e.printStackTrace();
}
g.getChildren().addAll(listOfComponents);
}
Just adding code for "caching of already loaded classes" in #Sebastian sir given code. It is working for me. Please suggest changes in it for better performance.
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("In Class loader");
Class result;
System.out.println(" >>>>>> Load class : "+name);
result = (Class)classes.get(name);
if(result != null){
System.out.println(" >>>>>> returning cached class.");
return result;
}else{
Class<?> c = findClass(name);
if ( c == null ) {
throw new ClassNotFoundException( name );
}
System.out.println(" >>>>>> loading new class for first time only");
return c;
}
}
I am confused on how use the buttons. I open the theme designer and create the button, then on the commands i choose the action execute and go to the Source (saving before)
On the code I have this method, on the simulator do nothing and in the device neither (on the simulator start an Open file window, i am using w7)
#Override
protected boolean onMainCommand105() {
try {
Display.getInstance().execute("fb://profile/14846274855890");
} catch (Exception e) {
Dialog.show("Error!", "Failed to start. installed?", "OK", null);
e.printStackTrace();
}
return true;
}
is this the correct way?
I saw my mistake thanks to this CN1 tutorial
http://www.codenameone.com/how-do-i---handle-eventsnavigation-in-the-gui-builder--populate-the-form-from-code.html
I should use Action Event, not execute
#Override
protected void onMain_Button1Action(Component c, ActionEvent event) {
try {
Display.getInstance().execute("https://www.facebook.com/CatedralAltaPatagonia/?fref=ts");
} catch (Exception e) {
Dialog.show("Error!", "Failed to start. installed?", "OK", null);
e.printStackTrace();
}
}
Or easier :
button.addActionListener(l -> {
System.out.println("test");
});
I've noticed a Platform.runLater() doesn't update the stage/screen immediately after running, so I'm guessing the painting is happening elsewhere or on another queued event. I'm curious as to when or how the actual painting or rendering to the screen is queued or signaled, after the runnable completes.
The following code will print 1.begin, 1.end, 2.begin, 2.end, 3.begin, 3.end to the console, but the label never shows 1, though the second runLater() waits.
package main;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.concurrent.CountDownLatch;
public class SmallRunLater extends Application {
SimpleStringProperty labelValue = new SimpleStringProperty("0");
#Override
public void start(Stage stage) throws InterruptedException {
Scene scene = new Scene(new Group());
stage.setWidth(550);
stage.setHeight(550);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
Label label = new Label();
label.textProperty().bind(labelValue);
Button startBtn = new Button("Start");
vbox.getChildren().addAll(startBtn, label);
startBtn.setOnAction((action) -> {
try {
Task task = new Task<Void>() {
#Override
protected Void call() throws Exception {
SmallWork work = new SmallWork();
work.doWork(labelValue);
return null;
}
};
new Thread(task).start();
} catch (Exception e) {
e.printStackTrace();
}
});
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class SmallWork {
public void doWork(SimpleStringProperty labelValue) throws InterruptedException {
Platform.runLater(() -> {
System.out.println("1.begin");
labelValue.set("1");
System.out.println("1.end");
});
runNow(() -> {
System.out.println("2.begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
labelValue.set("2");
System.out.println("2.end");
});
Platform.runLater(() -> {
System.out.println("3.begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
labelValue.set("3");
System.out.println("3.end");
});
}
public static void runNow(Runnable r){
final CountDownLatch doneLatch = new CountDownLatch(1);
Platform.runLater(() -> {
try {
r.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
doneLatch.countDown();
}
});
try {
doneLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Yes, you are right, Platform.runLater() (as implied by the name) doesn't run right away and just pushes the Runnable to the internal queue. There is an internal render tick deep down. The Runnable objects will be executed in the update tick just before render. The fact that label never shows "1" simply coincides with the fact that your runNow() gets called immediately, in the same tick, so the two Runnable objects get pushed to same queue and executed in the same tick within JavaFX internal loop. Hence, the following happens:
label set to 1
internal thread set to sleep. This actually freezes the application if you noticed, since the rendering thread is now sleeping
label set to 2
render tick happens, so we get to see "2"
...
I have tried running the code above and sometimes I can see 1, which means the two Runnable objects were pushed in different ticks. Something like that:
label set to 1
render tick
...
I am new to Java and are trying to display an image. I got code on the net but when trying it I get an error with the importing of " import javax.imageio.ImageIO;" The error message reads "javax.imageio.ImageIO" is either a misplace package name or a non-existing entity.
I have seen this on many samples but it does not work with me.
Is there any advice
mport java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Showmap extends Panel
{
BufferedImage img;
public Showmap ()
{
try
{
image = ImageIO.read (new File ("KNP.jpg"));
}
/*
catch (IOException e)
{
BufferedImage image;
public ShowImage() {
try {
System.out.println("Enter image name\n");
BufferedReader bf=new BufferedReader(new
InputStreamReader(System.in));
String imageName=bf.readLine();
File input = new File(imageName);
image = ImageIO.read(input);
}*/
catch (IOException e)
{
System.out.println ("Error:" + e.getMessage ());
}
}
public void paint (Graphics g)
{
g.drawImage (image, 0, 0, null);
}
static public void main (String args []) throws
Exception
{
JFrame frame = new JFrame ("Display image");
Panel panel = new Showmap ();
frame.getContentPane ().add (panel);
frame.setSize (500, 500);
frame.setVisible (true);
}
}
Thanks
Ivan
In your Project select:
Right Click on "JRE System Libary"
Select Properties
On Execution Enviroment select "J2SE-1.5(jre8)" or later; you should use the latest version of jre8
I was programming with "Ready to Program" and tried many options with out success. When I copied the same code to "JCreator" and run it fro there it was working fine. Seems "import javax.imageio.ImageIO;" is not working with "Ready to Program".