Can't delete just added component from the scene - user-interface

I have the following code in two different files:
#FXML
public void openFileMenu() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("FileMenu.fxml"), resourceBundle);
AnchorPane root = (AnchorPane) loader.load();
MenuController menuController = loader.getController();
if (toolbarStack.getWidth() < menuController.getContentWidth()) {
menuController.addManipulator();
}
ResizeListener.widthProperty.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number number, Number number2) {
if (toolbarStack.getWidth() < menuController.getContentWidth()) {
menuController.addManipulator();
} else {
menuController.removeManipulator();
}
}
});
}
and
package UI;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.*;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.util.Duration;
public class MenuController implements Initializable {
#Override
public void initialize(URL url, ResourceBundle rb) {}
public void addManipulator() {
AnchorPane.setLeftAnchor(menuScrollPane, 50.0);
AnchorPane.setRightAnchor(menuScrollPane, 50.0);
leftButton = new Button("<");
leftButton.setId("leftButton");
leftButton.setPrefSize(50.0, 100.0);
AnchorPane.setLeftAnchor(leftButton, 0.0);
leftButton.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
slideTo(LEFT);
}
});
leftButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
stopSlide();
}
});
rightButton = new Button(">");
rightButton.setId("rightButton");
rightButton.setPrefSize(50.0, 100.0);
AnchorPane.setRightAnchor(rightButton, 0.0);
rightButton.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
slideTo(RIGHT);
}
});
rightButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
stopSlide();
}
});
mainMenuPane.getChildren().addAll(leftButton, rightButton);
}
public void removeManipulator() {
mainMenuPane.getChildren().removeAll(leftButton, rightButton);
AnchorPane.setLeftAnchor(menuScrollPane, 0.0);
AnchorPane.setRightAnchor(menuScrollPane, 0.0);
}
private void slideTo(boolean direction) {
value.setValue(menuScrollPane.getHvalue());
double realSpeed = direction ? animationSpeed*(1-menuScrollPane.getHvalue()) : animationSpeed*menuScrollPane.getHvalue();
timeline = new Timeline();
KeyValue kv = direction ? new KeyValue(value, 1.0) : new KeyValue(value, 0.0);
KeyFrame frame = new KeyFrame(Duration.millis(realSpeed), kv);
timeline.getKeyFrames().add(frame);
timeline.play();
value.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
menuScrollPane.setHvalue(newValue.doubleValue());
}
});
}
private void stopSlide() {
timeline.stop();
timeline.getKeyFrames().removeAll(timeline.getKeyFrames());
}
public double getContentWidth() {
return menuContentPane.prefWidthProperty().doubleValue();
}
#FXML
private AnchorPane mainMenuPane;
#FXML
private AnchorPane menuContentPane;
#FXML
private ScrollPane menuScrollPane;
private Button leftButton;
private Button rightButton;
private Timeline timeline;
private DoubleProperty value = new SimpleDoubleProperty();
private final boolean LEFT = true;
private final boolean RIGHT = false;
private double animationSpeed = 1000.0;
}
The problem is that after adding Buttons by menuController.addManipulator(); it's impossible to remove them - menuController.removeManipulator(); doesn't work. But the most strange thing is that only mainMenuPane.getChildren().removeAll(leftButton, rightButton); doesn't work, at the same time AnchorPane.setLeftAnchor(menuScrollPane, 0.0); AnchorPane.setRightAnchor(menuScrollPane, 0.0); do everything they must. What is wrong?

Related

control on a java-fx Button by 'Advice' class on aop spring framework

