-1

I am trying to use a splash screen with my program and the splash screen shows but then nothing else happens. I am running the JAR file, that has the main class that creates an object(LoadingScreen) which creates a splash screen, through a bat file which goes through a jre and starts the splash screen with my gif. Batch file contents:

cd Desktop

cd YES (folder this stuff is in)

jre\bin\java.exe -splash:ahsSplash.gif YES.jar*

Here is the LoadingScreen class with the splash screen creator

import java.awt.*;
 
public class LoadingScreen 
{
    public LoadingScreen() throws NullPointerException, IllegalStateException, InterruptedException
    {
        final SplashScreen splash = SplashScreen.getSplashScreen();
        Graphics2D g = splash.createGraphics();
        for(int i=0; i<150; i++) 
        {
            renderSplashFrame(g, i);
            splash.update();
            Thread.sleep(50);
        }
        splash.close();
    }
    static void renderSplashFrame(Graphics2D g, int frame) 
    {
        final String[] comps = {"Getting bork.exe", "Training doggie", "Finding woof", "Loading treats", "Locating poopbag", "Sniffing Cats","Locating DogPride", "Locating AHSPride", "Deleting Bite.virus ;]", "Smelling food", "Stealing food", "Walking outside"};
        g.setComposite(AlphaComposite.Clear);
        g.fillRect(100,135,200,40);
        g.setPaintMode();
        g.setColor(Color.WHITE);
        g.drawString(comps[(frame/8)%comps.length]+"...", 100, 145);
    }
}

Here is the main method

public static void main(String[] args) throws NullPointerException, IllegalStateException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, GeneralSecurityException, BadLocationException, InterruptedException, UnsupportedLookAndFeelException, UnsupportedAudioFileException, LineUnavailableException
  {
    System.out.println(System.getProperty("java.security.properties"));//null
    new LoadingScreen();
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run() 
      {
        try 
        {
          createValues();
        } 
        catch (Exception e)
        {
          ifError(e.toString());
        }
        LoginScreen lS = new LoginScreen();
        while(!lS.getUserAuth())
        {
          continue;
        }
        lS.setVisible(false);
        userLoginData userData = lS.uD;
        if(userData.getAdmin() == false)
        {
          try 
          {
            new StudentScreen(userData.user, userData.grade);
          } 
          catch (Exception e)
          {
            ifError(e.toString());
          }
        }
        else
        {
          try 
          {
            new AdminScreen();
          } 
          catch (Exception e)
          {
            ifError(e.toString());
          }
        }
      }
    });
  }

I tried many things from different arguments in the batch file, running the other methods in the loadingscreen class after the splash screen gets closed, using a manifest file to create the jar, creating the jar through multiple IDEs and I tried to make the other screens come first (because they had buttons that would call the rest of the code) and then the splash screen but I would get a security exception. I also tried to put all of the LoadingScreen class stuff inside my main method in the main class but even then it would stop after the splash screen.

THANKS FOR YOUR HELP!

Some exceptions I added to help diagnose the problem Exceptions

KP101Coder
  • 14
  • 5
  • 2
    while(!lS.getUserAuth()) seems like a bad idea – MadProgrammer Nov 12 '22 at 04:24
  • 1
    [mcve] .. and don't sleep the EDT, ever! – kleopatra Nov 12 '22 at 04:32
  • `"the splash screen shows but then nothing else happens"` Well, something is happening but your not informing us of what that is. Does the application simply end? Does it display nothing after the Splash closes an go into an endless loop which forces you to shut it down? Use your IDE debugger and step through the code to see what the issue is. – DevilsHnd - 退職した Nov 12 '22 at 04:35
  • @MadProgrammer Yeah that does seem pretty bad. Do you have any suggestions because I cant continue till I get a button press but anything inside the button becomes error prone. Also it still works and I doubt it has anything to do with the Splashscreen. – KP101Coder Nov 12 '22 at 04:36
  • @DevilsHnd Yes that is correct the application simply ends. If I dont use the bat file and do it directly in cmd, after the splash screen a new line shows on the cmd prompt to indicate termination of the program. Also everything else works if I comment out the LoadingScreen call. – KP101Coder Nov 12 '22 at 04:37
  • @user18646436 You need to approach the problem from a event driven principle, instead of a procedural one. This would suggest that once the login has been processed, you have some kind of controller or delegate to decide what should be done next – MadProgrammer Nov 12 '22 at 04:38
  • Oh well I better get researching then. Unfortunately, I am a beginner trying to speedrun programming so pardon my lack of vocabulary. – KP101Coder Nov 12 '22 at 06:00
  • no screenshots of plain text please – kleopatra Nov 13 '22 at 05:19

