I am trying a build a small video player using java I am getting some errors,please help me fix them.
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Player player = new Player("/Users/name/Desktop/play.mp4");
Scene scene = new Scene(player, 720,480,Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
package sample;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
/**
* Created by akanksh on 03/11/17.
*/
public class Player extends BorderPane {
Media media;
MediaPlayer player;
MediaView view;
Pane mpane;
public Player(String file){
media = new Media(file);
player = new MediaPlayer(media);
view = new MediaView(player);
mpane = new Pane();
mpane.getChildren().add(view);
setCenter(mpane);
player.play();
}
}
errors :
No matter how many times I tried using different videos and different paths,its not working...help needed...
The media class needs a valid URI
Therefore you need a "schema" for your file such as file:///Users/...
Or you could use new File("/Users/name/Desktop/play.mp4").toURI()
The media constructor is looking for a URI, not a file path. If you are really specifying a file for the media (i.e. something the user specified on the file system, for example via a FileChooser) you should convert the path to a valid URI that both has a scheme and properly encodes any invalid characters in the path, such as whitespace.
If you have a File object, you simply do this with
File file = ... ;
Media media = new Media(file.toURI().toString());
If the file is specified as a string, create a file object first (though in any realistic situation you should have a File to begin with):
public Player(String file){
media = new Media(new File(file).toURI().toString());
player = new MediaPlayer(media);
view = new MediaView(player);
mpane = new Pane();
mpane.getChildren().add(view);
setCenter(mpane);
player.play();
}
Note that in the case where the media is part of the application (instead of being provided on the user's filesystem at run time), you should use a different technique entirely and treat it as a resource. See, for example, How to reference javafx fxml files in resource folder? for accessing resources in JavaFX.
Related
I'm trying to import an fxml file into my main class and Parent root = FXMLLoader.load(getClass().getResource(/View/Main_Form.fxml)); returns null.
It basically is telling me that it can't find the "Main_Form.fxml" file that I am asking it to find.
I have it in a package labeled "View" which is the path I specified.
code is as follows:
`package com.example.c482_1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/view/Main_Form.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}`
file structure of the project
I have tried checking the path, I made my main project the resource root with no luck as well.
Not quite sure but I would try checking to make sure the path is relative
I am using JavaFX to write a sample video player. But the tests fails when run together, ( Note: individually test passes).
Error: Unexpected exception thrown: java.lang.IllegalStateException: Application launch must not be called more than once
I understand that calling launch() twice on same Application Instance is causing this issue as per this . But I am not able to understand, that after one test completes, why the app is still running ? Why new instance is not getting created for 2nd test. testUnsupportedVideoFileThrowsError() succeeds but testSupportedVideoFilePlaysSuccessfully() fails.
package media;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import java.io.File;
public class PlayVideoSnippet extends Application {
private static String source;
private Media media = null;
private MediaPlayer mediaPlayer = null;
private MediaView mediaView = null;
private Scene scene = null;
public static void playVideo(String source) {
PlayVideoSnippet.source = source;
PlayVideoSnippet.launch();
}
#Override
public void start(Stage stage) throws InterruptedException {
try {
media = new Media(new File(source).toURI().toString());
//onError close the app
media.setOnError(() -> {
Platform.exit();
});
//Create MediaPlayer, with media
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
//onEnd of media, close the app
mediaPlayer.setOnEndOfMedia(() -> {
Platform.exit();
});
//Create media viewer
mediaView = new MediaView(mediaPlayer);
//create scene
scene = new Scene(new Group(), media.getWidth(), media.getHeight());
stage.setScene(scene);
stage.setTitle("Video Player");
//attach the mediaView to the scene root
((Group) scene.getRoot()).getChildren().add(mediaView);
stage.show();
} finally {
System.out.println("Inside finally");
stage.close();
}
}
}
package media;
import javafx.scene.media.MediaException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PlayVideoSnippetTest {
/**
* Tests for {#link PlayVideoSnippet#playVideo(String)}.
*/
final String PATH_OF_SUPPORTED_VIDEO_FILE = "src/test/resources/file_example_MP4_480_1_5MG.mp4";
final String PATH_OF_UNSUPPORTED_VIDEO_FILE = "src/test/resources/file_example_WMV_480_1_2MB.wmv";
#Test
void testSupportedVideoFilePlaysSuccessfully() {
assertDoesNotThrow(() -> PlayVideoSnippet.playVideo(PATH_OF_SUPPORTED_VIDEO_FILE));
}
#Test
void testUnsupportedVideoFileThrowsError() {
RuntimeException exception = assertThrows(RuntimeException.class, () -> PlayVideoSnippet.playVideo(PATH_OF_UNSUPPORTED_VIDEO_FILE));
assertTrue(exception.getCause().getClass().equals(MediaException.class));
}
}
I was able to fix the issue with help of below inputs:
Using TestFX for testing purpose as suggested by #jewelsea.
Inputs from #James_D
StackOver flow issue
ApplicationTest.launch() method internally takes care of setting up primary stage and cleaning before each test.
Solution:
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
class VideoTest extends ApplicationTest {
final String pathOfSupportedFile = "video.mp4";
final String pathOfUnsupportedFile = "video.wmv";
#Test
void testSupportedVideoFilePlaysSuccessfully() throws Exception {
assertDoesNotThrow(() -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
new String[]{pathOfSupportedFile}));
}
#Test
void testUnsupportedVideoFileThrowsError() throws Exception {
RuntimeException exception = assertThrows(RuntimeException.class,
() -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
new String[]{pathOfUnsupportedFile}));
assertTrue(exception.getCause().getCause().getClass().equals(MediaException.class));
}
}
I have an issue with JavaFX and multithreading. Basically I have an application and the task at hand asks me that I should have multiple users. Like for example I have a bug-testing application which shows a list of bugs and users and testers can choose to add/delete bugs from this list(a tableview in my case). Building the application was not a problem, but I don't understand how to 'simulate' multiple users. The task says that when I run my program, 3 windows should appear(2 for users and 1 for a tester), and when I add/delete a bug, the tableview should get updated.
I believe I need to do this with threads, as my last course involved multithreading, but I'm at a loss here. My main class looks like this:
import controller.OfertaCtrl;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import repository.OfertaRepo;
import view.OfertaFXML;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main extends Application {
private static Stage primaryStage;
private static Scene MyPage;
#Override
public void start(Stage primaryStage) throws Exception{
//Platform.setImplicitExit(false);
Main.primaryStage = primaryStage;
setPage();
}
public void setPage() throws IOException {
primaryStage.setTitle("Oferte");
FXMLLoader loader = new FXMLLoader(getClass().getResource("oferta.fxml"));
Pane pane = loader.load();
pane.setId("pane");
MyPage = new Scene(pane);
OfertaRepo repo = new OfertaRepo("C:\\Users\\Mihai\\workspace\\lalal\\newGUI\\src\\oferte.txt");
OfertaCtrl ctrl = new OfertaCtrl(repo);
OfertaFXML ctrl2 = loader.getController();
ctrl2.loadData(ctrl);
primaryStage.setScene(MyPage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
So basically I take a list of 'offers' in this example from a .txt file and put them in an ObservableArrayList with which I work with in my Controller class. The problem lies in the fact that I don't understand how I need to run multiple threads of the same application. Also, how would I update my tableview for all windows when I modify it in an open window? I was thinking of doing light pooling on my ObservableArrayList and checking for alterations every 1 second or so.
I can provide more information or whatever is needed, I just need a few points on how to go about solving this problem.
Here's how the application looks right now:
I found a way to open a link on default browser using HostServices.
getHostServices().showDocument("http://www.google.com");
Is there any way to open a media in default media player?
Is there any way to launch a specific File or Application?
Generally speaking, you can use Desktop#open(file) to open a file natively as next:
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.OPEN)) {
desktop.open(file);
} else {
throw new UnsupportedOperationException("Open action not supported");
}
Launches the associated application to open the file. If the specified
file is a directory, the file manager of the current platform is
launched to open it.
More specifically, in case of a browser you can use directly Desktop#browse(uri), as next:
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
desktop.browse(uri);
} else {
throw new UnsupportedOperationException("Browse action not supported");
}
Launches the default browser to display a URI. If the default browser
is not able to handle the specified URI, the application registered
for handling URIs of the specified type is invoked. The application is
determined from the protocol and path of the URI, as defined by the
URI class. If the calling thread does not have the necessary
permissions, and this is invoked from within an applet,
AppletContext.showDocument() is used. Similarly, if the calling does
not have the necessary permissions, and this is invoked from within a
Java Web Started application, BasicService.showDocument() is used.
If you want to either open a URL which has an http: scheme in the browser, or open a file using the default application for that file type, the HostServices.showDocument(...) method you referenced provides a "pure JavaFX" way to do this. Note that you can't use this (as far as I can tell) to download a file from a web server and open it with the default application.
To open a file with the default application, you must convert the file to the string representation of the file: URL. Here is a simple example:
import java.io.File;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class OpenResourceNatively extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField("http://stackoverflow.com/questions/39898704");
Button openURLButton = new Button("Open URL");
EventHandler<ActionEvent> handler = e -> open(textField.getText());
textField.setOnAction(handler);
openURLButton.setOnAction(handler);
FileChooser fileChooser = new FileChooser();
Button openFileButton = new Button("Open File...");
openFileButton.setOnAction(e -> {
File file = fileChooser.showOpenDialog(primaryStage);
if (file != null) {
open(file.toURI().toString());
}
});
VBox root = new VBox(5,
new HBox(new Label("URL:"), textField, openURLButton),
new HBox(openFileButton)
);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private void open(String resource) {
getHostServices().showDocument(resource);
}
public static void main(String[] args) {
launch(args);
}
}
Only the solution with java.awt.Desktop worked for me to open a file from JavaFX.
However, at first, my application got stuck and I had to figure out that it is necessary to call Desktop#open(File file) from a new thread. Calling the method from the current thread or the JavaFX application thread Platform#runLater(Runnable runnable) resulted in the application to hang indefinitely without an exception being thrown.
This is a small sample JavaFX application with the working file open solution:
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileOpenDemo extends Application {
#Override
public void start(Stage primaryStage) {
final Button button = new Button("Open file");
button.setOnAction(event -> {
final FileChooser fileChooser = new FileChooser();
final File file = fileChooser.showOpenDialog(primaryStage.getOwner());
if (file == null)
return;
System.out.println("File selected: " + file.getName());
if (!Desktop.isDesktopSupported()) {
System.out.println("Desktop not supported");
return;
}
if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
System.out.println("File opening not supported");
return;
}
final Task<Void> task = new Task<Void>() {
#Override
public Void call() throws Exception {
try {
Desktop.getDesktop().open(file);
} catch (IOException e) {
System.err.println(e.toString());
}
return null;
}
};
final Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The other proposed solution with javafx.application.HostServices did not work at all. I am using OpenJFX 8u141 on Ubuntu 17.10 amd64 and I got the following exception when invoking HostServices#showDocument(String uri):
java.lang.ClassNotFoundException: com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory
Obviously, JavaFX HostServices is not yet properly implemented on all platforms. On this topic see also: https://github.com/Qabel/qabel-desktop/issues/420
I am using JAVA FXML GUI to parse a text file. The user can select which file to parse and then press "load". When the user clicks on "load" the file gets parse and many lines gets added to an ArrayList. The user then search and manipulate the text that was parse that is store in the ArrayList.
Sometimes while loading/writing the file to the ArrayList or manipulating some lines, the GUI is not responsive. How can I separate the GUI process vs. the ArrayList handling in order for the GUI to always be accessible to the user ?
The code below launches my application:
package javafxapp;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Javafxapp 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();
FXMLDocumentController controller = new FXMLDocumentController();
controller.openingSound();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
This is a textbook case for the use of multithreading.
See this JavaFX documentation for information and tutorials on how to begin using it.