im trying to acsess an application button on javafx program by extenal 'Aspect' class using the spring aop .
This is the aspect class:
public class AspectControl {
private List<String> UserClicks;
private String[] expectedClick={"yellow","greean","red","blue","blue","blue","grean"};
public void beforeClickYellow(){
UserClicks.add("yellow");
}
public void afterClickYellow(){
Thread t=new Thread();
Main.yellowBtn.disableProperty();
}
}
this is the configuration xml :
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy/>
<aop:config>
<aop:aspect id ="aspectcontrol" ref = "control">
<aop:pointcut id ="YellowPointcut"
expression = "execution(*
application.ButtonsNotify.yellowNotify(..))"/>
<aop:before pointcut-ref ="YellowPointcut" method="beforeClickYellow"/>
<aop:after pointcut-ref ="YellowPointcut" method ="afterClickYellow"/>
</aop:aspect>
application class:
package application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class Main extends Application {
private static final int SCENE_WIDTH = 800;
private static final int SCENE_HEIGHT = 500;
private Group GroupButtns;
private final int TOTAL_CLICKS = 10;
private int numOfClick = 0;
public static Button yellowBtn;
#Override
public void start(final Stage stage) {
stage.initStyle(StageStyle.TRANSPARENT);
stage.sizeToScene();
stage.setScene(new AppScene());
//close application
final Button close = new Button("X");
close.setFont(Font.font("Arial", FontWeight.BOLD, 20));
close.setStyle("-fx-background-color:transparent;-fx-text-fill:red;");
close.setOpacity(0);
close.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
Platform.exit();
System.exit(0);
}
});
close.setTranslateY(stage.getScene().getHeight() - 20);
stage.getScene().setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent arg0) {
close.setOpacity(1);
}
});
stage.getScene().setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent arg0) {
close.setOpacity(0);
}
});
// close application
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
});
yellowBtn = new Button();
SetButnView(yellowBtn, "yellow");
yellowBtn.setTranslateY(stage.getScene().getHeight() - 250);
yellowBtn.setTranslateX(stage.getScene().getX() - 200);
yellowBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
numOfClick += 1;
ApplicationContext context = new ClassPathXmlApplicationContext("BeanConfig.xml");
ButtonsNotify notify = (ButtonsNotify) context.getBean("btnNotify");
notify.yellowNotify(numOfClick);
}
});
Button blueBtn = new Button();
SetButnView(blueBtn, "blue");
blueBtn.setTranslateY(stage.getScene().getHeight() - 250);
blueBtn.setTranslateX(stage.getScene().getX() - 10);
Button redbtn = new Button();
SetButnView(redbtn, "red");
redbtn.setTranslateY(stage.getScene().getHeight() - 420);
redbtn.setTranslateX(stage.getScene().getX() - 10);
Button greenbtn = new Button();
SetButnView(greenbtn, "green");
greenbtn.setTranslateY(stage.getScene().getHeight() - 420);
greenbtn.setTranslateX(stage.getScene().getX() - 200);
GroupButtns.getChildren().add(close);
GroupButtns.getChildren().add(yellowBtn);
GroupButtns.getChildren().add(blueBtn);
GroupButtns.getChildren().add(greenbtn);
GroupButtns.getChildren().add(redbtn);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private class AppScene extends Scene {
public AppScene() {
super(GroupButtns = new Group(), SCENE_WIDTH, SCENE_HEIGHT, Color.TRANSPARENT);
GroupButtns.setClip(new Ellipse(0, SCENE_HEIGHT / 2, SCENE_WIDTH / 3, SCENE_HEIGHT / 2)); //Scene shape and size
Rectangle background = new Rectangle(-SCENE_WIDTH / 2, 0, SCENE_WIDTH, SCENE_HEIGHT);
background.setFill(new LinearGradient(0, 0, 0, SCENE_HEIGHT, false, CycleMethod.NO_CYCLE, new Stop(0, Color.GRAY), new Stop(0.3, Color.GRAY),
new Stop(1., new Color(1, 1, 1, 0)))); //background color
GroupButtns.getChildren().add(background);
GroupButtns.getTransforms().addAll(new Translate(SCENE_WIDTH / 2, SCENE_HEIGHT), new Rotate(180));
}
}
public void SetButnView(Button btn, String color) {
if (color.equals("yellow")) {
Image src = new Image(getClass().getResourceAsStream("yellow1.png"));
btn.setGraphic(new ImageView(src));
}
if (color.equals("blue")) {
Image src = new Image(getClass().getResourceAsStream("blue1.png"));
btn.setGraphic(new ImageView(src));
}
if (color.equals("red")) {
Image src = new Image(getClass().getResourceAsStream("red1.png"));
btn.setGraphic(new ImageView(src));
}
if (color.equals("green")) {
Image src = new Image(getClass().getResourceAsStream("green1.png"));
btn.setGraphic(new ImageView(src));
}
}
}
And this is the poincut class which I call every time I press a btn on the application class:
package application;
public class ButtonsNotify {
public ButtonsNotify(){
}
public void yellowNotify(int clickNumber){
System.out.println("yellow");
}
public void RedNotify(int clickNumber){
System.out.println("red");
}
public void BlueNotify(int clickNumber){
System.out.println("blue");
}
public void GreenNotify(int clickNumber){
System.out.println("green");
}
}
How can I control the button's visability by the 'AspectControl' class??

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 ;
});
}
}

Slide in/out JavaFX stage from/to right side of the screen