1 Answers1

1

Swing is an event driven environment, this means that, instead of using a loop to wait for state to change, the system will notify of "events" which you can the register interest for and respond to based on your needs.

This is a core concept to most GUI frameworks. You should probably have a look at Writing Event Listeners. Swing class these listeners, but they are also know as observers and reflect the "observer pattern"

So, what's the answer? Well simple really, once the splash screen has completed, you create a dialog and present the user login. Once the login has been processed (or cancelled), you notify interested parties via a custom observer and they then decide what needs to be done.

enter image description here

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.SplashScreen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class Main {

    public static void main(String args[]) {
        new Main();
    }

    public Main() {
        Splash test = new Splash();

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JDialog loginDialog = new JDialog();
                loginDialog.add(new LoginPane(new LoginPane.LoginDelegate() {
                    @Override
                    public void loginWasSuccessful(User user) {
                        loginDialog.dispose();
                        JFrame frame = new JFrame("Awesomeness");
                        frame.add(new ApplicationPane());
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    }

                    @Override
                    public void loginWasCancelled() {
                        loginDialog.dispose();
                    }
                }));
                loginDialog.setModal(true);
                loginDialog.pack();
                loginDialog.setLocationRelativeTo(null);
                loginDialog.setVisible(true);

            }
        });
    }

    public class Splash {

        private BufferedImage background;
        private SplashScreen splash;

        protected Graphics2D getGraphics() {
            Graphics2D g = splash.createGraphics();
            if (g == null) {
                throw new RuntimeException("Not not create splash screen graphics");
            }
            return g;
        }

        protected void renderBackground() {
            // Get the splash screen size...
            Dimension size = splash.getSize();
            int width = size.width;
            int height = size.height;

            Graphics2D g2d = (Graphics2D) getGraphics().create();

            // Draw the background
            g2d.drawImage(background, 0, 0, null);
            // Apply alpha composite
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
            g2d.dispose();
        }

        protected void renderProgress(double progress) {
            int height = splash.getSize().height - 1;
            int width = splash.getSize().width - 1;

            Graphics2D g2d = (Graphics2D) getGraphics().create();

            g2d.setColor(Color.RED);
            int y = height - 50;
            g2d.fillRect(0, y, (int) (width * progress), 50);

            g2d.setColor(Color.WHITE);
            g2d.drawRect(0, height - 50, width, 50);

            FontMetrics fm = g2d.getFontMetrics();
            String text = "Awesomeness is loading..." + NumberFormat.getPercentInstance().format(progress);
            g2d.setColor(Color.WHITE);
            g2d.drawString(text, (width - fm.stringWidth(text)) / 2, y + ((50 - fm.getHeight()) / 2) + fm.getAscent());
            g2d.dispose();
        }

        protected void renderSplashScreen(double progress) {
            // I'm cheating here, by constently repainting the background
            // I'm automatically cleaning what ever was previously painted
            renderBackground();
            renderProgress(progress);
            splash.update();
        }

        public Splash() {
            splash = SplashScreen.getSplashScreen();
            if (splash == null) {
                throw new RuntimeException("Not not get reference to splash screen");
            }

            System.out.println("Present");
            try {
                background = ImageIO.read(splash.getImageURL());
                for (double progress = 0; progress < 1.0; progress += 0.05) {
                    renderSplashScreen(progress);
                    Thread.sleep(250);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            } catch (InterruptedException ex) {
            }
            System.out.println("All done here");
            splash.close();
        }
    }

    public interface User {
        public String getName();
    }

    public class DefaultUser implements User {
        private String name;

        public DefaultUser(String name) {
            this.name = name;
        }

        @Override
        public String getName() {
            return name;
        }
    }

    public class LoginPane extends JPanel {

        public interface LoginDelegate {
            public void loginWasSuccessful(User user);

            public void loginWasCancelled();
        }

        // You don't need this, I'm just faking some stuff
        private Random rnd = new Random();
        private LoginDelegate delegate;

        public LoginPane(LoginDelegate delegate) {
            setBorder(new EmptyBorder(8, 8, 8, 8));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(new JLabel("This is where you'd present some fields for user credentials"), gbc);
            add(new JLabel("But I'm lazy so you'll have to fill it in yourself"), gbc);

            JButton loginBtn = new JButton("Login");
            JButton cancelBtn = new JButton("Cancel");

            JPanel actions = new JPanel(new GridLayout(1, 2, 4, 0));
            actions.add(loginBtn);
            actions.add(cancelBtn);

            add(actions);

            loginBtn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (rnd.nextBoolean()) {
                        delegate.loginWasSuccessful(new DefaultUser("Bob"));
                    } else {
                        JOptionPane.showMessageDialog(LoginPane.this, "Login failed", "Error", JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
            cancelBtn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    delegate.loginWasCancelled();
                }
            });
        }
    }

    public class ApplicationPane extends JPanel {
        public ApplicationPane() {
            setBorder(new EmptyBorder(8, 8, 8, 8));
            setLayout(new GridBagLayout());
            add(new JLabel("All your application is belong to us"));
        }
    }
}

