Animated Splash Screen on Netbeans Platform app - java

Our maven/Netbeans platform application uses a custom image on startup, by replacing
Nbm-branding > core.jar > org.netbeans.core.startup > splash.gif
I tried making it an animated .gif, but only the first frame is displayed.
How would one possibly go about implementing an animated splash screen, maybe by running some JavaFX window animations?
I've seen another other SO question, but it wasn't really answered - please notice I'm asking about how to integrate a custom splash screen with my Netbeans Platform application, and not how to actually build it.

Surprisingly enough, I found out how to plug in a custom splash screen based on this post about user authentication and authorization.
Basically, one needs to write another start-up class, instead of the platform's default:
import java.lang.reflect.Method;
public class CustomStartup {
private static final String NB_MAIN_CLASS = "org.netbeans.core.startup.Main";
public static void main(String[] args) throws Exception {
// do whatever you need here (e.g. show a custom login form)
System.out.println("Hello world! I am a custom startup class");
JWindow splash = initSplash();
// once you're done with that, hand control back to NetBeans
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
Class<?> mainClass = Class.forName(NB_MAIN_CLASS, true, classloader);
Object mainObject = mainClass.newInstance();
Method mainMethod = mainClass.getDeclaredMethod("main", new Class[]{String[].class});
mainMethod.invoke(mainObject, (Object) args);
splash.setVisible(false);
}
}
In that class, one can create a JavaFX stage, embed it into a JWindow, and show it:
public JWindow initSplash(){
JWindow window = new JWindow();
final JFXPanel fxPanel = new JFXPanel();
window.add(fxPanel);
window.setVisible(true);
window.setLocationRelativeTo(null);
Platform.runLater(new Runnable() {
#Override
public void run() {
Scene scene = new Scene(new CustomFxSplash(), 475, 300, true);
fxPanel.setScene(scene);
}
}
return window;
}
Other things to remember are:
Suppress the original NetBeans splash screen by running your app with the --nosplash parameter.
Call your custom initialization class by running your app with the -J-Dnetbeans.mainclass=com.package.splash.CustomStartup parameter
As the link suggests this custom class has to be on the platform's initialization classpath, meaning inside the platform/core folder.

The current version of the NetBeans class that is responsible for rendering the splash screen can be viewed online here: org.netbeans.core.startup.
The culprit code that prevents the gif from animating is this line (line 546)
graphics.drawImage(image, 0, 0, null);
In order for the gif to animate the ImageObserver will have to be specified instead of being set to null and then repaint must be called when imageUpdate() is called on the ImageObserver.
An example of displaying an animated gif can be viewed here: Relationship Between Animated Gif and Image Observer
So as far as I can see you will either have to change the above NetBeans platform code and rebuild it for your application or you will have to create your own splash screen from scratch to use instead of the NetBeans one.
Hope you find this useful!

Related

JavaFx/ Swing window does not open after update to Java 1.8u40

We have an javafx application developed mainly in java 1.7 and tested in 1.8. It was running fine until java 1.8u35. Now we discovered, JavaFx windows are not going to open in 1.8u40 after upgrade. Even worse, the modal windows are blocking the entire tab/ browser of being used. So the user is just able to close the browser using the task manager.
We use javafx.embed.swing.JFXPanel to embed jfx-code into swing legacy code.
I have completely no clue what might be the problem, as there are no errors displayed in client's java console.
UPDATE:
I reviewed the known issues list for java1.8 here. The only thing I would probably link to our issue is this bug:
BUG-RT-32597: The SwingNode class does not support High DPI displays.
So I tried lowering the screen resolution (1280x1024 to 800x600) but without success.
Does anyone faced a similar issue before and knows what might help?
UPDATE:
I tried to better track down the problem but with not much luck.
To make it more visible, this is basically whats going on on window loading:
public static void initWindow(JDialog dialog){
final JFXPanel jfx = new JFXPanel();
Platform.runLater(new Runnable() {
public void run() {
System.out.println("JFXPanel");
}
});
Runnable r = new Runnable() {
public void run() {
AnchorPane root = new AnchorPane;
//... do some content loading
Scene scene = new Scene(root,width,height);
System.out.println("test");
}
};
dialog.add(jfx);
System.out.println("added jfx panel.");
dialog.pack();
System.out.println("packed jfx panel.");
dialog.setLocationRelativeTo(null);
System.out.println("loaded.");
}
I thought execution is going to stop somewhere, but its running through the entire function as usual. Nevertheless the window is not showing up.
UPDATE:
Not completely correct, my last comment, as I found out:
Around the above function, the following happens:
initWindow(this); //this is extending java.swing.JDialog
System.out.println("this comment is printed to console");
super.setVisible(true); //this is not executed properly. if removed, browser will not be blocked, but window doesnt show up either
System.out.println("this comment is not printed to console";
So, in general, there is the JDialog which gets packed with a JfxPanel. When calling setVisible() method from the JDialog class, the Application gets blocked but the window doesnt show up. Actually, in the thumbnail screen (alt+tab) it is shown as a container inside the application.
When removing the setVisible call, the browser does not get blocked, but also the window does not show up. Unfortunately, I did not find the JDialog class code to look up, what's going on inside setVisible().
Any ideas, what might be wrong with our setup or the setVisible method?
We had a similar problem. While comparing the Java sources of 1.8.0_31 and 1.8.0_45 we found out that there were some changes in the JFXPanel source code introduced with 1.8.0_45 that may cause problems in the following situation:
initialize modal JDialog with JFXPanel (executed on Swing's EDT)
initialize and set FX scene on JFXPanel in FX task (executed on FX Thread)
wait for FX task to be finished (wait on EDT)
pack() and show() JDialog (continued on EDT, blocks program execution)
continue with program execution after user closed JDialog (on EDT)
We use this workflow in order to wait for some user input being shown in a new modal JDialog and continue normal programm execution on EDT afterwards.
In 1.8.0_31, the preferred size of JFXPanel seems to be set in FX thread which allows JDialog.pack() to determine the correct bounds.
In 1.8.0_45, the preferred size of JFXPanel seems to be set not in FX thread anymore but in EDT after all pending AWT events are executed. So, when (4) is executed, JDialog.pack() does not know about the preferred size of the scene. As a consequence, the dialog has no content, or does not show up if undecorated as described in the original question above.
Here is a complete example to reproduce the different behaviour:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// create JDialog on EDT
final JDialog dialog = new JDialog((JDialog)null, "JDialog");
// initialize FX platform and create JFXPanel
final JFXPanel jfxPanel = new JFXPanel();
// add resize listener for JFXPanel
jfxPanel.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// not called in 1.8.0_45
System.out.println("JFXPanel.getSize(): "+jfxPanel.getSize());
}
});
// set FX Scene on JFXPanel and wait until finished
runAndWait(new Runnable() {
public void run() {
Text text = TextBuilder.create().text("JavaFx content").y(20).build();
Group root = new Group(text);
Scene scene = new Scene(root);
jfxPanel.setScene(scene);
}
});
// show undecorated modal JDialog with FX content
System.out.println("JFXPanel.getPreferredSize(): "+jfxPanel.getPreferredSize());
dialog.setUndecorated(true);
dialog.add(jfxPanel);
dialog.pack();
dialog.setModal(true);
System.out.println("JDialog.setVisible()");
dialog.setVisible(true);
}
});
}
private static void runAndWait(Runnable r) {
try {
FutureTask<Object> task = new FutureTask<Object>(r, null);
Platform.runLater(task);
task.get();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
When running this program, componentResized() is called only in 1.8.0_31 but not in 1.8.0_45.
A possible fix while keeping the synchronous program workflow on EDT is to replace JDialog.pack() with JDialog.setSize(...), e. g. by setting a constant size or by using the size of the FX scene that could be determined using root.getBoundsInLocal().
I encountered the same behaviour described by #Peter using 1.8.0_121.
I was able to get dialog.pack() to work using a window listener.
dialog.addWindowListener( new WindowAdapter() {
#Override
public void windowOpened(WindowEvent e) {
((JDialog)e.getSource()).pack();
}
});

JAVAFX - Windows rights calling

I have two good working windows (main window, first window) in seperate .java files, at the same package.
The program handles, if I call the the First window (from the main), the Main stays in the background. The only problem is that I still can use the main window if I click there, and create infinity first windows.
One solution is to shut down the Main window, to avoid clicking there again, but I would like to keep there. In order to make the solution I need a code which makes the background window somehow disabled until I click something in the First Window.
But to do that I need to give the rights to the "handler.java" to operate with the main.
Anybody has any idea how to do that?
Let me show you the 2 java file's methods:
Main.java:
public class program extends Application {
#Override
public void start(Stage main) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("mainwindow.fxml"));
Scene scene = new Scene(root);
main.setScene(scene);
main.setTitle("Main);
main.setWidth(800);
main.setHeight(600);
main.setResizable(false);
main.show();
First.java
public void first() throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("first.fxml"));
Scene scene = new Scene(root);
Stage first = new Stage();
first.setScene (scene);
first.setTitle("Köszöntjük az Útiokosban!");
first.setWidth(400);
first.setHeight(200);
first.setResizable(false);
first.show();
}
Use Stage.initModality to make one of your Stages modal (blocking).
Note: You need to set the modality before displaying the Stage.
Try using the advisory in the chapter "Modality" in this link:
http://docs.oracle.com/javase/8/javafx/api/javafx/stage/Stage.html

How to control volume in vlcj?

I am creating a project for my college using vlcj. this is my code
public class MediaPlayerUI extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static EmbeddedMediaPlayer mediaPlayer;
public static FullScreenStrategy fullScreenStrategy;
public MediaPlayerUI(String title) {
super(title);
// finding native library of vlc player
new NativeDiscovery().discover();
//setting a layout
setLayout(new BorderLayout());
//setting up mediaplayer components
String[] libvlcArgs = {};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(libvlcArgs);
mediaPlayer = mediaPlayerFactory.newEmbeddedMediaPlayer(fullScreenStrategy);
//creating swing Components
Canvas canvas = new Canvas();
//setting up the video surface
CanvasVideoSurface videoSurface = mediaPlayerFactory.newVideoSurface(canvas);
mediaPlayer.setVideoSurface(videoSurface);
//adding swing components to contant pane
Container UIContainer = getContentPane();
UIContainer.add(canvas,BorderLayout.CENTER);
}
}
and this
package andromedia;
import javax.swing.JFrame;
import uk.co.caprica.vlcj.player.embedded.DefaultFullScreenStrategy;
public class MainPlayer {
public static void main(String args[])
{
JFrame mainFrame = new MediaPlayerUI("AndroMedia");
mainFrame.setVisible(true);
mainFrame.setSize(500,500);
mainFrame.setDefaultCloseOperation(3);
MediaPlayerUI.fullScreenStrategy = new DefaultFullScreenStrategy(mainFrame);
MediaPlayerUI.mediaPlayer.playMedia("E:\\Media\\flash.mp4","Volume=0");
MediaPlayerUI.mediaPlayer.setVolume(0);
System.out.println(MediaPlayerUI.mediaPlayer.getVolume());
}
}
I cant control the volume
when I print the current volume I get the value "-1"
and am getting the following runtime errors
-1
[000000000d670bd0] main vout display error: Failed to set on top
[000000000d670bd0] main vout display error: Failed to resize display
any help would be greatly appreciated
thank you .
Volume is a bit problematic with recent versions of VLC. In older versions of VLC there was not a problem.
In 2.1, it is simply not possible to set/get the volume before media playback has actually begun. As you have described, you get a value of "-1".
So you have to find some other way, like using a MediaPlayerEventListener and waiting for a media player "playing" event and even then you may need to wait for a little bit longer using e.g. by sleeping for 500ms or so before setting/getting the volume.
Clearly that's a pretty bad solution, but unfortunately that's just the way it is.
With VLC 2.2+, the situation is a little bit better. You can now set/get the volume before playback has actually begun, but if you stop the media player (pause is OK, but not stop) then you can no longer set/get the volume until you play media again.
There is a thread at the VLC forums here with the same conclusions:
https://forum.videolan.org/viewtopic.php?f=32&t=104345
So because of this issue in LibVLC, the same issue appears in vlcj with no perfectly satisfactory solution (at the moment).
In your code, you do this:
mediaPlayer.playMedia(...);
mediaPlayer.setVolume(0);
mediaPlayer.getVolume();
You need to be aware that playMedia actually starts media player asynchronously, so at the point that function returns, and you try to set the volume immediately after, the media is absolutely not guaranteed to have actually started yet and because of this issue you can't set/get the volume yet.
To summarise, there is no ideal solution available to this right now, and it will likely require a change to LibVLC unless you are prepared to live with sub-optimal workarounds.
By the way, those "main vout display error" messages are irrelevant.

