2014-02-15 1 views
1

Это домашнее задание, в котором я должен прочитать файл и преобразовать все символы в верхний или нижний регистр в зависимости от того, что пользователь выбирает. У меня все работает, но я не уверен, обновляется ли индикатор выполнения каждого символа, или если он перескакивает до 100% при записи файла. Моя логика заключалась в том, что каждый символ записывается. Я увеличиваю счетчик и следую за этим приращением. Итак, progressBar.setValue(100 * (symbolsWritten/totalSymbols)); Вот часть моего кода, которая проверяет, является ли символ строчным, и при необходимости преобразует его в верхний регистр. Я просто учился, поэтому, пожалуйста, не слишком сильно меняйте мой код :) Спасибо за ваши комментарии.Можно ли обновить JProgressBar, просто увеличив setValue?

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 

ответ

2

Здесь есть две вещи. Первое - целочисленное деление, потому что symbolsWritten и totalSymbols оба являются int. Таким образом, вы никогда не получите дробное значение от int/int. Это будет просто прыгать от 0 до 1. Вы можете сделать бросок, если вы хотите:.

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

(Либо это, либо определить их как двойной, чтобы начать с это нормально использовать ++ на двойной, если значения в диапазон int.)

Другой способ обновления значения, поскольку это должно быть сделано на 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 будет есть их, но будет бросать ExecutionException с съеденной исключением как его причина, если вы звоните get.)

Если вы уже используете это в SwingWorker или другом потоке, вы должны называть эти обновления на EDT. Либо используя SwingWorker's 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 для обновления строки выполнения, но я думаю, что публикация - это то, как вы «предполагаете» это сделать.

Также см. Tasks that Have Interim Results для учебника по публикации.

+0

Radiodef благодарит вас за ответ, но на данный момент он все еще находится вне меня. Шаги прогресса абсолютно для меня, инструктор дал нам нулевую информацию о них, и они не были на этой неделе, поэтому я начинаю с нуля. Вышеупомянутый код вызывается из другого метода, который вызывается из нажатия кнопки, поэтому я считаю, что это технически событие действия? Кроме того, когда я решил использовать int-int division, я думал, что это будет нормально, потому что значение будет усечено. Разве это не нормально для индикатора прогресса? Не похоже, чтобы это было действительно верно? –

+0

Я добавил пример SwingWorker, если это поможет (вы также можете использовать обычный Thread, и это может быть проще). Обновление индикатора выполнения просто не будет работать, если вы не запустите задачу в отдельном потоке. С делением усечение работает для больших чисел, но ваш всегда будет фракцией между 0 и 1. Вы можете попробовать '(100 * charactersWritten)/totalSymbols', который, как я думаю, будет работать. – Radiodef