This question already has answers here:
getResourceAsStream returns null
(26 answers)
How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?
(1 answer)
Closed 1 year ago.
first of all, I'm a complete begginer in Java and JavaFX, using IntelliJ Idea for that.
I have tried to download and run a piece of game's code but ran into a problem that I can't pinpoint the cause of.
I have this in my VM options:
--module-path
${PATH_TO_FX};${OUTPUT}
--add-modules
javafx.controls,javafx.fxml
Error message itself:
Exception in Application constructor
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1071)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class gg.game.Game
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:891)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:803)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
... 1 more
Caused by: java.lang.NullPointerException: Input stream must not be null
at javafx.graphics/javafx.scene.image.Image.validateInputStream(Image.java:1142)
at javafx.graphics/javafx.scene.image.Image.<init>(Image.java:705)
at gg.game/gg.game.Game.<init>(Game.java:19)
... 14 more
Exception running application gg.game.Game
Game's code:
package gg.game;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.HashMap;
public class Game extends Application {
public static ArrayList<Block> platforms = new ArrayList<>();
private HashMap<KeyCode,Boolean> keys = new HashMap<>();
Image backgroundImg = new Image(getClass().getResourceAsStream("background.png"));
public static final int BLOCK_SIZE = 45;
public static final int MARIO_SIZE = 40;
public static Pane appRoot = new Pane();
public static Pane gameRoot = new Pane();
public Character player;
int levelNumber = 0;
private int levelWidth;
private void initContent(){
ImageView backgroundIV = new ImageView(backgroundImg);
backgroundIV.setFitHeight(14*BLOCK_SIZE);
backgroundIV.setFitWidth(212*BLOCK_SIZE);
levelWidth = LevelData.levels[levelNumber][0].length()*BLOCK_SIZE;
for(int i = 0; i < LevelData.levels[levelNumber].length; i++){
String line = LevelData.levels[levelNumber][i];
for(int j = 0; j < line.length();j++){
switch (line.charAt(j)){
case '0':
break;
case '1':
Block platformFloor = new Block(Block.BlockType.PLATFORM, j * BLOCK_SIZE, i * BLOCK_SIZE);
break;
case '2':
Block brick = new Block(Block.BlockType.BRICK,j*BLOCK_SIZE,i*BLOCK_SIZE);
break;
case '3':
Block bonus = new Block(Block.BlockType.BONUS,j*BLOCK_SIZE,i*BLOCK_SIZE);
break;
case '4':
Block stone = new Block(Block.BlockType.STONE,j * BLOCK_SIZE, i * BLOCK_SIZE);
break;
case '5':
Block PipeTopBlock = new Block(Block.BlockType.PIPE_TOP,j * BLOCK_SIZE, i * BLOCK_SIZE);
break;
case '6':
Block PipeBottomBlock = new Block(Block.BlockType.PIPE_BOTTOM,j * BLOCK_SIZE, i * BLOCK_SIZE);
break;
case '*':
Block InvisibleBlock = new Block(Block.BlockType.INVISIBLE_BLOCK,j * BLOCK_SIZE, i * BLOCK_SIZE);
break;
}
}
}
player =new Character();
player.setTranslateX(0);
player.setTranslateY(400);
player.translateXProperty().addListener((obs,old,newValue)->{
int offset = newValue.intValue();
if(offset>640 && offset<levelWidth-640){
gameRoot.setLayoutX(-(offset-640));
backgroundIV.setLayoutX(-(offset-640));
}
});
gameRoot.getChildren().add(player);
appRoot.getChildren().addAll(backgroundIV,gameRoot);
}
private void update(){
if(isPressed(KeyCode.UP) && player.getTranslateY()>=5){
player.jumpPlayer();
}
if(isPressed(KeyCode.LEFT) && player.getTranslateX()>=5){
player.setScaleX(-1);
player.animation.play();
player.moveX(-5);
}
if(isPressed(KeyCode.RIGHT) && player.getTranslateX()+40 <=levelWidth-5){
player.setScaleX(1);
player.animation.play();
player.moveX(5);
}
if(player.playerVelocity.getY()<10){
player.playerVelocity = player.playerVelocity.add(0,1);
}
player.moveY((int)player.playerVelocity.getY());
}
private boolean isPressed(KeyCode key){
return keys.getOrDefault(key,false);
}
#Override
public void start(Stage primaryStage) throws Exception {
initContent();
Scene scene = new Scene(appRoot,1200,620);
scene.setOnKeyPressed(event-> keys.put(event.getCode(), true));
scene.setOnKeyReleased(event -> {
keys.put(event.getCode(), false);
player.animation.stop();
});
primaryStage.setTitle("Mini Mario");
primaryStage.setScene(scene);
primaryStage.show();
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
update();
}
};
timer.start();
}
public static void main(String[] args) {
launch(args);
}
}
I would be grateful to any kind of response. Thank you.
Related
This program is a music player that allows user to pick a .wav file, play, pause, resume, and restart a the music file from a clip object and audioinput stream. The audio input stream loads a file that is determined by user via FileChooser. The program can play, pause, and resume by selecting a file, pressing play, pause, then play again, but does not play using the restart method or the resume method invoked via the respective buttons. Instead, the program hangs until the X button is clicked. I think it has something to do with the resetaudiostream method, but I am unsure what. Maybe something to do with ending the old clip and creating a new clip instance. Please review the logic and let me know what is making it hang and how that could be remedied.
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class Main extends Application {
static File musicfile;
static Long currentFrame;
static Clip clip;
static String status = "play";
static AudioInputStream audioInputStream;
static String filePath;
public void SimpleAudioPlayer()
throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
// create AudioInputStream object
audioInputStream =
AudioSystem.getAudioInputStream(new File(filePath).getAbsoluteFile());
// create clip reference
clip = AudioSystem.getClip();
// open audioInputStream to the clip
clip.open(audioInputStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Music Player");
GridPane gp = new GridPane();
Button selectFile = new Button("Select File");
GridPane.setConstraints(selectFile, 0,0);
selectFile.setOnAction(event->{
FileChooser filechooser = new FileChooser();
// create AudioInputStream object
try {
musicfile = filechooser.showOpenDialog(null);
audioInputStream = AudioSystem.getAudioInputStream(musicfile);
clip = AudioSystem.getClip();
// open audioInputStream to the clip
clip.open(audioInputStream);
}catch(IOException | UnsupportedAudioFileException | LineUnavailableException e){
e.printStackTrace();
}
});
Button play = new Button("Play");
GridPane.setConstraints(play, 1,0);
play.setOnAction(event->{
if(status == "play") {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
play();
});
Button pause = new Button("Pause");
GridPane.setConstraints(pause, 2,0);
pause.setOnAction(event -> pause());
Button restart = new Button("Restart");
GridPane.setConstraints(restart, 0,1);
restart.setOnAction(event -> {
try{
restart();
}
catch(IOException | UnsupportedAudioFileException | LineUnavailableException e){
e.printStackTrace();}
});
Button resume = new Button("Resume");
GridPane.setConstraints(resume, 1,1);
resume.setOnAction(event -> {
try {
resumeAudio();
}catch(IOException | LineUnavailableException | UnsupportedAudioFileException e){
e.printStackTrace();
}
});
gp.getChildren().addAll(play,selectFile, pause, restart, resume);
primaryStage.setScene(new Scene(gp, 300, 275));
primaryStage.show();
}
public void play()
{
//start the clip
clip.start();
status = "play";
}
// Method to pause the audio
public void pause()
{
if (status.equals("paused"))
{
System.out.println("audio is already paused");
return;
}
currentFrame =
clip.getMicrosecondPosition();
clip.stop();
status = "paused";
}
// Method to resume the audio
public void resumeAudio() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
if (status.equals("play"))
{
System.out.println("Audio is already "+
"being played");
return;
}
clip.close();
resetAudioStream();
clip.setMicrosecondPosition(currentFrame);
status = "play";
play();
}
// Method to restart the audio
public void restart() throws IOException, LineUnavailableException,
UnsupportedAudioFileException
{
clip.stop();
clip.close();
resetAudioStream();
currentFrame = 0L;
clip.setMicrosecondPosition(0);
status = "play";
play();
}
// Method to stop the audio
public void stop() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
currentFrame = 0L;
clip.stop();
clip.close();
}
// Method to jump over a specific part
public void jump(long c) throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
if (c > 0 && c < clip.getMicrosecondLength())
{
clip.stop();
clip.close();
resetAudioStream();
currentFrame = c;
clip.setMicrosecondPosition(c);
this.play();
}
}
// Method to reset audio stream
public void resetAudioStream() throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
audioInputStream = AudioSystem.getAudioInputStream(musicfile);
clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public static void main(String[] args) {
launch(args);
}
}
It is quiet simple to get the required functionality with a MediaPlayer:
import java.net.URI;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.stage.Stage;
import javafx.util.Duration;
/*
* If you get "cannot access class com.sun.glass.utils.NativeLibLoader" exception you may need to
* add a VM argument: --add-modules javafx.controls,javafx.media as explained here:
* https://stackoverflow.com/questions/53237287/module-error-when-running-javafx-media-application
*/
public class Main extends Application {
private MediaPlayer player;
private static final long JUMP_BY = 5000;//millis
#Override
public void start(Stage primaryStage) throws Exception{
URI uri = new URI("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3");
Media media = new Media(uri.toString());
//OR Media media = new Media("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3");
player = new MediaPlayer(media);
player.setOnError(() -> System.out.println(media.getError().toString()));
GridPane gp = new GridPane();
gp.setHgap(10);
Button play = new Button("Play");
GridPane.setConstraints(play, 0,0);
play.setOnAction(event-> playAudio());
Button pause = new Button("Pause");
GridPane.setConstraints(pause, 1,0);
pause.setOnAction(event -> pauseAudio());
Button resume = new Button("Resume");
GridPane.setConstraints(resume, 2,0);
resume.setOnAction(event -> resumeAudio());
Button stop = new Button("Stop");
GridPane.setConstraints(stop, 3,0);
stop.setOnAction(event -> stopAudio());
Button restart = new Button("Restart");
GridPane.setConstraints(restart, 4,0);
restart.setOnAction(event -> restartAudio());
Button jump = new Button("Jump >");
GridPane.setConstraints(jump, 5,0);
jump.setOnAction(event -> jump(JUMP_BY));
Label time = new Label();
GridPane.setConstraints(time, 6,0);
time.textProperty().bind( player.currentTimeProperty().asString("%.4s") );
gp.getChildren().addAll(play, pause, resume, stop, restart, jump, time);
primaryStage.setScene(new Scene(gp, 400, 45));
primaryStage.show();
}
//play audio
public void playAudio()
{
player.play();
}
//pause audio
public void pauseAudio()
{
if (player.getStatus().equals(Status.PAUSED))
{
System.out.println("audio is already paused");
return;
}
player.pause();
}
//resume audio
public void resumeAudio()
{
if (player.getStatus().equals(Status.PLAYING))
{
System.out.println("Audio is already playing");
return;
}
playAudio();
}
//restart audio
public void restartAudio()
{
player.seek(Duration.ZERO);
playAudio();
}
// stop audio
public void stopAudio()
{
player.stop();
}
//jump by c millis
public void jump(long c)
{
player.seek(player.getCurrentTime().add(Duration.millis(c)));
}
public static void main(String[] args) {
launch(args);
}
}
I made the following source code and succeed in communicating via RS232.
Then, I attempted to make jar file the source code.I can make the runnable jar file. But it couldn't execute the program when I execute double click in another PC(In case that I used my PC, The jar file executes properly.).
What should I do to resolve the problem.
I read some involved question, but I do't know what I should do.
So, please let me know the detail procedure how to make jar file.
[I have made jar file of other program before but then it didn't include external jar file. In this time, I used a jar file(RxTxcomm.jar) and two dll file to make the program . so I don't know the way of linking one another.]
My source code
[MyRxTx.java]
package sample;
import javafx.application.Platform;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
public class MyRxTx implements SerialPortEventListener {
SerialPort serialPort;
Main sample_serial;
public byte[] SendBuffer;
/**
* The port we're normally going to use.
*/
private final String PORT_NAMES[] = {
"COM29",
"COM30",
"COM31",
};
private InputStream inputStream;
private OutputStream outputStream;
private static final int TIME_OUT = 2000;
private static final int Baud_Rate = 115200;
public void initialize() throws InterruptedException {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId
= (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
} else {
System.out.println("Port Name: " + portId.getName() + "\n"
+ "Current Owner: " + portId.getCurrentOwner() + "\n"
+ "Port Type: " + portId.getPortType());
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(
Baud_Rate,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
SendBuffer=new byte[]{(byte)0x41,(byte)0x54};
write(SendBuffer);
}
#Override
public void serialEvent(SerialPortEvent Serial_event){
int received_data = 0;
StringBuffer buffer = new StringBuffer();
if(Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE){
while(true){
try{
received_data = inputStream.read();
if(received_data == -1) break;
if((char)received_data != '\r'){
buffer.append((char)received_data);
}
else{
buffer.append('\n');
break;
}
}
catch(IOException ex){}
}//while()文ここまで。
System.out.println("Receive Data:"+buffer);
Platform.runLater( () ->{
sample_serial.label_receive.setText("Receive Data:"+buffer);
});
}
}
protected void write(byte[] buffer) throws InterruptedException{
try {
outputStream.write(buffer);
outputStream.flush();
} catch (IOException e) {
System.err.println("Cannot write:" + e.getMessage());
}
}
/**
* This should be called when you stop using the port. This will prevent
* port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
}
[Main.java]
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBox;
import javafx.scene.layout.VBoxBuilder;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.stage.Stage;
import javafx.stage.StageBuilder;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main extends Application {
MyRxTx myRxTx;
private TextField text_Send;
public static Label label_receive;
#Override
public void start(Stage primaryStage) throws InterruptedException {
Button btn_send = ButtonBuilder.create().text("Send")
.prefWidth(100).alignment(Pos.CENTER)
.id("Send").build();
text_Send = TextFieldBuilder.create().text("Sending message").alignment(Pos.CENTER)
.prefWidth(150).build();
Font Font_receive = Font.font("Arial", FontPosture.REGULAR,20);
label_receive = LabelBuilder.create().text("Recieved message")
.alignment(Pos.TOP_CENTER).prefWidth(400).font(Font_receive).build();
HBox root1 = HBoxBuilder.create().spacing(100).children(text_Send,btn_send).build();
HBox root2 = HBoxBuilder.create().spacing(100).children(label_receive).build();
VBox root3 = VBoxBuilder.create().spacing(15).children(root1,root2).build();
Scene scene = new Scene(root3);
myRxTx = new MyRxTx();
myRxTx.initialize();
scene.addEventHandler(ActionEvent.ACTION,actionHandler);
primaryStage = StageBuilder.create().width(410).height(340).scene(scene).title("Serial Communication Test Tool").build();
primaryStage.show();
}
EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>(){
public void handle (ActionEvent e){
Button src =(Button)e.getTarget();
String text = src.getId();
System.out.println("Select Button:"+text);
String text_send = text_Send.getText();
if(text.equals("Send")){
try {
myRxTx.write(text_send.getBytes());
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
/* main*/
public static void main(String[] args) {
launch(args);
}
}
I have created a Grid Pane with a number of rows. A marker should only be moveable on 1 row. When moving the mouse it should move sideways only, left or right. When you click on the marker it should be locked, no more movement. It should be highlighted with a different color.
How can I achive this?
If you know any tutorials or examples please add, thanks.
Message Output:
Executing
C:\Users\s22380\Desktop\temp\JavaFXApplication9\dist\run269988000\JavaFXApplication9.jar
using platform C:\Program Files\Java\jdk1.8.0_92\jre/bin/java
Exception in Application constructor
java.lang.reflect.InvocationTargetException at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at
com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application
instance: class javafxapplication9.JavaFXApplication9 at
com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
at
com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745) Caused by:
java.lang.reflect.InvocationTargetException at
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at
com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:819)
at
com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at
com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method) at
com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at
com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at
com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
... 1 more Caused by: java.lang.NullPointerException at
sample.Controller.(Controller.java:33) at
javafxapplication9.JavaFXApplication9.(JavaFXApplication9.java:19)
... 13 more Exception running application
javafxapplication9.JavaFXApplication9 Java Result: 1 Deleting
directory
C:\Users\s22380\Desktop\temp\JavaFXApplication9\dist\run269988000
jfxsa-run: BUILD SUCCESSFUL (total time: 1 second)
How about this: Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application
{
Controller controller = new Controller(10,10);
#Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
loader.setController(this.controller);
Parent root = (Parent)loader.load();
this.controller.InitUi();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is basically the sample code when you say new JavaFX project in IntelliJ. I changed it to explicitly set the controller. But that is just personal preference.
The xaml for that
<?import javafx.scene.layout.*?>
<GridPane fx:id="mainGrid" alignment="center" gridLinesVisible="true" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
</children>
</GridPane>
Again. Basically the default stuff.
I also added a style sheet to define the different lock for the not movable state.
redStyle.css
.button {
-fx-text-fill: #006464;
-fx-background-color: #DFB951;
-fx-border-radius: 20;
-fx-background-radius: 20;
-fx-padding: 5;
}
Now for the controller.
It will do a few things:
Listen to the mouse events of the object I want to push around. If the delata is big enough I will move it => if the mouse is moved fast enough
When the button is pressed I will switch out the style sheet to get the different look. Right now this style works on all buttons in the scene. It could be changed to work only on a specific one.
package sample;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.shape.Rectangle;
public class Controller
{
#FXML
private GridPane mainGrid;
#FXML
private Button movable;
private final int sizeX;
private final int sizeY;
private final double minMoveDistanc = 3;
private boolean canMove = true;
private Double lastX = null;
private Double lastY = null;
private String redButtonStyle = Controller.class.getResource("redStyle.css").toExternalForm();
public Controller(int sizeX, int sizeY)
{
this.sizeX = sizeX;
this.sizeY = sizeY;
}
public void InitUi()
{
if (this.mainGrid != null)
{
final int numCols = sizeX;
final int numRows = sizeY;
for (int i = 0; i < numCols; i++)
{
ColumnConstraints colConst = new ColumnConstraints();
this.mainGrid.getColumnConstraints().add(colConst);
}
for (int i = 0; i < numRows; i++)
{
RowConstraints rowConst = new RowConstraints();
this.mainGrid.getRowConstraints().add(rowConst);
}
// add rectangle to keep grid in size
for (int i = 0; i < numCols; i++)
{
for (int j = 0; j < numRows; j++)
{
Rectangle rect = new Rectangle();
rect.setWidth(50);
rect.setHeight(50);
this.mainGrid.add(rect,i,j);
}
}
// ad movable object (Button)
this.movable = new Button("Hallo");
this.movable.setPrefWidth(50);
this.movable.setPrefHeight(50);
this.movable.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent actionEvent)
{
canMove = ! canMove;
movable.setText(canMove? "move" : "stop");
if (canMove)
{
movable.getScene().getStylesheets().remove(redButtonStyle);
}
else
{
movable.getScene().getStylesheets().add(redButtonStyle);
}
}
});
this.mainGrid.add(this.movable,5,5);
}
if (this.movable != null)
{
this.movable.setOnMouseEntered(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
lastX = null;
lastY = null;
}
});
this.movable.setOnMouseExited(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
lastX = null;
lastY = null;
}
});
this.movable.setOnMouseMoved(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
if (!canMove)
{ return; }
double x = mouseEvent.getSceneX();
double y = mouseEvent.getSceneY();
if (lastX == null)
{
lastX = x;
lastY = y;
return;
}
// calculate delta
double deltaX = x - lastX;
double deltaY = y - lastY;
// remember new position
lastX = x;
lastY = y;
boolean moved = false;
// x movement
if (Math.abs(deltaX) > minMoveDistanc)
{
moved = true;
int currentColumn = GridPane.getColumnIndex(movable);
if (deltaX < 0)
{
GridPane.setColumnIndex(movable, Math.max(currentColumn -1 ,0));
}
else
{
GridPane.setColumnIndex(movable, Math.min(currentColumn + 1 ,sizeX-1));
}
}
// y movement
if (Math.abs(deltaY) > minMoveDistanc)
{
moved = true;
int currentRow = GridPane.getRowIndex(movable);
if (deltaY < 0)
{
GridPane.setRowIndex(movable, Math.max(currentRow - 1 ,0));
}
else
{
GridPane.setRowIndex(movable, Math.min(currentRow + 1 ,sizeY-1));
}
}
if (moved)
{
lastX = null;
lastY = null;
}
}
});
}
}
}
I'm working on Eclipse e4 RCP application where I have one SWT part. Using JavaFX interoperability with SWT I have added javafx.embed.swt.FXCanvas. After I create a javafx.scene.Scene with 50000 javafx.scene.control.Button and hook it to the canvas, application memory jumps to 1.5gb.
Problem starts when I close that part, application does not release a memory. When I open that part again, memory jumps to 2.something gb.
Part class:
import javax.annotation.PostConstruct;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import javafx.embed.swt.FXCanvas;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
public class StressTestJavaFXPart
{
private Scene scene;
private FXCanvas canvas;
private final int columns = 100;
private final int rows = 500;
#PostConstruct
public void createComposite(final Composite parent)
{
parent.setLayout(new GridLayout(1, false));
canvas = new FXCanvas(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).span(0, 0).applyTo(canvas);
final Pane pane = new Pane();
for (int i = 0; i < columns ; i++)
{
for (int j = 0; j < rows ; j++)
{
final Button button = new Button(String.format("%s : %s", i, j));
pane.getChildren().add(button);
button.setLayoutX(100 * i);
button.setLayoutY(100 * j);
}
}
final ScrollPane sp = new ScrollPane(pane);
scene = new Scene(sp);
canvas.setScene(scene);
parent.addDisposeListener(new DisposeListener()
{
#Override
public void widgetDisposed(final DisposeEvent e)
{
canvas.dispose();
System.gc();
}
});
}
}
Any suggestions are very welcome! Thanks
I solved it using reflection:
parent.addDisposeListener(disposeEvent -> {
//release Pixel Buffer via Reflection -> prevents memory leak
try {
Field pixelBuffer = FXCanvas.class.getDeclaredField("pixelsBuf");
pixelBuffer.setAccessible(true);
pixelBuffer.set(this, null);
} catch (NoSuchFieldException | IllegalAccessException e) {
}
});
Worked well for me.
First of all it's my first app, I'm trying to code a calculator. When pressing an operator, if there is old one, calculate it and send the result to continue with it to the new process. The calculation process don't go to the second step, anyone can help to make this code work properly?
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class main extends Application {
String num1 ="";
String num2 ="";
String op ;
double result= 0;
boolean oldop =false ;
// the GUI component
public void start(Stage stage) throws Exception {
Button one = new Button("1");
Button two = new Button("2");
Button pls = new Button("+");
Button eql = new Button("=");
Button ac = new Button("AC");
Label lbl = new Label("empty");
FlowPane pane = new FlowPane();
pane.setHgap(10);
pane.getChildren().addAll(one,two,pls,eql,ac,lbl);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show();
// The Actions on buttons
one.setOnAction(e ->
{
if(!oldop){
num1+='1';
lbl.setText(num1);}
else {
num2+='1';
lbl.setText(num2);}});
two.setOnAction(e ->
{
if(!oldop){
num1+='2';
lbl.setText(num1);}
else {
num2+='2';
lbl.setText(num2);}});
pls.setOnAction(e -> {
if(!oldop){
oldop = true;
op="+";
lbl.setText(op);}
else {
result=calc(num1 , num2 ,op);
num1=String.valueOf(result);
num2="";
op="+";
lbl.setText(num1+op);
oldop = true;}});
eql.setOnAction(e ->{
if(oldop){
result=calc(num1 , num2 , op);
lbl.setText(String.valueOf(result));
oldop=false;
num2="";}
else
return;});
ac.setOnAction(e -> {
num1="";
num2="";
result=0;
oldop=false;});
}
// The calculation method
public int calc (String n1 , String n2 , String op){
switch (op) {
case "+" :
return Integer.parseInt(n1) + Integer.parseInt(n2) ;
case "-" :
return Integer.parseInt(n1) - Integer.parseInt(n2) ;
case "*" :
return Integer.parseInt(n1) * Integer.parseInt(n2) ;
case "/" :
return Integer.parseInt(n1) / Integer.parseInt(n2) ;
default :
return 0;
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
The problem seems to be that you cannot use the result of an previous operation in the second step, because you use String.valueOf which gives e.g. 3.0 for the int 3 (result of 1+2). This string cannot be used again in calc as it cannot be parsed back to an int with `Integer.parseInt.
I would suggest to work with int and only convert them to strings for the labels.
An ulgy workaround would be to add the following lines at the beginning of calc:
n1=n1.split("\\.")[0];
n2=n2.split("\\.")[0];