2

내 프로그램에 JProgressBar를 추가하려고하지만 업데이트가 없습니다! 이 값은 100 % 원인을 한 번만 변경합니다. 내 방법이있다.JProgressBar가 업데이트되지 않습니다

public void downloadImages(List<String> images) { 
    if (errorCode == 0) { 
     for (int i = 0; i < images.size(); i++) { 
      if (errorCode == 0) { 
       main.progressLabel.setText("Downloading image " + Integer.toString(i + 1) + " of " + Integer.toString(images.size())); 
       String imageStr = images.get(i); 
       String imageName = imageStr.substring(imageStr.lastIndexOf("/") + 1); 
       try { 
        URL url = new URL(imageStr); 
        InputStream in = url.openStream(); 
        OutputStream out = new FileOutputStream(saveDirectory + imageName); 

        byte[] b = new byte[2048]; 
        int length; 
        while ((length = in.read(b)) != -1) { 
         out.write(b, 0, length); 
        } 

        in.close(); 
        out.close(); 
       } catch (MalformedURLException e) { 
        errorCode = BAD_URL; 
       } catch (IOException e) { 
        errorCode = INVALID_PATH; 
       } 
       main.progressBar.setValue(((i+1)/images.size())*100); 
      } 

     } 
    } 
} 

진행률 막대 값을 변경하는 것은 위의 방법의 맨 아래에 있습니다.

그리고 어떻게 그 방법을 호출 할 수 있습니다.

public void download() { 
    final Downloader downloader = new Downloader(this, albumUrl.getText(), downloadPath.getText()); 
    progressBar.setValue(0); 
    downloadButton.setEnabled(false); 

    new Thread(new Runnable() { 
     public void run() { 
      List<String> images = downloader.getImages(downloader.getPageSource()); 
      downloader.downloadImages(images); 
      if (downloader.getErrorCode() == 0) { 
       progressLabel.setText("All images have been downloaded!"); 
      } else { 
       String error = ""; 
       switch (downloader.getErrorCode()) { 
       case Downloader.BAD_URL: 
       case Downloader.NOT_IMGUR_ALBUM: 
        error = "The URL entered is either invalid or does not link to an Imgur album."; 
        break; 
       case Downloader.BLANK_URL: 
        error = "The album URL field cannot be blank."; 
        break; 
       case Downloader.INVALID_PATH: 
        error = "The system cannot find the download directory path specified."; 
        break; 
       case Downloader.BLANK_PATH: 
        error = "The download directory cannot be blank."; 
        break; 
       case Downloader.CANNOT_READ_URL: 
        error = "An error occoured while reading the URL."; 
        break; 
       case Downloader.PARSING_ERROR: 
        error = "An error occoured while parsing the URL."; 
        break; 
       } 
       JOptionPane.showMessageDialog(Main.this, error, "Error", 0); 
      } 
      downloadButton.setEnabled(true); 
     } 
    }).start(); 
} 

편집 : 위의 문제는 전혀 문제가 아니며 프로그램에서 소수를 사용하지 않고 정수를 사용했습니다.

답변

4

images.size()는 정수이고, 그래서 그래서 무슨 일이 일어나고는 소수가 잘립니다지고있다, i+1입니다 : 여기

작은 예입니다. 이 그것이 i+1는 소수점 수있는 데이터 형으로 구분되고 있음을 확인합니다됩니다 할 수있는 것들

main.progressBar.setValue((int)((i+1)/(double)images.size())/100))

