【问题标题】:Java - JProgressBar won't change value, and JLabel won't change textJava - JProgressBar 不会改变值,而 JLabel 不会改变文本
【发布时间】:2021-03-19 02:19:03
【问题描述】:

我正在用 Java 编写一个程序,我想添加一个加载页面,其中显示一个进度条和一个标签,说明正在加载什么,该栏显示完成的距离,我已经完成了所有设置,所以它应该工作,但它没有,我不知道出了什么问题(我是 java 新手,所以请怜悯)

我尝试使用默认设置为 false 的布尔值,并且仅在执行“after-all-set-code”后才设置为 true(我使用 netbeans 创建 GUI)并且当我调用更新文本/进度条的函数,如果布尔值仍设置为 false,它将等待一秒钟并重试,直到“all-set-code”将其更改为 true,但这似乎不起作用。

这是在我的main 类中

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...");

    }

}

这是我在loadingPage 中的setLoading() 类:

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

这是我的setLoadingValue() 函数:

    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);
            
    }

这是我的setLoadingText() 函数:

    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);
        
    }

而我的 after-all-set-codeloadingTextLoaded = trueloadingBarLoaded = true 取决于完成的内容

它应该更新进度条的文本和值,但它不是,它正在将Settings loading text to "..." 输出到控制台并将Setting loading value to ...% 输出到控制台,但不会更改实际值或组件的文本。

我做错了什么?

简约问题:(主文件)


// 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

这就是 loadingBarloadingText 变量并声明的样子

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

loadingBarLoaded & loadingTextLoaded 是这样声明的

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

loadingTextLoaded & loadingBarLoaded 并在运行all-set-code 后将所有生成的代码放入窗口内后更改为true(我使用的是NetBeans GUI builder,因此生成了代码)

在 loadingPage.java 里面是这样布局的。

主窗口有一个面板覆盖整个主窗口,里面有三个东西,顶部的标签位于中间,应用程序名称为“Xtra”,下方为@987654348 @subtitle 这么小,表示当前正在加载的内容,下方是进度条loadingBar

Here is a screen shot of the layout

对不起,如果我没有遵循不成文的编码规则,我一周前才开始使用java。

【问题讨论】:

  • 你调试了吗?你在哪里设置断点?这些断点处的值是多少?或者可能是您期望的 smb。会为你调试吗?
  • 每次点赞后我都会向控制台输出一些东西,一切似乎都正常。我会再做一次,看看我是否错过了什么,但它似乎工作得很好
  • 使用 Swing worker 在后台进行计算,否则你的 UI 将冻结。
  • 您应该发布minimal reproducible example。我们不知道您的 gui 中有哪些项目,您的字段是如何定义的,它们是静态的、易失的等,或者 loadingBarLoaded 的真正作用。在不相关的注释中,您违反了编码约定。类和接口名称应始终以大写字母开头,变量名不应。
  • 我想你没有理解minimal reproducible example的概念。基本上,我们可以将它复制并粘贴到我们的 IDE,运行它,并获得与您获得的相同结果。然后我们可以更好地理解它的工作方式。这意味着框架的定义,向其中添加元素,显示它,完整的类 - 但没有像您的 Xtra 实际所做的那样不相关的项目。对只使用 Java 一周的人来说,这可能有很多问题,但目前除了猜测之外别无他法。

标签: java swing jprogressbar


【解决方案1】:

了解摆动中的穿线。您必须使用 SwingWorker 并在 doInBackground() 方法中进行加载并在那里返回进度。

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));
        }
    }
}

重要的是,您不能从 doInBackground() 方法访问任何 Swing 组件,因为该方法不是从 Swing 事件调度线程调用的。

【讨论】:

  • 你应该添加一个小例子,否则这应该是一个评论。
【解决方案2】:

我修复了它,当 GUI 构建器创建它使用此代码的页面时

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

我改成:

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

在文件的开头我放了这个: public static loadingPage LP = new loadingPage();

它似乎奏效了。

【讨论】:

  • 你真的看到进步了吗?我建议您使用 SwingWorker 方法。
  • 没有。我不太关心动画它只是改变价值
  • 好的,如果看不到进度,使用 ProgressBar 有什么意义?
  • 你看到了进度,它上升并完成它,它只是没有平滑地动画到下一个点,它只是跳转到它
猜你喜欢
  • 2013-03-27
  • 2011-01-30
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
相关资源
最近更新 更多