Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some ambiguity with vmargs in config.jason #65

Closed
maheshkurmi opened this issue Jun 26, 2016 · 4 comments
Closed

Some ambiguity with vmargs in config.jason #65

maheshkurmi opened this issue Jun 26, 2016 · 4 comments

Comments

@maheshkurmi
Copy link

maheshkurmi commented Jun 26, 2016

I am having problem with showing splash screen using exe generated with packr. I tried changing config.jason to include vmargs, but no luck.
This is my Folder Structure

G:/packr/out_windows
---jre
---simphy.jar
---jogamp-fat.jar
---commons-net-3.4.jar
---splash.png
---simphy.exe
---config.jason

Application shows splash screen, when I run through command prompt with this command
javaw -Xmx1G -splash:splash.png -classpath simphy.jar;jogamp-fat.jar;commons-net-3.4.jar org.shikhar.simphy.Sandbox

but when application is invoked through packr generated exe, no splashscreen is shown(although application runs properly). This is my config.jason

{
  "classPath": [
    "Simphy.jar",
    "jogamp-fat.jar",
    "commons-net-3.4.jar"
  ],
  "mainClass": "org.shikhar.simphy.Sandbox", 
  "vmArgs": [
    "splash:splash.png",
    "Xmx1G"
    ]
}


The content of simphy.jar(which contains main class) is as shown

simphy.jar
---META-INF
---org
---splash.png

and this is content of META-INF in simphy.jar

Manifest-Version: 1.0
Main-Class: org.shikhar.simphy.Sandbox
@code-disaster
Copy link
Member

It appears that the -splash VM argument is processed and filtered by the java executable, and not forwarded to / ignored by libjvm. WinRun4J for example implements its own solution, which isn't cross-platform.

@maheshkurmi
Copy link
Author

Thanks for rply.. that means it is not possible to use splashscreen with packr.

@code-disaster
Copy link
Member

No. Not per VM option. And I believe it would be a major pain to add custom support, like WinRun4J does, which works well on all platforms.

I don't know your requirements. If you really need a splash screen of some kind, it may be feasible to do one in Java instead. Loading and starting the JVM doesn't need much time on desktop systems.

@maheshkurmi
Copy link
Author

Once again thanks for your suggestion, I implemented splash screen in java itself. Actually my application takes a while in starting up, thats why splash screen was badly needed. This is what I did..

package org.shikhar.simphy;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;

import javax.swing.JFrame;

/**
 * Derived from
 * https://www.randelshofer.ch/oop/javasplash/javasplash.html#secondsplash
 * 
 * @author Mahesh kurmi
 *
 */
public class SplashWindow extends JFrame {
    private static SplashWindow instance;
    private Image image;
    private boolean paintCalled = false;
    private String msg = "";

    /**
     * The main method does three things: 
     * 1. Open the splash window 
     * 2. Invoke the main method of class Sandbox (Main app class)
     * 3. Close the splash window when the main method of Sandbox returns
     * @param args
     */
    public static void main(String[] args) {
        SplashWindow.splash();
        SplashWindow.invokeMain("org.shikhar.simphy.Sandbox", args);
        SplashWindow.disposeSplash();
    }

    public static void splash() {
        /*
         * In the first splash() method we use the AWT Toolkit class to create
         * the image. We use this method instead of the new Image IO API,
         * because it does not immediately load the image using the current
         * thread.
         */
        splash(Toolkit.getDefaultToolkit().createImage(
                SplashWindow.class
                        .getResource("/org/shikhar/simphy/images/splash.png")));
        // ImageUtilities.getIconFromClassPathSuppressExceptions("/org/shikhar/simphy/images/splash.png").getImage());
    }

    private SplashWindow(Image image) {
        super();
        this.image = image;

        MediaTracker mt = new MediaTracker(this);
        mt.addImage(image, 0);
        try {
            mt.waitForID(0);
        } catch (InterruptedException ie) {
        }
    }

    /**
     * Here we invoke the main() method of our application using, er, clumsy Reflection code.
     * @param className
     * @param args
     */
    private static void invokeMain(String className, String[] args) {
        try {
            Class.forName(className)
                    .getMethod("main", new Class[] { String[].class })
                    .invoke(null, new Object[] { args });
        } catch (Exception e) {
            InternalError error =

            new InternalError("Failed to invoke main method");
            error.initCause(e);
            throw error;
        }
    }

    private static void splash(Image image) {
        /*
         * an instance of the SplashWindow is created then, the instance is shown. And then,
         * we wait in a synchronized block until the paint method of the
         * instance has been called.
         */
        if (instance == null && image != null) {
            instance = new SplashWindow(image);
            instance.setSize(816, 251);
            instance.setUndecorated(true);
            instance.setLocationRelativeTo(null);
            instance.setVisible(true);
            if (!EventQueue.isDispatchThread()
                    && Runtime.getRuntime().availableProcessors() == 1) {

                synchronized (instance) {
                    while (!instance.paintCalled) {
                        try {

                            instance.wait();

                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        }
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

    @Override
    public void paint(Graphics g) {
        if (image == null) {
            System.out.println("image is null");
            return;
        }

        if (g == null) {
            System.out.println("g is null");
            return;
        }

        Graphics2D g2D = (Graphics2D) g;
        g2D.drawImage(image, 0, 0, this);
        g2D.setColor(new Color(239, 127, 34));
        g2D.fillRect(543, 34, 800, 30);
        g2D.setColor(new Color(255, 255, 255));
        g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        g2D.drawString(msg + "...", 543, 52);

        if (!paintCalled) {
            paintCalled = true;
            synchronized (this) {
                notifyAll();
            }
        }
    }

     /**Called from Sandbox class to set progress */
    public static void setProgress(String msg, int percentage) {
        if (instance == null)
            return;
        instance.msg = msg;
        instance.repaint();
    }

    /**
     * free resources if any
     */
    public static void disposeSplash() {
        if (instance == null)
            return;
        instance.setVisible(false);
        instance.image.flush();
        instance.image = null;
        instance.dispose();
        instance = null;
    }

}

For now it does the job, but I am not much comfortable with JVM loading mechanism so there may be few problems with the implementation. Kindly reply if there is any improvement needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants