JavaFx application Window dimension changes in El Capitan after bundling - macos

I am creating a javaFx application that runs in Mac OSX El Capitan. When I create a bundle from my jar file to .app file, the application window dimension changes.
I want window dimension to be the same before and after bundling. Any help is appreciated.

As I known JavaFX doesn't save/restore window position/dimension automatically.
So, you should restore window position/dimension before show window and save then before window hide. For example I am using such helper:
import javafx.stage.Stage;
import java.util.prefs.Preferences;
public class StagePositionManager {
public static final String IS_FIRST_RUN_KEY = "isFirstRun";
public static final String X_KEY = "x";
public static final String Y_KEY = "y";
public static final String WIDTH_KEY = "width";
public static final String HEIGHT_KEY = "height";
private final Stage stage;
private final Class<?> windowClass;
public StagePositionManager(Stage stage, Class<?> windowClass) {
this.stage = stage;
this.windowClass = windowClass;
restoreStagePosition();
stage.setOnHidden(event -> saveStagePosition());
}
private void saveStagePosition() {
Preferences preferences = Preferences.userNodeForPackage(windowClass);
preferences.putBoolean(IS_FIRST_RUN_KEY, false);
preferences.putDouble(X_KEY, stage.getX());
preferences.putDouble(Y_KEY, stage.getY());
preferences.putDouble(WIDTH_KEY, stage.getWidth());
preferences.putDouble(HEIGHT_KEY, stage.getHeight());
}
private void restoreStagePosition() {
Preferences preferences = Preferences.userNodeForPackage(windowClass);
if (!preferences.getBoolean(IS_FIRST_RUN_KEY, true)) {
stage.setX(preferences.getDouble(X_KEY, 0));
stage.setY(preferences.getDouble(Y_KEY, 0));
stage.setWidth(preferences.getDouble(WIDTH_KEY, 1024));
stage.setHeight(preferences.getDouble(HEIGHT_KEY, 768));
}
}
}
and call it after application start:
public class MyApplication extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
...
new StagePositionManager(primaryStage, Main.class);
...

Related

I am trying to learn uses of GUI but vscode and eclipse are both saying "GUI cannot be resolved to a type" after declaring "new GUI()" in main

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUITest {
private JPasswordField passwordBox;
private JButton enterButton = new JButton ("Enter");
private JLabel textBox = new JLabel("Enter Password Here:");;
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
public void GUITest() {
PanelSetup();
FrameSetup();
}
public void PanelSetup(){
panel.setBorder(BorderFactory.createEmptyBorder(150, 150, 250, 250));
panel.setLayout(new GridLayout(0,1));
}
public void FrameSetup(){
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setTitle("GUI TEST");
frame.pack();
frame.setVisible (true);
}
public static void main (String[] args) {
new GUI();
}
}
Unfortunately, the problem is creating the new GUI and I cannot run the code to see if the rest of it works and/or adding more stuff to it. If you can help that would be much appreciated
Change "new GUI();" to "new GUITest();" as you are creating a new instance of the current class.
public static void main (String[] args) {
new GUI();
}
to
public static void main (String[] args) {
new GUITest();
}
Also, remove the void tag from your constructor as it turns it into a method.
public void GUITest() {
PanelSetup();
FrameSetup();
}
to
public GUITest() {
PanelSetup();
FrameSetup();
}
It seems like you're new to java, welcome! I'd take a look at w3schools excellent java docs if you want to get better at syntax. w3schools java

Spring data jpa with java FX