I have a task to make JavaFX application. When I start it the window should slides smoothly from right side of screen and when I click on "x" button it's should slides out to right side and then finishes.
I found possible to use simple Timeline animation for this. I made the window to slide in, when I run app, but can't figure out how to slide out window.
I tried to handle this defining handler via setOnCloseRequest() method of stage, but stuck with two problems:
can't implement animation
after click on "x" application closed immediately even if I use consume() method of Window event
Code:
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) {
stage.setTitle("Main");
Group root = new Group();
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
stage.setX(primScreenBounds.getMinX() + primScreenBounds.getWidth());
System.out.println(primScreenBounds.getWidth());
stage.setY(primScreenBounds.getMinY());
stage.setWidth(0);
stage.setHeight(primScreenBounds.getHeight());
Timeline timeline = new Timeline();
timeline.setAutoReverse(true);
WritableValue<Double> writableWidth = new WritableValue<Double>() {
#Override
public Double getValue() {
return stage.getWidth();
}
#Override
public void setValue(Double value) {
stage.setWidth(value);
}
};
KeyValue kv = new KeyValue(writableWidth, 600d);
KeyFrame kf = new KeyFrame(Duration.millis(3000), kv);
timeline.getKeyFrames().addAll(kf);
timeline.play();
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
event.consume();
}
});
}
}
This works (kind of, it is not very smooth) for me:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.WritableValue;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
public class SlidingWindow extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) {
stage.setTitle("Main");
Group root = new Group();
Scene scene = new Scene(root);
stage.setScene(scene);
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
double screenRightEdge = primScreenBounds.getMaxX() ;
stage.setX(screenRightEdge);
System.out.println(primScreenBounds.getWidth());
stage.setY(primScreenBounds.getMinY());
stage.setWidth(0);
stage.setHeight(primScreenBounds.getHeight());
Timeline timeline = new Timeline();
WritableValue<Double> writableWidth = new WritableValue<Double>() {
#Override
public Double getValue() {
return stage.getWidth();
}
#Override
public void setValue(Double value) {
stage.setX(screenRightEdge - value);
stage.setWidth(value);
}
};
KeyValue kv = new KeyValue(writableWidth, 600d);
KeyFrame kf = new KeyFrame(Duration.millis(3000), kv);
timeline.getKeyFrames().addAll(kf);
timeline.play();
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Timeline timeline = new Timeline();
KeyFrame endFrame = new KeyFrame(Duration.millis(3000), new KeyValue(writableWidth, 0.0));
timeline.getKeyFrames().add(endFrame);
timeline.setOnFinished(e -> Platform.runLater(() -> stage.hide()));
timeline.play();
event.consume();
}
});
}
}
The Platform.runLater(...) seems necessary to prevent a slew of NullPointerExceptions when the window is hidden, probably because the animation is causing some system to try to access a stage that no longer exists.

How to reload the screen when changing languages​ in JavaFX?

