简体   繁体   中英

Java - JProgressBar won't change value, and JLabel won't change text

I am writing a program in Java and I want to add a loading page where it displays a progress bar and a label saying what is loading and the bar showing how far it is to completing, I have everything set up so it should work but it doesn't, I do not know what is wrong (I am new to java so please have mercy)

I have tried having a boolean that is set to false by default and is set to true only after "after-all-set-code" has been executed (I am using netbeans to create the GUI) and when I call the function to update the text/progress bar, if the boolean is still set to false it will wait a second and retry till the "all-set-code" changes it to true, but that doesn't seem to work.

This is inside my main class

public class Xtra {

     public static loadingPage LP = new loadingPage();

    public static void main(String[] args) {

        // Show loading page
        LP.main(args);
        
        // Set loading
        LP.setLoading(0, "Fetching Config...");
        
        // Get Config
        // Durring the "getConfig" function it calls the function "LP.setLoading()" multiple times to update the loading bar & text
        Xtra.getConfig();
        
        // Set loading
        LP.setLoading(0, "Loading user data...");

    }

}

This is my setLoading() class inside of loadingPage :

public void setLoading(int per, String txt) {
    
    if ("".equals(txt)) {
        
        setLoadingValue(per);
        
    } else {
        
        setLoadingText(txt);
        setLoadingValue(per);
        
    }
    
}

This is my setLoadingValue() function:

    public void setLoadingValue(int x) {
        
        // This will turn true when the after-all-set code runs
        while (!loadingBarLoaded) {
            
            // Try to wait a second,
            // Do this so it doesn't take up too much CPU
            try {
            
                // Wait a second
                TimeUnit.SECONDS.sleep(1);
                
                // Print to console
                System.out.println("Loading value not loaded,\nWaiting another second");
                
                // If there is an error waiting
            } catch (InterruptedException ex) {
                
                // Alert user
                System.out.println("You cannot sleep now, monsters are nearby");
                
            }
            
        }
        
        // After loaded boolean turns true
        
        // Alert user of change
        System.out.println("Setting loading value to " + x + "%");
        
        // Change value
        loadingBar.setValue(x);
            
    }

This is my setLoadingText() function:

    public void setLoadingText(String txt) {
        
        // This will turn true when the after-all-set code runs
        while (!loadingTextLoaded) {
            
            // Try to wait a second,
            // Do this so it doesn't take up too much CPU
            try {
            
                // Wait a second
                TimeUnit.SECONDS.sleep(1);
                
                // Print to console
                System.out.println("Loading text not loaded,\nWaiting another second");
                
                // If there is an error waiting
            } catch (InterruptedException ex) {
                
                // Alert user
                System.out.println("You cannot sleep now, monsters are nearby");
                
            }
            
        }
        
        // After loaded boolean turns true
        
        // Alert user of change
        System.out.println("Setting loading text to \"" + txt + "\"");
        
        // Change value
        loadingText.setText(txt);
        
    }

and my after-all-set-code is loadingTextLoaded = true & loadingBarLoaded = true depening on what is finished

It's supposed to update the text and the value of the progress bar but it isn't, it is outputting the Settings loading text to "..." to the console & the Setting loading value to ...% to the console as well, but not changing the actual value or text of the components.

What am I doing wrong?

Minimalistic problem: (Main file)


// Inside main function
// Show loading page
        LP.main(args);
        
        LP.loadingBar.setValue(50);
        LP.loadingText.setText("Hello");
    // nothing changes. (Both are public so I can call them from different files

This is what the loadingBar & loadingText vars and declared like

public javax.swing.JProgressBar loadingBar;
public javax.swing.JLabel loadingText;

loadingBarLoaded & loadingTextLoaded is declared like this

public boolean loadingTextLoaded = false;
public boolean loadingBarLoaded = false;

loadingTextLoaded & loadingBarLoaded and changed to true after all the generated code puts them into place inside the window after the all-set-code is ran (I am using NetBeans GUI builder so the code is generated)

Inside the loadingPage.java this is how it is laid out.

The main window and there is a panel covering the entire main window and it has three things inside of it, a label at the top that sits in the middle, it has the application name "Xtra" and below it the loadingText subtitle that small and says what is currently loading, below that, a progress bar loadingBar .

Here is a screen shot of the layout

Sorry if I am not following the unwritten coding rules, I only started with java like a week ago.

Learn about threading in swing. You have to use a SwingWorker and do the loading in the doInBackground() method and return progress there.

import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class Main {

    private JProgressBar prog;

    public static void main(String[] args) throws InvocationTargetException, InterruptedException {

        SwingUtilities.invokeAndWait(()-> new Main().initGUI());
    }

    private void initGUI(){
        JDialog dialog = new JDialog();
        dialog.setTitle("Progress");
        prog = new JProgressBar();
        prog.setMaximum(100);
        dialog.add(prog);
        dialog.pack();
        dialog.setVisible(true);
        BackgroundWorker bw =new BackgroundWorker();
        bw.execute();
    }

    private class BackgroundWorker extends SwingWorker<String, Integer>{
        @Override
        protected String doInBackground() throws Exception {
            try{Thread.sleep(1000);}catch(Exception e){}
            publish(10);
            try{Thread.sleep(1000);}catch(Exception e){}
            publish(20);
            try{Thread.sleep(1000);}catch(Exception e){}
            publish(30);
            try{Thread.sleep(1000);}catch(Exception e){}
            publish(70);
            try{Thread.sleep(1000);}catch(Exception e){}
            publish(100);
            return "finished";
        }

        @Override
        protected void process(List<Integer> chunks) {
            prog.setValue(chunks.get(chunks.size()-1));
        }
    }
}

Important is, that you don't access any Swing Component from the doInBackground() method, as this method is not called from the Swing Event Dispatch Thread.

I fixed it, when the GUI builder created the page it used this code

/* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new loadingPage().setVisible(true);
            }
        });

I changed it to:

/* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                LP.setVisible(true);
            }
        });

and at the begining of the file I put this: public static loadingPage LP = new loadingPage();

and it seemed to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM