2016-12-14 4 views
1

진행률 표시 줄 진행률 메시지를 업데이트하기 위해이 코드를 작성했습니다. 기본적으로 for() 루프에서 실행되는 길이 프로세스가있을 때 루프에서이 프로세스를 던지고 prog = i 및 max = array max로 업데이트해야합니다.업데이트 (그래픽) 사용시 Jlabel 텍스트 곱하기 및 겹침

for(int i = 1; i <= array.length-1; i++){ 
//Process 
setPrg(this.lbl, ths.prg, i, array.length-1, "Doing so process"); 
} 

-

public void setPrg(JLabel lbl, JProgressBar prg, int prog, int max, String msg) { 
    prg.setMaximum(max); 
    if (prog <= max) { 
     prg.setValue(prog); 
    } 
    prg.update(prg.getGraphics()); 
    if (prog >= max) { 
     setMessage(lbl, ""); 
    } else { 
     setMessage(lbl, msg); 
    } 
} 

    public void setMessage(JLabel lbl, String msg) { 
     lbl.setText(msg); 
     lbl.update(lbl.getGraphics()); 
    } 

나는 각 과정을 설명하는 고유 한 메시지를 가지고있는() 루프, 여러 연속이 작업을 수행.

어떤 이유로 인해 레이블 텍스트 자체가 겹쳐서 나타나는 문제가 있습니다.

setPrg(this.lbl, ths.prg, i, array.length-1, "This is process 1"); 

그리고 하나의 코드 실행 : 그럼

setPrg(this.lbl, ths.prg, i, array.length-1, "The second process this is"); 

두 번째 프로세스가 시작으로 두 개의 메시지의 텍스트가 즉시 중복됩니다 예를 들어, 내가 한 루프가있는 경우이 코드를 실행합니다 대신에 "This is process 1"이 사라집니다. 나는이 라인을 포함하지 않으면 반면에

는 :

lbl.update(lbl.getGraphics()); 

텍스트가 전혀 루프 동안 표시하지 않습니다, 그리고 마지막 문자 세트를 라벨은 이후에 표시됩니다에 대한 고리.

도움 주시면 감사하겠습니다.

여기에 전체 프로그램 :

package test; 

import javax.swing.JLabel; 
import javax.swing.JProgressBar; 

public class Main extends javax.swing.JFrame { 

    public Main() { 
     initComponents(); 
    } 
public void setPrg(JLabel lbl, JProgressBar prg, int prog, int max, String msg) { 
     prg.setMaximum(max); 
     if (prog <= max) { 
      prg.setValue(prog); 
     } 
     prg.update(prg.getGraphics()); 
     if (prog >= max) { 
      setMessage(lbl, ""); 
     } else { 
      setMessage(lbl, msg); 
     } 
    } 

    public void setMessage(JLabel lbl, String msg) { 
     lbl.setText(msg); 
     lbl.update(lbl.getGraphics()); 
    } 

    @SuppressWarnings("unchecked") 
    // <editor-fold defaultstate="collapsed" desc="Generated Code">       
    private void initComponents() { 

     jButton1 = new javax.swing.JButton(); 
     jProgressBar1 = new javax.swing.JProgressBar(); 
     jLabel1 = new javax.swing.JLabel(); 
     jTextField1 = new javax.swing.JTextField(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     jButton1.setText("Button"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 

     jLabel1.setText("jLabel1"); 

     jTextField1.setText("jTextField1"); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
        .addGroup(layout.createSequentialGroup() 
         .addGap(246, 246, 246) 
         .addComponent(jLabel1)) 
        .addGroup(layout.createSequentialGroup() 
         .addGap(226, 226, 226) 
         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) 
          .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
          .addComponent(jButton1))) 
        .addGroup(layout.createSequentialGroup() 
         .addContainerGap() 
         .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 540, javax.swing.GroupLayout.PREFERRED_SIZE))) 
       .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
       .addContainerGap(108, Short.MAX_VALUE) 
       .addComponent(jButton1) 
       .addGap(22, 22, 22) 
       .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
       .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(18, 18, 18) 
       .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(40, 40, 40)) 
     ); 

     pack(); 
    }// </editor-fold>       

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     for (int i = 1; i <= 10000; i++) { 
      this.setPrg(jLabel1, jProgressBar1, i, 10000, "Message 1"); 
     } 
       for (int i = 1; i <= 10000; i++) { 
      this.setPrg(jLabel1, jProgressBar1, i, 10000, "Second Message"); 
     } 
    }           

    public static void main(String args[]) { 
     //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
     /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */ 
     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException ex) { 
      java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (InstantiationException ex) { 
      java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     //</editor-fold> 

     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new Main().setVisible(true); 
      } 
     }); 
    } 

    // Variables declaration - do not modify      
    public javax.swing.JButton jButton1; 
    public javax.swing.JLabel jLabel1; 
    public javax.swing.JProgressBar jProgressBar1; 
    public javax.swing.JTextField jTextField1; 
    // End of variables declaration     
} 
+1

'lbl.update (lbl.getGraphics())'는 의미가 없습니다. 그것을 제거해야합니다. 라벨이 오버라이드 (override) 된 paint 또는 paintComponent 메소드를 가지는 서브 클래스인가? – VGR

+0

"프로세스를 설명하는 고유 한 메시지"몇 개의 스레드를 실행합니까? – Andrew

+1

코드가 EventDispatchThread에서 실행 되었습니까 아니면 WorkerThread에서 실행 되었습니까? – Alexander

답변

2

문제는 Swing 이벤트 스레드에서 오래 실행되는 코드를 실행하는 것뿐만 아니라 잘못된 Swing 그래픽 호출을 만드는 것입니다. 해결 방법은 백그라운드 스레드에서 SwingWorker의 doInBackground 메서드와 같이 장기 실행 코드를 수행하고 Swing 이벤트 스레드에서 모든 Swing 호출을 처리하는 데주의를 기울이는 것입니다.

를 사용하고이를 실행하는 방법 :

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.concurrent.ExecutionException; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class Main4b extends JPanel { 
    private static final int MAX = 10000; 
    private static final int PREF_W = 400; 
    private static final int PREF_H = 200; 
    private ButtonAction buttonAction = new ButtonAction(); 
    private JButton button = new JButton(buttonAction); 
    private JTextField jTextField1 = new JTextField("jTextField1", 10); 
    private JLabel jLabel1 = new JLabel("jLabel1"); 
    private JProgressBar jProgressBar1 = new JProgressBar(0, MAX); 

    public Main4b() { 
     jProgressBar1.setStringPainted(true); 

     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 
     add(new JPanel() {{add(button);}}); 
     add(new JPanel() {{add(jTextField1);}}); 
     add(new JPanel() {{add(jLabel1);}}); 
     add(jProgressBar1); 
     setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     Dimension superSz = super.getPreferredSize(); 
     if (isPreferredSizeSet()) { 
      return superSz; 
     } 
     int prefW = Math.max(superSz.width, PREF_W); 
     int prefH = Math.max(superSz.height, PREF_H); 
     return new Dimension(prefW, prefH); 
    } 

    private class ButtonAction extends AbstractAction { 
     public ButtonAction() { 
      super("Button"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      setEnabled(false); // make the button non-pressable 

      // create background thread worker 
      MyWorker myWorker = new MyWorker(); 

      // add propertychange listener to it 
      myWorker.addPropertyChangeListener(new WorkerListener()); 

      // run the worker thread 
      myWorker.execute(); 
     } 
    } 

    // background thread 
    private static class MyWorker extends SwingWorker<Void, Integer> { 
     private static final String MY_PROGRESS = "my progress"; 
     private int myProgress = 0; 

     @Override 
     protected Void doInBackground() throws Exception { 
      // all this code is run in a background thread 

      // do this twice 
      for (int j = 0; j < 2; j++) { 

       // iterate from 0 to 10,000 
       for (int i = 0; i < MAX; i++) { 
        Thread.sleep(1); // small delay so we can see what we're doing 
        setMyProgress(i + j * MAX); // send output to listeners 
       } 
      } 
      return null; 
     } 

     public int getMyProgress() { 
      return myProgress; 
     } 

     // myProgress is a "bound" field, one that will notify listeners 
     // if it is changed 
     public void setMyProgress(int myProgress) { 
      int oldValue = this.myProgress; 
      int newValue = myProgress; 
      this.myProgress = myProgress; 
      // notify all listeners 
      firePropertyChange(MY_PROGRESS, oldValue, newValue); 
     } 

    } 

    private class WorkerListener implements PropertyChangeListener { 
     private String message = "Message %d: %05d"; 

     public WorkerListener() { 
      jLabel1.setText(String.format(message, 1, 0)); 
     } 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
      // all this code is run on the Swing event thread 

      // listen for changes to my progress bound field 
      if (MyWorker.MY_PROGRESS.equals(evt.getPropertyName())) { 
       int value = (int) evt.getNewValue(); // get value 
       int newMsgIndex = 1 + value/MAX; // message number 
       jProgressBar1.setValue(value % MAX); // set value on progress bar 
       jLabel1.setText(String.format(message, newMsgIndex, value % MAX)); 
      } else if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
       // worker is done 
       jLabel1.setText(""); // reset JLabel 
       buttonAction.setEnabled(true); // re-enable JButton's Action 
       MyWorker myWorker = (MyWorker) evt.getSource(); 
       try { 
        // always call this to catch and handle any exceptions that 
        // may have been thrown from within the worker 
        myWorker.get(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } catch (ExecutionException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

    } 

    private static void createAndShowGui() { 
     Main4b mainPanel = new Main4b(); 

     JFrame frame = new JFrame("Main"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 
4

당신이 멀티 스레드 환경에서 자동으로있는 스윙을 사용하고 있습니다. 하나는 메인 스레드이고, Swing은 UI 다시 그리기에 EDT를 사용합니다. 사용 SwingUtilities.invokeLater()

는) 및 JLabel.setValue()는 EventDispatchThread로에JProgressBar.setValue을 (실행합니다. 이렇게하면 업데이트됩니다.

SwingUtilities 사용 방법의 예입니다.

final JProgressBar prg = new JProgressBar(); 
    final JLabel lbl = new JLabel(); 

    SwingUtilities.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      prg.setValue(70); 
      lbl.setText("Text"); 
     } 
    }); 

그리고 당신은 볼 것이다, 그 lbl.update로 전화 (lbl.getGraphics());은 더 이상 필요하지 않습니다.

+0

시도해 보았지만 여전히 업데이트되지 않으므로 진행 막대에 변경 사항이 표시되지 않습니다. – Zhiming010

+0

'public void setPrg (final JLabel lbl, final JProgressBar prg, final int prog, final int max, final String MSG) { SwingUtilities.invokeLater (신규의 Runnable() { @Override 공개 무효 실행() { prg.setMaximum (최대); 경우 (PROG <= 최대) { prg.setValue (PROG)} if (prog> = max) { lbl.setText (""); } else { lbl.setText (msg); } } }); }' – Zhiming010