0

I am trying to create a custom loading screen for a Java WAVPlayer app. The initial JFrame holds a custom JPanel that displays a circular loading bar. The bar's progress is controlled and updated within its own thread LoadThread. At the end of this thread, I want the current JFrame to close.

I know that I can't just use this.dispose() within the LoadThread. I have tried using an instance boolean variable that would control when the JFrame should be disposed--this was an obvious fail. I have tried using multiple threads to control different processes, but that quickly became too convoluted (and didn't yield my desired results). I read up on Java's SplashScreen class, and that may be the easiest path to take. I've been working at this for a few days now, and I really just want to figure out if what I'm trying to accomplish is feasible/necessary.

Below : Custom Panel class LoadPanel, JFrame form LoadingFrame, Main class WAVPlayer

public class LoadPanel extends JPanel{

int progress=0;

public void UpdateProgress(int progressVal){
    this.progress=progressVal;
}

@Override
public void paint(Graphics g){
    super.paint(g);
    Graphics2D g2=(Graphics2D)g;

    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON); // cleans gfx lines
    g2.translate(this.getWidth()/2,this.getHeight()/2);
    g2.rotate(Math.toRadians(270));
    Arc2D.Float arc=new Arc2D.Float(Arc2D.PIE);
    Ellipse2D circle=new Ellipse2D.Float(0,0,110,110);
    arc.setFrameFromCenter(new Point(0,0),new Point(120,120));
    circle.setFrameFromCenter(new Point(0,0),new Point(110,110));
    arc.setAngleStart(1);
    arc.setAngleExtent(-progress*3.6); // 360/100=3.6

    g2.setColor(Color.BLUE); // creating progress circles
    g2.draw(arc);
    g2.fill(arc);
    g2.setColor(Color.BLACK);
    g2.draw(circle);
    g2.fill(circle);
}
}


public class LoadingFrame extends javax.swing.JFrame {

private Thread LoadThread;

public LoadingFrame() {
    setUndecorated(true);
    setBackground(new Color(0,0,0,0));
    initComponents();
    Application.getApplication().setDockIconImage(new ImageIcon(getClass()
            .getResource("/waveicons/WAVE_ICON32.png")).getImage());
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    testButton = new javax.swing.JButton();
    jp_progress = new wavplayer.LoadPanel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    testButton.setText("testButton");
    testButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            testButtonActionPerformed(evt);
        }
    });

    jp_progress.setBackground(new Color(0,0,0,0));

    javax.swing.GroupLayout jp_progressLayout = new javax.swing.GroupLayout(jp_progress);
    jp_progress.setLayout(jp_progressLayout);
    jp_progressLayout.setHorizontalGroup(
        jp_progressLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 300, Short.MAX_VALUE)
    );
    jp_progressLayout.setVerticalGroup(
        jp_progressLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 0, Short.MAX_VALUE)
    );

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jp_progress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(testButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(133, 133, 133)
            .addComponent(testButton)
            .addContainerGap(138, Short.MAX_VALUE))
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jp_progress, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addContainerGap())
    );

    pack();
}// </editor-fold>                        

private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    testButton.setEnabled(false);

    LoadThread=new Thread(new Runnable(){
        @Override
        public void run(){
            for (int num = 1; num <= 100; num++) {
                jp_progress.UpdateProgress(num);
                jp_progress.repaint();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    Logger.getLogger(LoadingFrame.class.getName())
                            .log(Level.SEVERE, null, ex);
                }
            }
            testButton.setEnabled(true);
        }
    });
    LoadThread.start();


}                                          

// Variables declaration - do not modify                     
private wavplayer.LoadPanel jp_progress;
private javax.swing.JButton testButton;
// End of variables declaration                   
}


public class WAVPlayer {

public static void main(String[] args) {
    LoadingFrame frame=new LoadingFrame();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.pack();
    System.out.println("Im here at the end of main");
}
}
  • 1. Use a JDialog not a JFrame. 2) Your code disobeys Swing threading rules as you're changing gui state within the background thread. 3) Don't even use a thread if all you need is a delay. Use a Swing Timer instead – Hovercraft Full Of Eels Sep 22 '18 at 00:16
  • @Hovercraft Full of Eels - What is the benefit of using a JDialog instead of a JFrame in this instance? – jagged_prospect Sep 22 '18 at 00:32
  • It's not the main application window and so shouldn't be a JFrame for theoretical reasons, and also there's no risk of closing the entire application when you close or dispose of the dialogue. Also it can be made modal if need be, something you can't do with a JFrame – Hovercraft Full Of Eels Sep 22 '18 at 00:37
  • @HovercraftFullOfEels - I understand what you mean now. The option to control modality could also be useful. Since the SplashScreen class requires an instance of a JFrame to be present, it would also be unnecessary for the same "theoretical reasons" to implement that, right? Or perhaps I'm missing the point of the SplashScreen class. – jagged_prospect Sep 22 '18 at 14:13

0 Answers0