2012-05-27 5 views
12

से jProgressBar अद्यतन मैं प्रोग्रेसबार अपडेट करके लंबे समय तक चलने वाले कार्य की निगरानी करने के लिए उपयोग करता हूं। लंबे समय तक चलने वाला कार्य निश्चित रूप से स्विंगवर्कर थ्रेड में किया जाता है।स्विंगवर्कर

मुझे लगता है कि जैसी चीजों के कार्यक्रम के लिए इस्तेमाल किया:

public class MySwingWorkerClass extends SwingWorker<Void, Void> { 
    private JProgressBar progressBar;  

    public MySwingWorker(JProgressBar aProgressBar) {   
     this.progressBar = aProgressBar;   
     progressBar.setVisible(true);   
     progressBar.setStringPainted(true); 
     progressBar.setValue(0);   
    } 

    @Override 
    public Void doInBackground() { 
     //long running task 
     loop { 
      calculation(); 
      progressBar.setValue(value); 
     } 
     return null; 
    }  

    @Override 
    public void done() {     
     progressBar.setValue(100); 
     progressBar.setStringPainted(false); 
     progressBar.setVisible(false);  
    } 
} 

लेकिन हाल ही में मुझे पता चला कि मैं इसे "setProgress" का उपयोग कर और संपत्ति परिवर्तन को परिभाषित करते हुए करते हैं और कि

public class MySwingWorkerClass extends SwingWorker<Void, Void> { 
    private JProgressBar progressBar;  

    public MySwingWorker(JProgressBar aProgressBar) {   
     addPropertyChangeListener(new PropertyChangeListener() { 
      public void propertyChange(PropertyChangeEvent evt) { 
       if ("progress".equals(evt.getPropertyName())) { 
        progressBar.setValue((Integer) evt.getNewValue()); 
       } 
      } 
     }); 

     progressBar.setVisible(true);   
     progressBar.setStringPainted(true); 
     progressBar.setValue(0); 
     setProgress(0); 
    } 

    @Override 
    public Void doInBackground() { 
     //long running task 
     loop { 
      calculation(); 
      setProgress(value); 
     } 
     return null; 
    }  

    @Override 
    public void done() {     
     setProgress(100); 
     progressBar.setValue(100); 
     progressBar.setStringPainted(false); 
     progressBar.setVisible(false);  
    } 
} 
तरह बातें कर सकता है

मेरा सवाल है: क्या मेरा पहला कोड स्वीकार्य है या क्या मैं किसी भी सत्र के लिए सेट प्रोग्रेस का उपयोग करूंगा? मुझे दूसरा कोड अधिक जटिल लगता है और मेरे मामले में और यह नहीं पता कि दूसरे का उपयोग करने का कोई फायदा या कारण है या नहीं।

कोई सलाह?

EDIT उत्तर के लिए धन्यवाद। एक सारांश के रूप में। पहला समाधान "गलत" है क्योंकि प्रगति बार अद्यतन ईडीटी के बाहर किया जाता है। दूसरा समाधान "सही" है क्योंकि प्रगति बार अपडेट ईडीटी

के अंदर किया गया है, अब मेरे मामले में @mKorbel के "रोचक" उत्तर के अनुसार मेरी गणना HTML पाठ में परिणाम देती है जिसे मैं "सम्मिलित करता हूं" (देखें this link)। मेरा वर्तमान कोड निम्नलिखित है।

मैं प्रकाशित (स्ट्रिंग) और मेरे प्रक्रिया कोड कि

@Override 
    protected void process(List<String> strings) { 
     for (String s : strings) { 
      try { 
       htmlDoc.insertBeforeEnd(htmlDoc.getElement(htmlDoc.getDefaultRootElement(), StyleConstants.NameAttribute, HTML.Tag.TABLE), s); 
      } catch (BadLocationException ex) { 
      } catch (IOException ex) { 
      } 
     } 
    } 

मैं @mKobel मेरे मामले में भी ऐसा ही करने को पुन: उपयोग कर सकते हैं की तरह लग रहा है। मेरा मतलब है कि वह मेरे मामले में टेबल प्रतिपादन को ओवरराइड करने के लिए उपयोग करता है, मैं किस रेंडरर को ओवरराइड (jTextPane?) और कैसे?

+1

मुझे लगता है कि आपका दूसरा दृष्टिकोण भी गलत है। आप मान सेट करने के लिए श्रोता का उपयोग कर रहे हैं, जो श्रोता को बुलाएगा, जो मूल्य निर्धारित करेगा, जो श्रोता इत्यादि का आह्वान करेगा आदि। मुझे यकीन नहीं है कि यह वास्तव में होगा, लेकिन यह गलत लगता है। इस तरह, आपको स्विंगवर्कर का लाभ नहीं मिल रहा है, आप अभी भी ईडीटी में प्रगति पट्टी का मूल्य निर्धारित कर रहे हैं। –

+1

['स्विंगवर्कर.publish (वी ...)'] (http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#publish%28V...%29) "प्रक्रिया विधि के अंदर * इवेंट डिस्पैच थ्रेड * पर प्रसंस्करण के लिए मध्यवर्ती परिणाम देने के लिए 'doInBackground' विधि के अंदर से इस विधि का उपयोग किया जाना चाहिए।" –

+0

@ एंड्रयू थॉम्पसन: मैं प्रकाशन को "प्रकाशित" परिणामों में उपयोग करता हूं लेकिन यहां http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html प्रोग्रेसबार मान सेट करने के लिए वे सेट प्रोग्रेस का उपयोग करते हैं और प्रकाशित नहीं है, तो? – HpTerm

उत्तर

7

पहले कोड में, आप निम्न पंक्ति को गैर-ईडीटी (इवेंट डिस्पैचर थ्रेड) थ्रेड में कॉल कर रहे हैं। तो यह सुरक्षित थ्रेड नहीं है:

progressBar.setValue(value); 

इस रूप में घुमाओ एक धागा सुरक्षित पुस्तकालय के रूप में नहीं बनाया गया है अनपेक्षित व्यवहार हो सकता है।

स्विंग तरीके से इसे करने के लिए विभिन्न विधियां हैं। इसका एक सही तरीका यह है कि आपने दूसरे पोस्ट में क्या किया है। एक और publish()/process() विधियों का उपयोग करना होगा, और एक तीसरी विधि SwingWorker और SwingUtilities.invokeLater() के बजाय अपना स्वयं का धागा लिखना होगा।

+0

क्या आप अपना जवाब यह कहने के लिए संपादित कर सकते हैं कि क्या आपका मतलब है कि मेरा दूसरा कोड उपयोग करने वाला है? क्योंकि टिप्पणियां कहती हैं कि यह "गलत" है, लेकिन हालांकि यह इस http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html के अनुसार सही था, लेकिन क्या मैं "प्रकाशित" का उपयोग करूंगा प्रगति पट्टी अद्यतन करें? मैंने सोचा कि इसके लिए क्या प्रगति है। – HpTerm

4

आपका दूसरा दृष्टिकोण सही है और SwingWorker कक्षा के क्लास जावाडोक में भी दस्तावेज किया गया है। ईडीटी पर 'प्रगति' घटना को निकाल दिया गया है, इसलिए आपका श्रोता ईडीटी पर प्रगति पट्टी को अद्यतन करता है। यह आपके पहले दृष्टिकोण में नहीं है।

एक और दृष्टिकोण (publish/process के रूप में वज़ीर ने संकेत का उपयोग) का एक उदाहरण my answer on a previous SO question

+0

ओह, मैंने इस पहले, सही विश्लेषण को अनदेखा किया। – trashgod

+0

आपके द्वारा प्रदान किया गया लिंक दिलचस्प है, जिस तरह से आप प्रक्रिया/प्रकाशन में प्रगति पट्टी को अपडेट करते हैं और सेट प्रोग्रेस का उपयोग करके नहीं। इस पर एक नज़र डालेंगे। – HpTerm

+1

रॉबिन का सहायक उदाहरण कार्यकर्ता और प्रगति पट्टी को सीधे जोड़ने की सुविधा दिखाता है; 'PropertyChangeListener' के माध्यम से कमजोर युग्मन का लाभ यह है कि _all_ श्रोताओं को केवल प्रगति पट्टी पर ही ईडीटी पर अधिसूचित किया जाता है। – trashgod

4

मैं एक ProgressBar अपडेट करके एक लंबी चलने वाली कार्य की निगरानी करने के लिए उपयोग में पाया जा सकता। लंबे समय तक चलने वाला कार्य निश्चित रूप से स्विंगवर्कर थ्रेड में किया जाता है।

सही आप Background

import java.awt.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.table.*; 

public class TableCellProgressBar { 

    private String[] columnNames = {"String", "ProgressBar"}; 
    private Object[][] data = {{"dummy", 100}}; 
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public Class<?> getColumnClass(int column) { 
      return getValueAt(0, column).getClass(); 
     } 

     @Override 
     public boolean isCellEditable(int row, int col) { 
      return false; 
     } 
    }; 
    private JTable table = new JTable(model); 

    public JComponent makeUI() { 
     TableColumn column = table.getColumnModel().getColumn(1); 
     column.setCellRenderer(new ProgressRenderer()); 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       startTask("test"); 
       startTask("error test"); 
       startTask("test"); 
      } 
     }); 
     JPanel p = new JPanel(new BorderLayout()); 
     p.add(new JScrollPane(table)); 
     return p; 
    } 
//http://java-swing-tips.blogspot.com/2008/03/jprogressbar-in-jtable-cell.html 

    private void startTask(String str) { 
     final int key = model.getRowCount(); 
     SwingWorker<Integer, Integer> worker = new SwingWorker<Integer, Integer>() { 

      private int sleepDummy = new Random().nextInt(100) + 1; 
      private int lengthOfTask = 120; 

      @Override 
      protected Integer doInBackground() { 
       int current = 0; 
       while (current < lengthOfTask && !isCancelled()) { 
        if (!table.isDisplayable()) { 
         break; 
        } 
        if (key == 2 && current > 60) { //Error Test 
         cancel(true); 
         publish(-1); 
         return -1; 
        } 
        current++; 
        try { 
         Thread.sleep(sleepDummy); 
        } catch (InterruptedException ie) { 
         break; 
        } 
        publish(100 * current/lengthOfTask); 
       } 
       return sleepDummy * lengthOfTask; 
      } 

      @Override 
      protected void process(java.util.List<Integer> c) { 
       model.setValueAt(c.get(c.size() - 1), key, 1); 
      } 

      @Override 
      protected void done() { 
       String text; 
       int i = -1; 
       if (isCancelled()) { 
        text = "Cancelled"; 
       } else { 
        try { 
         i = get(); 
         text = (i >= 0) ? "Done" : "Disposed"; 
        } catch (Exception ignore) { 
         ignore.printStackTrace(); 
         text = ignore.getMessage(); 
        } 
       } 
       System.out.println(key + ":" + text + "(" + i + "ms)"); 
      } 
     }; 
     model.addRow(new Object[]{str, 0}); 
     worker.execute(); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

    public static void createAndShowGUI() { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new TableCellProgressBar().makeUI()); 
     frame.setSize(320, 240); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 

class ProgressRenderer extends DefaultTableCellRenderer { 

    private final JProgressBar b = new JProgressBar(0, 100); 

    public ProgressRenderer() { 
     super(); 
     setOpaque(true); 
     b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); 
    } 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
     Integer i = (Integer) value; 
     String text = "Completed"; 
     if (i < 0) { 
      text = "Error"; 
     } else if (i < 100) { 
      b.setValue(i); 
      return b; 
     } 
     super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column); 
     return this; 
    } 
} 

करने का कोई प्रयास और लंबे समय से चल रहा कार्य पुनः निर्देशित लेकिन क्यों (भी Java Essential Classes और Generics के बारे में आवश्यक गहरे ज्ञान) SwingWorker का उपयोग करके Wwing जीयूआई उलझी के लिए सभी मामलों में SwingWorker उपयोग कर सकते हैं ,

Runnable#Thread के लिए मूल कार्यान्वयन स्विंग जीयूआई के आउटपुट के लिए केवल invokeLater आवश्यक है, और मामले में शुरू होने पर घ EDT से, (घुमाओ/AWT श्रोता से) और किसी भी कोड लाइन के बिना होता है Thread.sleep(int) तो है invokeLater केवल सलाह दी/उत्पादन कोड के लिए आवश्यक

import java.awt.Component; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JProgressBar; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingUtilities; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellRenderer; 

public class TableWithProgressBars { 

    public static class ProgressRenderer extends JProgressBar implements TableCellRenderer { 

     private static final long serialVersionUID = 1L; 

     public ProgressRenderer(int min, int max) { 
      super(min, max); 
      this.setStringPainted(true); 
     } 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, 
       boolean isSelected, boolean hasFocus, int row, int column) { 
      this.setValue((Integer) value); 
      return this; 
     } 
    } 
    private static final int maximum = 100; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TableWithProgressBars().createGUI(); 
      } 
     }); 

    } 

    public void createGUI() { 
     final JFrame frame = new JFrame("Progressing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     Integer[] oneRow = {0, 0, 0, 0}; 
     String[] headers = {"One", "Two", "Three", "Four"}; 
     Integer[][] data = {oneRow, oneRow, oneRow, oneRow, oneRow,}; 
     final DefaultTableModel model = new DefaultTableModel(data, headers); 
     final JTable table = new JTable(model); 
     table.setDefaultRenderer(Object.class, new ProgressRenderer(0, maximum)); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     frame.add(new JScrollPane(table)); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       Object waiter = new Object(); 
       synchronized (waiter) { 
        int rows = model.getRowCount(); 
        int columns = model.getColumnCount(); 
        Random random = new Random(System.currentTimeMillis()); 
        boolean done = false; 
        while (!done) { 
         int row = random.nextInt(rows); 
         int column = random.nextInt(columns); 
         Integer value = (Integer) model.getValueAt(row, column); 
         value++; 
         if (value <= maximum) { 
          model.setValueAt(value, row, column); 
          try { 
           waiter.wait(15); 
          } catch (InterruptedException e) { 
           e.printStackTrace(); 
          } 
         } 
         done = true; 
         for (row = 0; row < rows; row++) { 
          for (column = 0; column < columns; column++) { 
           if (!model.getValueAt(row, column).equals(maximum)) { 
            done = false; 
            break; 
           } 
          } 
          if (!done) { 
           break; 
          } 
         } 
        } 
        frame.setTitle("All work done"); 
       } 
      } 
     }).start(); 
    } 
} 

वाकई भारी और लंबी चलने वाली कार्य आप Runnable#Thread पर नजर है के लिए मेरे निष्कर्ष (सरल, आसान, non_buggy और स्पष्ट रास्ता), सिर्फ तभी जब Java & Swing के बारे में अपने ज्ञान को बहुत अच्छी तरह से तो आप सोच सकते हैं के बारे में SwingWorker

+0

यह उत्तर मेरे मामले में अपवाद उत्पन्न करता है [प्रश्न] (http://stackoverflow.com/questions/13538275/the-property-change-event-of- प्रगति-bar-not-firing)! –

4

के रूप में अपने दूसरे उदाहरण में इस example में दिखाया गया है, कार्यकर्ता setProgress() के आपके उपयोग सही है: ए एन PropertyChangeListener घटना प्रेषण धागे पर असीमित रूप से अधिसूचित किया जाएगा।

+0

सही मैं हमेशा इस बारे में भूलना चाहता हूं – mKorbel