I'm using Spring JPA with OpenJFX. It's this project JavaFX-weaver, simply adding spring-boot-start-data-jpa inside pom.
However my starting time of Spring JPA is 15-20s and the UI will not show until spring is initalized. When users will start the application it takes a lot of time, every time!
As a workaround i tried to create a simply java fx application without Spring (using this demo here) and then starting there in the main method the main method from spring over a button (see example bellow). That will start spring, but dependencies and properties are not laoded.
Do you know a good way to practice that case ? Every help is welcome.
Thank you
AppBootstrap (Java + OpenJFX)
public class AppBootstrap extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
// start spring jpa main method
btn.setOnAction(event -> App.main(new String[]{""}));
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
}
App (Spring JPA + javafx-weaver)
#SpringBootApplication
public class App {
public static void main(String[] args) {
Application.launch(SpringbootJavaFxApplication.class, args);
}
}
Startup of an JPA powered Application increases load time for ApplicationContext. While you can make things faster by not checking or creating a database scheme, e.g. by setting hibernate.hbm2ddl.auto=none, this is not the best option.
It is by design that the primary stage is shown after the ApplicationContext is loaded, since it should be able to be dependency injected.
The best practice I recommend is using a splash screen while loading the ApplicationContext. It's a bit tricky, since you have separate Threads, but roughly it looks like this:
Create a splash window
public class Splash {
private static final int SPLASH_WIDTH = 200;
private static final int SPLASH_HEIGHT = 200;
private final Parent parent;
private final Stage stage;
public Splash() {
this.stage = new Stage();
stage.setWidth(SPLASH_WIDTH);
stage.setHeight(SPLASH_HEIGHT);
Label progressText = new Label("Application loading ...");
VBox splashLayout = new VBox();
splashLayout.setAlignment(Pos.CENTER);
splashLayout.getChildren().addAll(progressText);
progressText.setAlignment(Pos.CENTER);
splashLayout.setStyle(
"-fx-padding: 5; " +
"-fx-background-color: white; " +
"-fx-border-width:5; " +
"-fx-border-color: white;"
);
splashLayout.setEffect(new DropShadow());
this.parent = splashLayout;
}
public void show() {
Scene splashScene = new Scene(parent);
stage.initStyle(StageStyle.UNDECORATED);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
stage.setScene(splashScene);
stage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2.0);
stage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2.0);
stage.show();
}
public void hide() {
stage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(0.3), parent);
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(actionEvent -> stage.hide());
fadeSplash.play();
}
}
Initialize Application
public class SpringbootJavaFxApplication extends Application {
private ConfigurableApplicationContext context;
class ApplicationContextLoader extends Task<Void> {
private final Stage primaryStage;
ApplicationContextLoader(Stage primaryStage) {
this.primaryStage = primaryStage;
}
#Override
protected Void call() {
ApplicationContextInitializer<GenericApplicationContext> initializer =
context -> {
context.registerBean(Application.class, () -> SpringbootJavaFxApplication.this);
context.registerBean(Stage.class, () -> primaryStage);
context.registerBean(Parameters.class,
SpringbootJavaFxApplication.this::getParameters); // for demonstration, not really needed
};
SpringbootJavaFxApplication.this.context = new SpringApplicationBuilder()
.sources(JavaFxSpringbootDemo.class)
.initializers(initializer)
.run(getParameters().getRaw().toArray(new String[0]));
return null;
}
}
#Override
public void start(Stage primaryStage) {
var splash = new Splash();
splash.show();
final ApplicationContextLoader applicationContextLoader = new ApplicationContextLoader(primaryStage);
applicationContextLoader.stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
context.publishEvent(new StageReadyEvent(primaryStage));
splash.hide();
}
});
new Thread(applicationContextLoader).start();
}
#Override
public void stop() {
this.context.close();
Platform.exit();
}
}

PreferenceActivity - garbled screen after rotation

I use PreferenceActivity for setting of live wallpaper utilizing OpenGL ES 2.0. And quite often I get completely garbled screen for this PreferenceActivity.
Steps to reproduce:
Open live wallpaper preview.
Open preferences by tapping "Settings..." button
Activity is displayed correctly no matter how often you repeat step 2.
Change orientation of device while in preview.
Open preferences by tapping "Settings..." button again.
Screen of PreferenceActivity is garbled.
I have no custom code for drawing PreferenceActivity - only a few helper methods to initialize data.
Bug disappears after disabling h/w acceleration by setting android:hardwareAccelerated="false" in manifest. Apparently, scroll animation is not as smooth as with h/w acceleration.
Example of garbled screen:
Code of activity:
package org.package.name;
import android.content.SharedPreferences;
import android.os.Bundle;
public class Prefs extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener
{
public static final String PREFERENCES = "org.package.name";
// Option names and default values
public static final String OPT_AUTOROTATE = "autorotate";
private static final boolean OPT_AUTOROTATE_DEF = true;
public static final String OPT_FLOATING = "floating_type";
public static final String OPT_FLOATING_DEF = "1";
public static final String OPT_ZOOM = "zoom";
private static final boolean OPT_ZOOM_DEF = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(PREFERENCES);
addPreferencesFromResource(R.xml.settings);
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onDestroy() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
public static boolean getAutoRotate(SharedPreferences prefs) {
return prefs.getBoolean(OPT_AUTOROTATE, OPT_AUTOROTATE_DEF);
}
public static int getFloatingType(SharedPreferences prefs) {
return Integer.parseInt(prefs.getString(OPT_FLOATING, OPT_FLOATING_DEF));
}
public static boolean getZoom(SharedPreferences prefs) {
return prefs.getBoolean(OPT_ZOOM, OPT_ZOOM_DEF);
}
}

