【问题标题】:Can a JProgressBar be updated by simply incrementing setValue?可以通过简单地增加 setValue 来更新 JProgressBar 吗?
【发布时间】:2014-03-14 13:44:03
【问题描述】:

这是一个家庭作业,我要读入一个文件并将所有字符转换为大写或小写,具体取决于用户选择的内容。我已经完成了所有这些工作,但我不确定我的进度条是否随着每个字符的写入而更新,或者当文件写入完成时它是否会跳到 100%。我的逻辑是在写入每个字符后,我增加一个计数器,然后在该增量之后我progressBar.setValue(100 * (symbolsWritten / totalSymbols)); 这是我的代码的一部分,用于检查字符是否为小写,并在需要时将其转换为大写。我只是在学习,所以请不要把我的代码打得太糟糕:) 谢谢你的 cmets。

public void writeFileLC(char[] theCharArray)
{
    int totalSymbols = theCharArray.length;
    int symbolsWritten = 0;
    int symbolsConverted = 0;

    /*this loop checks to see if the character is upper case and converts
     it if needed. Then it writes the characters to the output file via
     the output object output*/
    for (int i = 0; i < theCharArray.length; i++)
    {
        if (Character.isUpperCase(theCharArray[i]))
        {
            try
            {
                output.format("%c", Character.toLowerCase(theCharArray[i]));
                symbolsConverted++;
                symbolsWritten++;
                Symbols_converted_textfield.setText(String.valueOf(symbolsConverted));
                ProgressBar.setValue(100 * (symbolsWritten / totalSymbols));
            }//end try block
            catch (FormatterClosedException formatterClosedException)
            {
                JOptionPane.showMessageDialog(this, "Error writing to file",
                        "Error writing to file", JOptionPane.ERROR_MESSAGE);

            }//end catch
        }//end if

        else
        {
            try
            {
                output.format("%c", theCharArray[i]);
                symbolsWritten++;
                Symbols_converted_textfield.setText(String.valueOf(symbolsConverted));
                ProgressBar.setValue(100 * (symbolsWritten / totalSymbols));
            }//end try block
            catch (FormatterClosedException formatterClosedException)
            {
                JOptionPane.showMessageDialog(this, "Error writing to file",
                        "Error writing to file", JOptionPane.ERROR_MESSAGE);

            }//end catch
        }//end else         
    }//end for
}//end method writeFileLC

【问题讨论】:

    标签: java swing jprogressbar


    【解决方案1】:

    这里发生了两件事。第一个是整数除法,因为symbolsWrittentotalSymbols 都是整数。所以你永远不会从int / int 得到小数值。它只会从 0 跳到 1。如果需要,您可以进行强制转换:

    bar.setValue((int)Math.round(
        100.0 * ((double)symbolsWritten / (double)totalSymbols)
    ));
    

    (或者将它们定义为 double 开头。如果值在 int 范围内,则可以在 double 上使用 ++。)

    另一个是更新值的方式,因为它应该在the Event Dispatch Thread 上完成。这取决于如何调用此方法。如果在事件中调用它,您需要启动background thread,否则在该过程完成之前不会显示更新。

    @Override
    public void actionPerformed(ActionEvent ae) { // some action event
        final String someString = "SoMe StRiNg"; // some String
    
        SwingWorker<Void, Void> task = new SwingWorker<Void, Void>() {
            @Override
            public Void doInBackground() {
                writeFileLC(someString.toCharArray());
                return (Void)null;
            }
            @Override
            public void done() {
                try {
                    get();
                } catch(Exception e) {
                    e.printStackTrace(System.err);
                }
            }
        };
    
        task.execute();
    }
    

    done 中的有趣业务很奇怪,但如果您想捕获在 doInBackground 中抛出的异常,这很重要。SwingWorker 会吃掉它们,但如果您调用 @987654333 @.)

    如果您已经在 SwingWorker 或其他线程中运行它,您应该在 EDT 上调用这些更新。通过使用 SwingWorker 的 publish 或使用 invokeLater

    所以当你想更新writeFileLC里面的进度条时:

    final int progress = (int)Math.round(
        100.0 * ((double)symbolsWritten / (double)totalSymbols)
    );
    
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            bar.setValue(progress);
        }
    });
    

    publish 通常比invokeLater 响应性稍差,因为它是combines the results。就个人而言,我通常使用 invokeLater 来更新进度条,但我猜 publish 是你“应该”这样做的方式。

    另请参阅Tasks that Have Interim Results 了解发布教程。

    【讨论】:

    • Radiodef 谢谢你的回答,但在这一点上它仍然超出了我的范围。进度条对我来说是全新的,教练给我们的信息为零,而且它们不在本周的阅读中,所以我从头开始。上面的代码是从另一个从按钮按下调用的方法调用的,所以我认为它在技术上是一个动作事件?另外,当我决定使用 int-int 除法时,我认为它可以,因为值会被截断。进度条不好吗?不是说一定要非常准确吗?
    • 如果有帮助,我添加了一个 SwingWorker 示例(您也可以使用常规线程,实际上它可能更容易)。除非您在单独的线程中运行任务,否则更新进度条根本不起作用。使用除法,截断适用于大数,但您的始终是 0 到 1 之间的小数。您可以尝试(100 * symbolsWritten) / totalSymbols,我想这会起作用。
    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2011-05-13
    • 2012-06-02
    • 2021-04-12
    相关资源
    最近更新 更多