You may also want to look into the model view controller concept

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you very much, I really appreciate the work you did to show me such a cool concept, however, I am not sure if this solves my problem. I really just want to show the new JFrames after the splashscreen which seems to terminate the program on completion. – KP101Coder Nov 12 '22 at 05:57
  • Also I did not need all of the classes for user stuff those were from my other classes I already made. Love the creative elements thought :) – KP101Coder Nov 12 '22 at 06:33
  • Right - so this, rather simple example will do exactly as you asked - but - you’ll need to modify how you’re approaching the problem – MadProgrammer Nov 12 '22 at 06:46
  • AH perfect you are still here! I was experimenting with your code and the invoke later seemed to help a lot. Now the problem is some ExceptionInitializationError and some java.lang.securityException. I will add a picture of the cmd output to my original problem – KP101Coder Nov 12 '22 at 06:53
  • Its pretty late where I am at so I will be afk for some time. I really appreciate your time and would love to fix this issue. – KP101Coder Nov 12 '22 at 06:57
  • `Google.emptyTrash`? That's another issue all together – MadProgrammer Nov 12 '22 at 08:40
  • Its a method that empty my drive trash. – KP101Coder Nov 12 '22 at 14:09
  • Well - that's the cause of your issues - this isn't a standard Java API and you'll need to make the time to figure out how to fix it – MadProgrammer Nov 12 '22 at 21:50
  • Yeah you were right. It is the drive method which is super weird because it works when I run it in vscode but not from the jar file. Do you know what could cause that? – KP101Coder Nov 13 '22 at 06:31
  • Oo, I did a bunch of searching and it has to do with my java security parameters. I tried doing what (https://stackoverflow.com/questions/58182231/openjdk-11-error-can-not-initialize-cryptographic-mechanism) said but i couldn't get it to work. I wasn't even sure what file they were even talking about to be honest. – KP101Coder Nov 13 '22 at 07:09
  • OMG I found out that I didn't even have the config folder because the tutorials I was watching didn't need to use it because they never ran network code. Im sorry for wasting your time lololol I just needed to copy the config file into my jre folder – KP101Coder Nov 13 '22 at 19:23