JavaFX Image and ImageViewer not supporting jpeg - image

I created an fxml file with an ImageView on an AnchorPane using SceneBuilder and through controller class I set the image with the code somewhat like...
#FXML ImageView;
...
void func(File file) {
Image image = new Image(file.toURI().toString());
ImageView.setImage(image);
}
But the thing is whenever the file is a jpeg it doesn't show. Though it works completely fine with png. I looked up the openjfx doc for Image. It says that jpeg's are supported. What's the catch here?
FXML code (test.fxml):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.Testctrl">
<children>
<ImageView fx:id="imageView" fitHeight="1080.0" fitWidth="1440.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
Controller Class code (Testctrl.java):
package client;
import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import java.io.File;
public class Testctrl {
#FXML ImageView imageView;
private Main main;
public void setMain(Main main) {
this.main = main;
}
public void load() {
File file = new File("image.jpg");
Image image = new Image(file.toURI().toString());
imageView.setImage(image);
imageView.setFitHeight(1080);
imageView.setPreserveRatio(true);
}
}
Main Class code (Main.java):
package client;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Main extends Application {
private Testctrl testctrl;
private Stage stage;
#Override
public void start(Stage primaryStage) throws Exception{
stage = primaryStage;
stage.setFullScreen(true);
stage.setResizable(false);
showTest();
}
public void showTest(){
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("test.fxml"));
Parent root=null;
try {
root = loader.load();
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
testctrl = loader.getController();
testctrl.setMain(this);
testctrl.load();
stage.setScene(new Scene(root, 1920, 1080));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

How can I move a Label with a KeyEvent? (JavaFX)

I just learned how to make a GUI application with JavaFX with a FXML file. There is one thing that I don't understand though. When I try to add a KeyListener to a Label or the layout in my FXML file, the code doesn't get executed. It is a simple task like System.out.println("worked");, nothing complicated(eventually I want to move the Label with the keylistener, but now I just wanted something simple where I could easily see if it worked). I read somewhere that you need to add the listener on Frame level, but I don't know how. I would really appreciate it if someone could help me
Main.java:
package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
Controller controller = new Controller();
controller.moveLabel(event);
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
My controller class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
public class Controller {
#FXML
private Label label;
#FXML
public void moveLabel(KeyEvent e){
switch (e.getCode()){
case RIGHT:
label.setTranslateX(3);
break;
default:
System.out.println("not possible");
}
}
}
My FXML file:
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10"
vgap="10">
<Label text="Text" fx:id="label" ></Label>
</GridPane
Error message:
Exception in thread "JavaFX Application Thread"
java.lang.NullPointerException
at sample.Controller.moveLabel(Controller.java:15)
at sample.Main$1.handle(Main.java:22)
at sample.Main$1.handle(Main.java:18)
at
com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handle
BubblingEvent(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.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$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$352
(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock
(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent
(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
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)
Add a method to your controller to move the label, e.g.
public class Controller {
private final double moveDelta = 10 ;
#FXML
private Label labelTest ;
public void moveLabel(int deltaX, int deltaY) {
labelTest.setTranslateX(labelTest.getTranslateX() + moveDelta * deltaX);
labelTest.setTranslateY(labelTest.getTranslateY() + moveDelta * deltaY);
}
}
Then get a reference to the controller in the start() method (you need to use the non-static load() method from FXMLLoader to do this), and call the method from the key handler:
#Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch(event.getCode()){
case RIGHT:
controller.moveLabel(1, 0);
break;
default:
System.out.println("not possible");
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}

JavaFX progress bar component activated from Spring Listener Method

I have three layer(gui->services->dao) desktop application (JavaFX+Spring 4).
Some of my methods realized in my services layer (without fx dependency) have long time computing. I'd like to report their progress in gui.
But there is a problem. My service layer hasn't got direct access to gui, make a log of IO operations and returns only summarize of it. GUI layer, doesn't know about progress of intermediate operations.
I try to make a generic progress component. It could be realized as a Spring Bean with listener method located id GUI layer. My services can publish ApplicationEvent, which can be received via progress component in gui. When it gets the event, should activate progress bar and report next events.
In init methods I have started ProgressTask, and bind progressProperty with my gui progress bar control.
Call method of my ProgressTask runs while actual counter is less that max number of steps.
There is my component:
#Component
#Controller
public class ProgressBarComponent {
#FXML
private ProgressBar progressBar;
private ProgressTask actTask;
#FXML
public void initialize(){
}
private void initProgressBar(int aMax){
actTask=new ProgressTask();
actTask.initState(aMax);
progressBar.progressProperty().bind(actTask.progressProperty());
new Thread(actTask).start();
}
#EventListener
public void handleProgressEvent(ProgressEvent event) {
if(event.getGetActStep()==0){
initProgressBar(event.getMaxStep());
}
actTask.changeState(event.getGetActStep());
}
class ProgressTask extends Task<Object>{
private int max=100;
private int act=0;
private volatile boolean cancelled;
public void initState(int aMax){
this.max=aMax;
}
public void changeState(int newVal){
act=newVal;
updateProgress(act, max);
updateMessage("progress: " + act);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new IllegalArgumentException(e);
}
}
#Override
protected Object call() throws Exception {
while(act<max){
}
return null;
}
}
}
But it doesn't work.
Progress bar control is activated but in one step and at once it has a 100 percent value.
I have found a lot of examples Progress Bar FX control, but all of them assume that main logic is computed inside call() method of ProgressTask. In my case it isn't possible.
It is possible to make a ProgressBar Component, which is activated from listener method ? If yes, what code should be in ProgressTask.call() method ?
The point of a Task is to define some functionality that should be run on a background thread. So if this functionality is already implemented elsewhere, there is no need for a task.
Assuming the service is being invoked on a background thread (i.e. not on the FX Application Thread), you should just be able to do:
#Component
#Controller
public class ProgressBarComponent {
private int max ;
#FXML
private ProgressBar progressBar;
#FXML
public void initialize(){
}
private void initProgressBar(int aMax){
this.max = aMax ;
}
#EventListener
public void handleProgressEvent(ProgressEvent event) {
if(event.getGetActStep()==0){
Platform.runLater(() -> initProgressBar(event.getMaxStep()));
}
Platform.runLater(() ->
progressBar.setProgress(1.0 * event.getGetActStep() / max));
}
}
Here's a complete SSCCE:
ProgressViewer.java:
package springevent;
import org.springframework.context.event.EventListener;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ProgressViewer {
private Stage stage = new Stage();
private Scene scene ;
private ProgressBar progressBar ;
public ProgressViewer() {
progressBar = new ProgressBar();
StackPane root = new StackPane(progressBar);
root.setPadding(new Insets(20));
scene = new Scene(root);
stage.setScene(scene);
}
#EventListener
public void progressUpdate(ProgressEvent event) {
if (event.getCurrent() < event.getMax()) {
Platform.runLater(stage::show);
} else {
Platform.runLater(stage::hide);
}
final double progress = 1.0 * event.getCurrent() / event.getMax() ;
Platform.runLater(() -> progressBar.setProgress(progress));
}
}
Service.java:
package springevent;
import javax.inject.Inject;
import org.springframework.context.ApplicationContext;
public class Service {
#Inject
private ApplicationContext context ;
public void runService() {
context.publishEvent(new ProgressEvent(0, 100));
try {
for (int i = 1 ; i <= 100; i++) {
Thread.sleep(200);
context.publishEvent(new ProgressEvent(i, 100));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
ProgressEvent.java
package springevent;
public class ProgressEvent {
private final int current ;
private final int max ;
public ProgressEvent(int current, int max) {
this.current = current ;
this.max = max ;
}
public int getCurrent() {
return current ;
}
public int getMax() {
return max ;
}
}
MainController.java
package springevent;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import org.springframework.context.event.EventListener;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class MainController {
#Inject
private Executor exec ;
#Inject
private Service service ;
#FXML
private Button startButton ;
public void startProcess() {
exec.execute(service::runService);
}
#EventListener
public void progressUpdate(ProgressEvent event) {
startButton.setDisable(event.getCurrent() < event.getMax());
}
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="springevent.MainController">
<padding>
<Insets top="20" bottom="20" left="20" right="20"/>
</padding>
<Button fx:id="startButton" text="Start process" onAction="#startProcess" />
</StackPane>
Main.java
package springevent;
import java.io.IOException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
private AbstractApplicationContext context ;
#Override
public void start(Stage primaryStage) throws IOException {
context = new AnnotationConfigApplicationContext(AppConfig.class);
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
loader.setControllerFactory(context::getBean);
Scene scene = new Scene(loader.load());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
and AppConfig.java:
package springevent;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
#Bean
public Service service() {
return new Service();
}
#Bean
public MainController mainController() {
return new MainController();
}
#Bean
public ProgressViewer progressViewer() {
return new ProgressViewer();
}
#Bean
public Executor exec() {
return Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
}
}

JavaFX MVC controller not work

i'm beginner with javaFX and i try to develop an application with MVC. In this application i use two controllers, one for menuBar and for panelCenter which contain button and label. When i click on Button (CenterControler) "It works" but when i click on File->Quit (MainControler) it don't works.
Here the file Main.java :
package application;
import java.io.IOException;
import controler.CenterControler;
import controler.MainControler;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
CenterControler ctrl_Center;
MainControler ctrl_Main;
Stage primaryStage;
#Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/themain.fxml"));
Parent root = (Parent) fxmlLoader.load();
ctrl_Main = (MainControler)fxmlLoader.getController();
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("FXML Welcome");
primaryStage.setScene(scene);
primaryStage.show();}
public static void main(String[] args) {
launch(args);
}
}
MainControler.java
package controler;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
public class MainControler implements Initializable{
#FXML
private Menu File;
#FXML
private MenuBar barreMenu;
#FXML
private Menu sousMenu;
#FXML
private MenuItem menuQuit;
#FXML
private CenterControler centreControle;
#Override
public void initialize(URL location, ResourceBundle resources) {
assert File != null : "fx:id=\"File\" was not injected: check your FXML file 'themain.fxml'.";
assert menuQuit != null : "fx:id=\"menuQuit\" was not injected: check your FXML file 'themain.fxml'.";
}
public void setCenterControle(CenterControler cc){this.centreControle = cc; }
#FXML
protected void onClick2()
{
centreControle.show("IT WORKS !!! FROM MAIN CONTROLER");
}
}
CenterControler.java
package controler;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
public class CenterControler implements Initializable{
#FXML
private AnchorPane monFonds;
#FXML
private Button btn_1;
#FXML
private Label labelMSG;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
assert btn_1 != null : "fx:id=\"btn_1\" was not injected: check your FXML file 'part2.fxml'.";
assert labelMSG != null : "fx:id=\"labelMSG\" was not injected: check your FXML file 'part2.fxml'.";
}
public void setBTN(Button btn){ this.btn_1 = btn;}
public void setLabel(Label lb) {this.labelMSG = lb; }
public Button getBTN(){ return this.btn_1; }
public Label getLabel(){ return this.labelMSG;}
#FXML
protected void onClickShowMSG()
{
labelMSG.setText("PUSH FROM CENTER CONTROLER");
}
public void show(String msg)
{
labelMSG.setText(msg);
}
}
themain.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controler.MainControler">
<children>
<MenuBar fx:id="barreMenu" VBox.vgrow="NEVER">
<menus>
<Menu fx:id="sousMenu" mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="menuQuit" mnemonicParsing="false" onAction="#onClick2" text="Quit" />
</items>
</Menu>
</menus>
</MenuBar>
<fx:include fx:id="p2" source="part2.fxml" />
</children>
</VBox>
part2.fxml
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controler.CenterControler">
<children>
<Button fx:id="btn_1" layoutX="274.0" layoutY="188.0" mnemonicParsing="false" onAction="#onClickShowMSG" text="Button" />
<Label fx:id="labelMSG" layoutX="286.0" layoutY="128.0" text="Label" />
</children>
</AnchorPane>
Thanks in advance.
The name of the field where the controller is injected is constructed by taking the value of the fx:id attribute of the fx:include element and concatenating "Controller". Therefore the name of the field where the nested controller is injected has to be p2Controller and not centreControle:
public class CenterControler implements Initializable {
//...
#FXML
private CenterControler p2Controller;
//...
}
Unfortunately this is not well documented... (I had to look at the source code to find out)

java fx can't image doesn't show

i have a problem with displaying images in java fx.I want to simply display image which i get from string path.My image in this case images.jpg is in src folder of the project.
so far i got code like this:
FXML FILE:
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com /javafx/8">
<children>
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
CONTROLLER CLASS:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class MainPaneController implements Initializable {
#FXML
private ImageView imageView;
private Image image;
String path;
#Override
public void initialize(URL location, ResourceBundle resources) {
String path = "indeks.jpg";
imageView = new ImageView();
image = new Image(path);
imageView.setImage(image);
}
public ImageView getImageView() {
return imageView;
}
public void setImageView(ImageView imageView) {
this.imageView = imageView;
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
}
MAIN CLASS:
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Parent parent = (Parent) FXMLLoader.load(getClass().getResource(
"/pl/gallery/view/MainPane.fxml"));
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I have no idea what i'm doing wrong here.

Add image to a button at a specific position JavaFX

When I add image and text to a button, by default elements are set horizontally. How can I change this behavior to get text under image ?
Set the contentDisplayProperty on the button.
button.setContentDisplay(ContentDisplay.TOP);
Here is an executable example:
import javafx.application.Application;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ButtonGraphicTest extends Application {
#Override public void start(final Stage stage) throws Exception {
final Label response = new Label();
final ImageView imageView = new ImageView(
new Image("http://icons.iconarchive.com/icons/eponas-deeway/colobrush/128/heart-2-icon.png")
);
final Button button = new Button("I love you", imageView);
button.setStyle("-fx-base: coral;");
button.setContentDisplay(ContentDisplay.TOP);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
response.setText("I love you too!");
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().addAll(button, response);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10; -fx-font-size: 20;");
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
// icon license: (creative commons with attribution) http://creativecommons.org/licenses/by-nc-nd/3.0/
// icon artist attribution page: (eponas-deeway) http://eponas-deeway.deviantart.com/gallery/#/d1s7uih

Resources