Well, I'm beginner with java and fxml.
I creating a application and need to change language of the screen. I have the file with internationalized keys but i no have idea as reload the screen with the changed language.
The application have a menu where have the language available. I want just refresh screen when the user change language.
change is still manual, as you can see on code: (Main.java):
public class Main extends Application {
private Locale locale = new Locale("en", "US");
private Image icon = new Image("picture.jpg");
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
Scene scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icon);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
This code is on the controller, when change language:
#FXML
private void btnMenuLanguageEnglishAction(ActionEvent event) {
this.locale = new Locale("en", "US");
}
#FXML
private void btnMenuLanguagePortuguesAction(ActionEvent event) {
this.locale = new Locale("pt", "BR");
}
how to send this locale to main and refresh the screen?
as will be the method that I use? I've tried some that I saw here on the site but no one answered my question.
Here is my implementation:
import javafx.fxml.FXMLLoader;
import javafx.geometry.NodeOrientation;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
/**
* Created by Fouad on 3/20/2015.
*/
public abstract class I18NController
{
private Stage primaryStage;
public void setPrimaryStage(Stage primaryStage){this.primaryStage = primaryStage;}
public Stage getPrimaryStage(){return primaryStage;}
public final void changeLanguage(I18NLanguage language) throws IOException
{
StateBundle stateBundle = new StateBundle();
onSaveState(stateBundle);
Locale locale = language.getLocale();
Locale.setDefault(locale);
ResourceBundle resourceBundle = getResourceBundle(locale);
URL fxml = getFXMLResource();
FXMLLoader loader = new FXMLLoader(fxml, resourceBundle);
Parent root = loader.load();
NodeOrientation nodeOrientation = language.getNodeOrientation();
root.setNodeOrientation(nodeOrientation);
primaryStage.setScene(new Scene(root));
primaryStage.sizeToScene();
I18NController newController = loader.getController();
newController.setPrimaryStage(primaryStage);
onLoadState(newController, language, resourceBundle, stateBundle);
}
protected abstract ResourceBundle getResourceBundle(Locale locale);
protected abstract URL getFXMLResource();
protected abstract void onSaveState(StateBundle stateBundle);
protected abstract void onLoadState(I18NController newController, I18NLanguage newLanguage, ResourceBundle resourceBundle, StateBundle stateBundle);
public static interface I18NLanguage
{
Locale getLocale();
NodeOrientation getNodeOrientation();
}
public static class StateBundle
{
private Map<String, Object> sMap = new HashMap<>();
StateBundle(){}
public void putData(String key, Object value)
{
sMap.put(key, value);
}
public <T> T getDate(String key, Class<T> type)
{
return type.cast(sMap.get(key));
}
}
}
You can use this class as base class to the controller, something like this:
JavaFXController.java:
public class JavaFXController extends I18NController implements Initializable
{
#FXML private DatePicker dpDate;
#FXML private RadioButton rdoArabic;
#FXML private RadioButton rdoEnglish;
// ...
#Override
public void initialize(URL location, ResourceBundle resources)
{
// ...
rdoEnglish.setOnAction(e ->
{
try
{
changeLanguage(AppSettings.Language.ENGLISH);
}
catch(IOException e1)
{
e1.printStackTrace();
}
});
rdoArabic.setOnAction(e ->
{
try
{
changeLanguage(AppSettings.Language.ARABIC);
}
catch(IOException e1)
{
e1.printStackTrace();
}
});
}
// ...
#Override
protected ResourceBundle getResourceBundle(Locale locale)
{
return ResourceBundle.getBundle("com/stackoverflow/gui/resources/JavaFXResourceBundle", locale, new UTF8Control());
}
#Override
protected URL getFXMLResource()
{
return getClass().getResource("resources/JavaFXDocument.fxml");
}
#Override
protected void onSaveState(StateBundle stateBundle)
{
LocalDate localDate = dpDate.getValue();
boolean isRdoArabicSelected = rdoArabic.isSelected();
boolean isRdoEnglishSelected = rdoEnglish.isSelected();
stateBundle.putData("localDate", localDate);
stateBundle.putData("isRdoArabicSelected", isRdoArabicSelected);
stateBundle.putData("isRdoEnglishSelected", isRdoEnglishSelected);
}
#Override
protected void onLoadState(I18NController newController, I18NLanguage newLanguage, ResourceBundle resourceBundle, StateBundle stateBundle)
{
JavaFXController controller = (JavaFXController) newController;
controller.getPrimaryStage().setTitle(resourceBundle.getString("window.title"));
NodeOrientation nodeOrientation = newLanguage.getNodeOrientation();
LocalDate localDate = stateBundle.getDate("localDate", LocalDate.class);
boolean isRdoArabicSelected = stateBundle.getDate("isRdoArabicSelected", Boolean.class);
boolean isRdoEnglishSelected = stateBundle.getDate("isRdoEnglishSelected", Boolean.class);
controller.dpDate.setValue(localDate);
controller.rdoArabic.setSelected(isRdoArabicSelected);
controller.rdoEnglish.setSelected(isRdoEnglishSelected);
}
}
AppSettings.java:
import com.parmajeyat.autobooking.gui.I18NController;
import javafx.geometry.NodeOrientation;
import java.util.Locale;
/**
* Created by Fouad on 2/7/2015.
*/
public final class AppSettings
{
private static final class Locales
{
public static final Locale SAUDI_AR_LOCALE = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build(); // nu is for numbers
public static final Locale SAUDI_EN_LOCALE = new Locale("en", "SA");
}
public static enum Language implements I18NController.I18NLanguage
{
ARABIC(Locales.SAUDI_AR_LOCALE, NodeOrientation.RIGHT_TO_LEFT),
ENGLISH(Locales.SAUDI_EN_LOCALE, NodeOrientation.LEFT_TO_RIGHT);
private Locale locale;
private NodeOrientation nodeOrientation;
Language(Locale locale, NodeOrientation nodeOrientation)
{
this.locale = locale;
this.nodeOrientation = nodeOrientation;
}
public Locale getLocale(){return locale;}
public NodeOrientation getNodeOrientation(){return nodeOrientation;}
}
}
UTF8Control.java:
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**
* Created by Fouad on 2/1/2015.
*/
public class UTF8Control extends ResourceBundle.Control
{
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException
{
// The below is a copy of the default implementation.
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, "properties");
ResourceBundle bundle = null;
InputStream stream = null;
if(reload)
{
URL url = loader.getResource(resourceName);
if(url != null)
{
URLConnection connection = url.openConnection();
if(connection != null)
{
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
}
else
{
stream = loader.getResourceAsStream(resourceName);
}
if(stream != null)
{
try
{
// Only this line is changed to make it to read properties files as UTF-8.
bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
}
finally
{
stream.close();
}
}
return bundle;
}
}
I know, it is quite old question, but I am new in JavaFX and I had just the same problem.
Here is my final solution for change language in app. It may not be ideal, but it works for me.
In controller I have that method:
#FXML
private BorderPane root; //root pane
#FXML
private void changeLocale(ActionEvent event) throws IOException{
Scene scene = root.getScene();
if(event.getSource().equals(lang_en)){
scene.setRoot(FXMLLoader.load(getClass().getResource("Layout.fxml"),ResourceBundle.getBundle("resources/Bundle", Locale.ENGLISH))); // = new Locale("en")
}else if(event.getSource().equals(lang_cs)){
scene.setRoot(FXMLLoader.load(getClass().getResource("Layout.fxml"),ResourceBundle.getBundle("resources/Bundle", new Locale("cs", "CZ"))));
}else{
}
}
The method loads new loader into my scene (to load into stage also works).
For complete scenario ... I can change current language with two radiomenuitems in menu, so after loading new loader (in the method "public void initialize(URL location, ResourceBundle resources)" in controller) I change selection of radiomenuitems with this switch:
switch(resources.getLocale().getLanguage()){
case "en":
lang_en.setSelected(true);
break;
case "cs":
lang_cs.setSelected(true);
break;
default:
break;
}
It is simple and may be useful for someone else who will have that problem.
Use binding with your Labeled (Label, Text, TitledPane, etc).
I managed to solve, the code:
Main:
public class Main extends Application {
private static Locale locale = new Locale("pt", "BR");
private static Image icone = new Image("picture.jpg");
private Scene scene;
public static Stage stage;
/**
*
* #param st
* #throws Exception
*/
#Override
public void start(Stage st) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
stage = st;
scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icone);
stage.setScene(scene);
stage.show();
}
public static Image getIcone() {
return icone;
}
public static Locale getLocale() {
return locale;
}
public static void setLocale(Locale locale) {
Main.locale = locale;
}
public void reload() throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icone);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
the controller:
#FXML
private void btnMenuLanguageEnglishAction(ActionEvent event) throws IOException {
Main.setLocale(new Locale("en", "US")); // change to english
Main.stage.close();
Main reload = new Main();
reload.reload();
}
#FXML
private void btnMenuLanguagePortuguesAction(ActionEvent event) throws IOException {
Main.setLocale(new Locale("pt", "BR")); // change to Portuguese;
Main.stage.close();
Main reload = new Main();
reload.reload();
}
but still has a problem: the language change can occur only once, the second time gives fatal error... Hope that helps someone.

