I'm learning javafx and want my application to be able to show gnome shell notifications. I'm using the standard gnome libraries for java. Here is a simple app that I created using javafx in which when a button is clicked, a notification will be created.
Main class
package gtknotifications;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.gnome.gtk.Gtk;
/**
*
* #author jyotiproy
*/
public class GtkNotifications extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXML file
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gtknotifications.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
Fxml Controller
package gtknotifications;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import org.gnome.notify.*;
import org.gnome.gtk.*;
/**
*
* #author jyotiproy
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
Notification notify = new Notification("Test", "This is a Test Gtk Notification","");
notify.setTimeout(1000);
notify.show();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The error I'm getting while clicking the button is
Caused by: org.freedesktop.bindings.FatalError:
You *must* call Gtk.init() before using anything else in java-gnome!
and
Caused by: java.lang.reflect.InvocationTargetException
Why are these errors coming and how to get rid of them?
EDIT
As the comments mentioned and the answer instructed I ran the code with adding the Gtk.init(new String[0]); in the start method of the main class but I got the following errors.
DANGER: GLib-GObject-WARNING, cannot register existing type 'GdkDisplayManager'
DANGER: GLib-CRITICAL, g_once_init_leave: assertion 'result != 0' failed
DANGER: GLib-GObject-CRITICAL, g_object_new_with_properties: assertion 'G_TYPE_IS_OBJECT (object_type)' failed
After showing these, the window doesn't load and no stack traces are shown. The build also doesn't stop and needs to be force closed.
As per the error message you are supposed to call the org.gnome.gtk.Gtk.init(String[]) method somewhere early in your application lifecycle, before you attempt to use any GTK features. As per the method javadoc:
Initialize the GTK libraries. This must be called before any other org.gnome.* classes are used.
You could try the below:
#Override
public void start(Stage stage) throws Exception {
Gtk.init(new String[0]);
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
...
Related
For education purposes I am trying to add hotkeys to my javafx application. Using my sample code, I am unable to access my label via hotkey. Using a button I can call the very same method updating my label succesfully.
The View:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="62.0" prefWidth="91.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx.probleme.SampleViewController">
<children>
<Label id="label" fx:id="label" layoutX="14.0" layoutY="45.0" text="Label" />
<Button layoutX="20.0" layoutY="14.0" mnemonicParsing="false" onAction="#updateText" text="Button" />
</children>
</AnchorPane>
And the controller:
package fx.probleme;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class SampleViewController extends Application {
#FXML
Label label;
#FXML
void updateText() {
label.setText(label.getText() + "+");
}
#Override
public void start(Stage stage) throws Exception {
Parent parent = FXMLLoader.load(this.getClass().getResource("SampleView.fxml"));
Scene scene = new Scene(parent);
scene.setOnKeyPressed((final KeyEvent keyEvent) -> {
if (keyEvent.getCode() == KeyCode.NUMPAD0) {
updateText();
}
});
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You get NullPointerException, because at that stage the Label is not initialized, the initialization is done in the initialize.
First of all you have mixed your main class with your controller class, you may want to separate them, setting a controller that implements Initializable, after that in the initialize method you can call any method of the components because in it all of the components annotated by #FXML are initialized. In your case, in start method is not yet initialized. Also you may don't want to use the scene's method, instead of you can add events, actions to your content pane, in your case to the AnchorPane.
I would suggest to separate the controller class from your main class, and implement Initializable. This helps you to have a better vision over your application, you cans see where exactly your components are initialized, were are you sure about using their methods, without NPE.
If you don't want to do it in a separate class(which is recommended) you can add an fx:id for AnchorPane in the .fxml file, then you can add the method to onKeyPressed like you did for the Button.
I have installed Scene Builder and opened a new FXML Project just to test it out. I have seen on other computers that when a new FMXL Project is opened, the default code generates a button that displays text when clicked. However, when I try to run the main method of the default FXML Project, I get a stack error with a NullPointerException. I have searched many question threads on how to fix it but none of them really give me a concrete answer. Any help would be appreciated.
## JavaFXApplication2.java ##
package javafxapplication2;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author Hafiz
*/
public class JavaFXApplication2 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
## FXMLDocumentController.java ##
}
package javafxapplication2;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
/**
*
* #author Hafiz
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
## FXMLDocument.fxml ##
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication2.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
I think that your problem is caused by private method "handleButtonAction". Turn it to public and try then. Greetings
i'm fairly new to javafx and fxml. I'm trying to teach myself! However, when I was creating a program for a simple login GUI I came into an issue when I finally tried to run my program. It told me there was no main method in my class and I'm unsure of how to fix it. Any ideas?
My program creates a login screen and when you enter "test" for the username and password it'll take you to another scene.
Here is my Login.java
package com;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
/**
*
* #author Tyler
*/
public class Login extends Application{
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Login");
stage.show();
}
}
Here is my LoginController.java
package com;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* #author Tyler
*/
public class LoginController implements Initializable {
#FXML
private Label lblMessage;
#FXML
private TextField txtUsername;
#FXML
private PasswordField txtPassword;
#FXML
private void btnLoginAction(ActionEvent event) throws Exception{
if(txtUsername.getText().equals("test") && txtPassword.getText().equals("test")){
((Node) (event.getSource())).getScene().getWindow().hide();
Parent parent = FXMLLoader.load(getClass().getResource("DateSelection.fxml"));
Stage stage = new Stage();
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.setTitle("Date Selection");
stage.show();
}else{
lblMessage.setText("Username or Password is invalid!");
}
}
/**
* Initializes the controller class.
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Here is my Login.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" fx:id="lblMessage" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.LoginController">
<children>
<PasswordField fx:id="txtPassword" layoutX="200.0" layoutY="200.0" prefHeight="30.0" prefWidth="200.0" promptText="Password" />
<TextField fx:id="txtUsername" layoutX="200.0" layoutY="140.0" prefHeight="30.0" prefWidth="200.0" promptText="Username" />
<Button fx:id="btnLogin" layoutX="269.0" layoutY="251.0" mnemonicParsing="false" onAction="#btnLoginAction" prefHeight="30.0" text="Login">
<font>
<Font size="14.0" />
</font></Button>
<Label fx:id="lblMessage" layoutX="283.0" layoutY="71.0" text="Label" />
</children>
</AnchorPane>
Here is my DateSelectionController.java
package com;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
/**
* FXML Controller class
*
* #author Tyler
*/
public class DateSelectionController implements Initializable {
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Here is my DateSelection.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="com.DateSelectionController">
<children>
<Label layoutX="191.0" layoutY="164.0" text="Welcome">
<font>
<Font name="System Bold" size="50.0" />
</font>
</Label>
</children>
</AnchorPane>
From Oracle:
The main() method is not required for JavaFX applications when the JAR file for the application is created with the JavaFX Packager tool, which embeds the JavaFX Launcher in the JAR file. However, it is useful to include the main() method so you can run JAR files that were created without the JavaFX Launcher, such as when using an IDE in which the JavaFX tools are not fully integrated. Also, Swing applications that embed JavaFX code require the main() method.
So one solution is to make sure it's being built in a way that fully supports the JavaFX tools. The other solution is to add a main method to starts the application. That would avoid any potential problems like this, and doesn't cause any problems in the case where it's not needed.
Your main method should look like this:
public static void main(String[] args){
Application.launch(Login.class, args);
}
That will simply pass control on to JavaFX to handle like it would normally.
This question already has an answer here:
javafx 8 compatibility issues - FXML static fields
(1 answer)
Closed 8 years ago.
I am using JavaFX 8 and FXML in this project and trying to update my text area with the results from other classes within the program.
The Text Area is defined in the FXML document as such:
<TextArea fx:id="feedBack" editable="false" focusTraversable="false"
layoutX="203.0" layoutY="32.0" prefHeight="205.0" prefWidth="308.0"
wrapText="true"/>
It is called in the controller here, note that originally it was a "private" item but to make it work with the classes I made it public:
#FXML
public static TextArea feedBack;
EDIT: It is worth noting that when the TextArea is identified as "private" I have no issue getting the set/append text method to work but this does not allow me to use the text area in other classes, which is what I need to do.
However now when I try to do either appendText() or setText(), such as follows:
feedBack.setText("Connection Made");
I am given a null point exception. Why is this? I have made this work in JavaFX 7 with FXML by doing the same thing and it works fine. What am I missing to make this work?
EDIT, test/proof of brokenness with complete tiny program.
I did not make another class for this one as the textarea won't work in the control anyway.
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="textareatester.FXMLDocumentController">
<children>
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<TextArea fx:id="feedback" layoutX="61.0" prefHeight="200.0" prefWidth="200.0" wrapText="true" />
<Button fx:id="dostuff" layoutX="261.0" layoutY="62.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Button" />
</children>
</AnchorPane>
Main Method:
package textareatester;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TextAreaTester extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Controller Class:
package textareatester;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
public static TextArea feedback;
#FXML
private Button dostuff;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
feedback.setText("Hello World!"); ///<-- this is what gives me the NPE
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// not touching anything
}
}
Solution for those who are curious:
I ended up simply returning my results strings from my methods and then appending them to the TextArea.
The problem is the static at the definition of the TextArea. Since static attributes are bound to the class and not the object, variable feedback is never initiated and thus is null when accessed in the EventHandler.
Today i am Going to create Hello World Application with JavaFX Fxml project.Here is the code.
Sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="temp.Temp">
<children>
<Button id="button" layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" prefHeight="16" prefWidth="69" fx:id="label" />
</children>
</AnchorPane>
Sample.java
package temp;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class Sample implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Temp.java
package temp;
import javafx.application.Appl
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Temp extends Application {
public static void main(String[] args) {
Application.launch(Temp.class, args);
}
#Override
public void start(Stage stage) throws Exception {
try{
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
stage.setScene(new Scene(root));
stage.show();
}
catch(Exception e){
System.out.print(e);
}
}
}
But It is Giving Error
/Users/apple/NetBeansProjects/Temp/nbproject/jfx-impl.xml:1757: The following error occurred while executing this line:
/Users/apple/NetBeansProjects/Temp/nbproject/jfx-impl.xml:1392: jarsigner returned: 1
BUILD FAILED (total time: рем seconds)
But When i Use Exception Handling it Gives Location Not Found ?
Please help
You are trying to load Controller from fx:controller="temp.Temp". This is not Your controller class, you should use fx:controller="temp.Sample" instead.
You also need a leading forward slash to load package resources. Assuming that you have Sample.fxml in the temp package, it would look like this:
Parent root = FXMLLoader.load(getClass().getResource("/temp/Sample.fxml"));