처럼 그렇게 일을해야 무엇 무엇인가, (더 포괄적 인 데이터 형식을 반환 which'll 이 경우에는 double), double을 int로 나눌 것입니다. 왜냐하면 더 포괄적이기 때문에 double을 리턴 할 것이기 때문에 문제가되지 않을 것입니다. 그런 다음 데이터 유형이 setValue()이므로 int로 캐스팅합니다. 스윙의

+0

+1이 응답을 입력하는 중입니다. 조나단은 현재 코드로 항상 0이 될 것입니다. EDT에서 UI 업데이트 코드를 이동하는 것뿐만 아니라 정밀 문제를 해결하면이 기능이 올바르게 수행되어야합니다. –

+0

+1 예전 다른 문제는 OP가 있고, 아마도 실제 문제를 일으키는 것이지만, 장기 실행 루프에서 edt/edt에서 Swing을 업데이트하는 것은 좋지 않습니다. –

+0

자바가이 일을 한 번도 알지 못해서 죄송합니다.하지만 너희들은 많이 배웠다. EDT, 감사합니다 : D –

7

주요 문제는 GUI EDT에서 장기 실행 작업을 수행하여 Event Dispatch Thread을 차단하고 있다는 것입니다.

SwingWorker을 사용하십시오.

enter image description here

import java.awt.BorderLayout; 
import java.awt.Cursor; 
import java.awt.Insets; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.Random; 
import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingWorker; 

public class ProgressBarDemo extends JPanel { 

    private JButton startButton; 
    private JTextArea taskOutput; 

    public ProgressBarDemo() { 
     super(new BorderLayout()); 

     final JProgressBar progressBar = new JProgressBar(0, 100); 
     progressBar.setValue(0); 
     progressBar.setStringPainted(true); 

     taskOutput = new JTextArea(5, 20); 
     taskOutput.setMargin(new Insets(5, 5, 5, 5)); 
     taskOutput.setEditable(false); 

     // Create the demo's UI. 
     startButton = new JButton("Start"); 
     startButton.setActionCommand("start"); 
     startButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       startButton.setEnabled(false); 
       setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
       // Instances of javax.swing.SwingWorker are not reusuable, so 
       // we create new instances as needed. 
       final Task task = new Task(); 
       task.addPropertyChangeListener(new PropertyChangeListener() { 
        @Override 
        public void propertyChange(PropertyChangeEvent pce) { 
         if ("progress".equals(pce.getPropertyName())) { 
          int progress = (Integer) pce.getNewValue(); 
          progressBar.setValue(progress); 
          taskOutput.append(String.format("Completed %d%% of task.\n", task.getProgress())); 
         } 
        } 
       }); 
       task.execute(); 
      } 
     }); 

     JPanel panel = new JPanel(); 
     panel.add(startButton); 
     panel.add(progressBar); 

     add(panel, BorderLayout.PAGE_START); 
     add(new JScrollPane(taskOutput), BorderLayout.CENTER); 
     setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); 

    } 

    /** 
    * Create the GUI and show it. As with all GUI code, this must run on the 
    * event-dispatching thread. 
    */ 
    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("ProgressBarDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel progressBarPanel = new ProgressBarDemo(); 
     frame.add(progressBarPanel); 

     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // Schedule a job for the event-dispatching thread: 
     // creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

    private class Task extends SwingWorker<Void, Void> { 

     /* 
     * Main task. Executed in background thread. 
     */ 
     @Override 
     public Void doInBackground() { 
      Random random = new Random(); 
      int progress = 0; 
      // Initialize progress property. 
      setProgress(0); 
      while (progress < 100) { 
       // Sleep for up to one second. 
       try { 
        Thread.sleep(random.nextInt(1000)-15); 
       } catch (InterruptedException ignore) { 
       } 
       // Make random progress. 
       progress += random.nextInt(10); 
       setProgress(Math.min(progress, 100)); 
      } 
      return null; 
     } 

     /* 
     * Executed in event dispatching thread 
     */ 
     @Override 
     public void done() { 
      Toolkit.getDefaultToolkit().beep(); 
      startButton.setEnabled(true); 
      setCursor(null); // turn off the wait cursor 
      taskOutput.append("Done!\n"); 
     } 
    } 
} 
+1

와우 살펴보고, 자세한 내용은 Concurrency in Swing에서 봐, 즉이었다 실행중인 예제로 빠른 업데이트;) – MadProgrammer

+0

나는 그것을 시도했지만 여전히 작동하지 않았다! 나는 downloadImages 메서드를 호출하는 방법을 보여주기 위해 게시물을 편집했습니다. –

+0

@JonathanBeaudoin 어쨌든 제가 Swing worker를 제안했는데 편집 내용이 쓰레드가 사용되고 SwingWorker가 없다는 것을 보여 줍니까? 내가 준 링크를 읽으세요.그리고 다른 사람들도 –

3

두 규칙 ...

  1. 는 이벤트 파견 스레드 중 측면에서 어떤 UI 구성 요소를 업데이트하지 마십시오 이벤트 파견 스레드를 막지 마십시오.

나는 더 많은 것이 있지만, 이것들 중 하나 또는 둘 다를 깨뜨리고 일어나기를 기대합니다.

스윙은 단일 스레드 API입니다. 다시 칠하기 요청을 포함하여 이벤트를 전달하는 단일 스레드가 있습니다. 이 스레드를 차단하면 (시간이 많이 소요되는 작업, I/O 등) 사용자 입력을 처리하고 구성 요소에 다시 칠하기 요청을 보내지 않으므로 아무 것도 업데이트되지 않고 응용 프로그램이 멈춰있는 것처럼 보입니다. ...

당신은 EDT OFF 이미지 로딩 코드를 얻을 필요가

...

특히, Worker Threads and SwingWorker

+0

+1 나는 규칙을 좋아한다 :) –

관련 문제