In Java 7, transparent GIF doesn't animate properly

So, I'm having an issue with a program. I have a GIF that's transparent. The animation works properly, except that instead of showing one image at a time, it sort of stacks the images on top of each other. I tried overriding the paintIcon method of the ImageIcon class to clear the canvas, but that didn't work either. ANy thoughts?
My code:
public class GifRunner extends JPanel {
JLabel label;
public GifRunner() {
super();
label = new JLabel();
ImageIcon icon = new ImageIcon(getClass().getResource("/animation.gif");
label.setIcon(icon);
add(label);
}
public static void main(String[] args) {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GifRunner panel = new GifRunner();
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
}
Any help would be much appreciated
you can override the ImageIcon's paintIcon function and manually clear the canvas:
class ClearImageIcon extends ImageIcon{
public ClearImageIcon(String filename){super(filename);}
#Override
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D)g.create();
g2.setBackground(new Color(0,0,0,0));
g2.clearRect(0, 0, getIconWidth(), getIconHeight());
super.paintIcon(c, g2, x, y);
}
}
it will draw every frame nicely on to the screen.
Works fine for me...
Windows 7, Java 7.
Original
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AnimatedGifTest {
public static void main(String[] args) {
new AnimatedGifTest();
}
public AnimatedGifTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
ImageIcon image = new ImageIcon("C:\\Users\\swhitehead\\Documents\\My Dropbox\\Ponies\\appleture_animated_gif_by_inkwell_pony-d4uggao.gif");
JLabel label = new JLabel(image);
add(label);
}
}
}

Resources