Netbeans not displaying UI

I'm running this in netbeans and it's not displaying anything. Does anyone know why netbeans isn't displaying the User Interface? Is it because I'm using an empty java file? My Code is below. I am new to netbeans and java so any help would be appreciated.
import java.awt.*;
import javax.swing.*;
class UserInterface extends javax.swing.JFrame {
public UserInterface() {
setTitle("My First UI");
setLayout(null);
setBounds(10,10,400,600);
Container con = getContentPane();
JLabel lblCustomerName = new JLabel("Customer Name");
JTextField txtCustomerName = new JTextField();
JButton btnOkay = new JButton("Okay");
lblCustomerName.setBounds(20,20,100,20);
txtCustomerName.setBounds(125,20,100,20);
btnOkay.setBounds(20,300,80,60);
con.add(lblCustomerName);
con.add(txtCustomerName);
con.add(btnOkay);
con.setVisible(true);
}
}
class Tester {
public static void main(String[] args) {
new UserInterface();
}
}
Your java code cannot show your frame.
Please set in your Tester.class:
class Tester {
public static void main(String[] args) {
UserInterface ui = new UserInterface();
ui.setVisible(true);
}
}
And you could remove con.setVisible(true); from your UserInterface.class.

JavaFX 2 and Internationalization

I've just started writing my first JavaFX 2 application after learning the basics and would like to internationalize it.
I notice that in JavaFX 1.x, the scripting language allowed for very simple internationalization of strings. Are there any similar features in JavaFX 2?
Basically: what is the best practice for internationalizing a JavaFX 2 application?
The basic steps (among others) of a java app internationalizing, are Localelizing and resource bundling. In JavaFX, you can use FXMLLoader#setResources() for that purposes. Here a SSCCE demo to demonstrate it. The codes are self-descriptive.
Demo package structure:
bundledemo
|------ BundleDemo.java
|------ MyController.java
|------ MyView.fxml
bundles
|------ MyBundle_en.properties
|------ MyBundle_kg.properties
MyBundle_en.properties
key1=Name Surname
key2=How are you?
MyBundle_kg.properties
key1=Aты Жөнү
key2=Кандайсың?
MyView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.*?>
<BorderPane fx:controller="bundledemo.MyController" xmlns:fx="http://javafx.com/fxml">
<top>
<!-- This label's text will be set by the controller -->
<Label fx:id="lblTextByController"/>
</top>
<center>
<!-- This label's text will be taken from the bundle automatically -->
<Label text="%key2"/>
</center>
</BorderPane>
MyController.java
package bundledemo;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class MyController implements Initializable {
#FXML private Label lblTextByController;
private ResourceBundle bundle;
#Override
public void initialize(URL location, ResourceBundle resources) {
bundle = resources;
lblTextByController.setText(bundle.getString("key1"));
}
}
BundleDemo.java
package bundledemo;
// imports are ignored.
public class BundleDemo extends Application {
private Stage stage;
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
Button btnEN = new Button();
btnEN.setText("English");
btnEN.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
loadView(new Locale("en", "EN"));
}
});
Button btnKG = new Button();
btnKG.setText("Kyrgyz");
btnKG.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
loadView(new Locale("kg", "KG"));
}
});
VBox root = new VBox(20);
root.getChildren().add(HBoxBuilder.create().spacing(10).style("-fx-background-color: gray").padding(new Insets(5)).children(btnEN, btnKG).build());
root.getChildren().add(new StackPane());
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
private void loadView(Locale locale) {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setResources(ResourceBundle.getBundle("bundles.MyBundle", locale));
Pane pane = (BorderPane) fxmlLoader.load(this.getClass().getResource("MyView.fxml").openStream());
// replace the content
StackPane content = (StackPane) ((VBox) stage.getScene().getRoot()).getChildren().get(1);
content.getChildren().clear();
content.getChildren().add(pane);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Screenshot:
If your internationalized text needs to be rendered in a font that might be on the user's target system, then you can either:
Embed the font with your application:
How to embed .ttf fonts is JavaFx 2.2?
OR
Use web(Google) fonts in JavaFX.
If the required font is not available, then the internationalized text might be displayed as unintelligible gibberish, even though everything else about the setup is fine.
This works for me:
└───src
├───app
├───bundles // <- here the "bundles"
├───dicts
├───images
├───libs
└───resources
In the bundles package are
LangBundle_en.properties
LangBundle_de.properties
Sample content:
enter_pwd=Enter your password:
To load them I use the following code:
#Override
public void initialize(URL location, ResourceBundle resources) {
ResourceBundle lngBndl = ResourceBundle
.getBundle("bundles.LangBundle", new Locale("en", "EN"));
tvSetupPwd.setText(lngBndl.getString("enter_pwd"));
// ...
}
Look at my example
More I described here or on GitHub
Update:
the solution is in Messages.java
/**
* The class with all messages of this application.
*/
public abstract class Messages {
private static ResourceBundle BUNDLE;
private static final String FIELD_NAME = "lookup";
private static final String BUNDLE_NAME = "messages/messages";
private static final String CONTROLS_BUNDLE_NAME = "com/sun/javafx/scene/control/skin/resources/controls";
public static final String MAIN_APP_TITLE;
public static final String DIALOG_HEADER;
public static final String MAIN_CONTROLLER_CONTENT_TEXT;
public static final String MAIN_CONTROLLER_HELLO_TEXT;
public static final String MAIN_CONTROLLER_GOODBYE_TEXT;
static {
final Locale locale = Locale.getDefault();
final ClassLoader classLoader = ControlResources.class.getClassLoader();
final ResourceBundle controlBundle = getBundle(CONTROLS_BUNDLE_NAME,
locale, classLoader, PropertyLoader.getInstance());
final ResourceBundle overrideBundle = getBundle(CONTROLS_BUNDLE_NAME,
PropertyLoader.getInstance());
final Map override = getUnsafeFieldValue(overrideBundle, FIELD_NAME);
final Map original = getUnsafeFieldValue(controlBundle, FIELD_NAME);
//noinspection ConstantConditions,ConstantConditions,unchecked
original.putAll(override);
BUNDLE = getBundle(BUNDLE_NAME, PropertyLoader.getInstance());
MAIN_APP_TITLE = BUNDLE.getString("MainApp.title");
DIALOG_HEADER = BUNDLE.getString("Dialog.information.header");
MAIN_CONTROLLER_CONTENT_TEXT = BUNDLE.getString("MainController.contentText");
MAIN_CONTROLLER_HELLO_TEXT = BUNDLE.getString("MainController.helloText");
MAIN_CONTROLLER_GOODBYE_TEXT = BUNDLE.getString("MainController.goodbyeText");
}
public static ResourceBundle GetBundle() {
return BUNDLE;
}
}
and in PropertyLoader.java
public class PropertyLoader extends ResourceBundle.Control {
private static final String PROPERTIES_RESOURCE_NAME = "properties";
private static final PropertyLoader INSTANCE = new PropertyLoader();
public static PropertyLoader getInstance() {
return INSTANCE;
}
#Override
public ResourceBundle newBundle(final String baseName, final Locale locale, final String format,
final ClassLoader loader, final boolean reload)
throws IllegalAccessException, InstantiationException, IOException {
final String bundleName = toBundleName(baseName, locale);
final String resourceName = toResourceName(bundleName, PROPERTIES_RESOURCE_NAME);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
final URL url = loader.getResource(resourceName);
if (url != null) {
final URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8));
} finally {
stream.close();
}
}
return bundle;
}
}

Resources