Making a custom icon for a JFrame

Well I was wondering if I could make an icon image for a JFrame. I do know its posible, because, let me say, I am NOT digging the java logo.
Well if I just hava to use a Frame object I will.
Can someone tell me, I know its possible!
Use an ImageIcon.
ImageIcon icon = new ImageIcon( pathToIcon );
yourFrame.setIconImage(icon.getImage());
Good Luck!
First, you have to have an image file on your computer. It can be named anything. For this example, we will call this one "pic.jpg".
Next, you need to include it in the files that your application is using. For example, if you're using NetBeans, you simply click on "Files" in the left hand side of the IDE (not File as in the menu, mind you). Drag the picture's file over to the folder that houses the main package. This will include it for available use in the code.
Inside the method where you define the JFrame, you can create an image like this:
Image frameImage = new ImageIcon("pic.jpg").getImage();
You can now set it as the IconImage for the frame like this:
JFrame frame = new JFrame("Title");
frame.setIconImage(frameImage);
Hope that's helpful.
Note: the reason that the Image object has to be created like this is because Image is abstract and cannot be instantiated by saying new Image();
Props to you, btw, kid. I wish I would have started learning programming when I was your age. Keep at it!
You can do the following.
public Test {
public static void main(String[] args) {
JFrame frame = new JFrame("My Frame");
frame.setIconImage(new ImageIcon(Test.class.getResource("image.png"));
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setVisible(true);
frame.setSize(100, 100);
//other stuffs....
}
}

How does NetBeans' Splash Screen feature work?

New to NetBeans and just noticed that in the File >> Project Properties >> Application dialog there is a text field labeled Splash Screen that allows you to specify a path to an image that you would like displayed when your program is launching.
I want to customize the way my splash screen works (adding a progress bar, etc.) and would like to code it from the ground up but don't know where to start. What are the best practices for Java/Swing-based splash screens?
Thanks for any and all input!
The project properties -> Application -> Splash Screen allows you to add an image to an application. This property sets a value in the MANIFEST.MF called SplashScreen-Image: e.g. SplashScreen-Image: META-INF/GlassFish316x159.jpg This property will automatically cause the image to display as a splash screen. It does not work inside NetBeans, and must be run outside the IDE.
There is a tutorial Splash Screen Beginner Tutorial that details how to use it more detail. The tutorial was done for NetBeans 6.8, but will work on 7.2.1 which is the latest at the time of this post.
I'm not sure how NetBeans does it, but Splash Screens are supported by the JRE since version 6. See http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/splashscreen/
Splash screen is just a instance of java.awt.Window or undecorated javax.swing.JFrame.
To create window just say new Window(null), then set size and position (using tookit you can calculate where the screen center is) and then say window.setVisible(true)
Due to this is your own window you can do what you want: set layout, image, add process bar to the SOUTH etc.
You can also use JFrame: new JFrame().setUndecorated(true)`
There are a couple of ways to do this.
To do a simple splash screen (an image) you can specify this in the command line of you java application.
Here is a simple example
java -splash:<file name> <class name>
However, if you want a progress bar, you are going to have to do something a little more complicated, and write some code yourself. This is done in the following way.
Create a JWindow (or Window or undecorated JFrame) component with your splash screen elements
Set it to visible
Do the rest of your Swing GUI startup code
Set your JFrame to visible, then immediately follow with setting the JWindow to visible(false)
This should show the splash almost immediately, and then hide once the your application is fully loaded.
To see some splash screen code, take a look here. The implementation in the link only shows how to achieve what you can with the -splash command, but it will give you a good start to also include the progress bar that you requested.
I hope this helps you, it is a small example of how to create yourself a simple splash screen using a dummy Progress Bar:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class SplashScreen extends JWindow
{
private static JProgressBar progressBar = new JProgressBar();
private static SplashScreen execute;
private static int count;
private static Timer timer1;
public SplashScreen()
{
Container container = getContentPane();
container.setLayout(null);
JPanel panel = new JPanel();
panel.setBorder(new javax.swing.border.EtchedBorder());
panel.setBackground(new Color(255,255,255));
panel.setBounds(10,10,348,150);
panel.setLayout(null);
container.add(panel);
JLabel label = new JLabel("Hello World!");
label.setFont(new Font("Verdana",Font.BOLD,14));
label.setBounds(85,25,280,30);
panel.add(label);
progressBar.setMaximum(50);
progressBar.setBounds(55, 180, 250, 15);
container.add(progressBar);
loadProgressBar();
setSize(370,215);
setLocationRelativeTo(null);
setVisible(true);
}
public void loadProgressBar()
{
ActionListener al = new ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
count++;
progressBar.setValue(count);
if (count == 50){
timer1.stop();
execute.setVisible(false);
//load the rest of your application
}
}};
timer1 = new Timer(50, al);
timer1.start();
}
public static void main (String args[]){
execute = new SplashScreen();
}
}
Cheers!
Also consider to build your application on top of the NetBeans Platform (a Swing-based RCP). One of the many benefits: it comes with a customizable splash screen with progress bar.
Sample progress bar:
http://platform.netbeans.org/tutorials/nbm-paintapp.html#wrappingUp
Port a Swing application to the NetBeans Platform:
http://platform.netbeans.org/tutorials/60/nbm-porting-basic.html
Further links:
http://netbeans.org/features/platform/index.html
http://netbeans.org/features/platform/all-docs.html
If your application is build using NetBeans Platform, then here's a tutorial about splash screen customisation: http://wiki.netbeans.org/Splash_Screen_Beginner_Tutorial
There is a sample Javafx equivalent of Splash screen. However this splash screen is basically a java swing applet that is called from javafx to be displayed to the user and simulates more or less eclipse and netbeans splash screen using progress bar and titles for the loaded contents. This is the link.
You must be able to get the code and separate out the splash screen code written in java swings and use it for yourself.
This is a custom java swings splash screen. and hence to center the splash screen it uses the traditional
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension labelSize = l.getPreferredSize();
setLocation(screenSize.width / 2 - (labelSize.width / 2),
screenSize.height / 2 - (labelSize.height / 2));

Categories

Resources