2011-10-11 69 views
1

我的程序直观地演示了众所周知的QuickSort算法的顺序版本,并提供了两个新的可视化演示:(I)QuickSort的并行版本,使用低级别线程API和SwingUtilities,以及(II)使用SwingWorker API实现的QuickSort的并行版本。线程和按钮:如何在完成运行后重新启动程序

我试图在成功运行后重新启动程序。目前,当排序操作开始时,这些按钮被禁用,这是正确的,但它们不会重新启用,所以我想知道在成功运行后是否有方法启用所有按钮?部分代码如下:

// http://www.java2s.com/Code/Java/Collections-Data-Structure/Animationforquicksort.htm 
// http://www.sorting-algorithms.com/quick-sort 

import java.lang.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.Rectangle2D; 
import java.util.*; 
import javax.swing.*; 
import java.util.concurrent.atomic.*; 

public class QuickSortVisualizer implements Runnable { 
    static int LENGTH = 32; 
    static int LEFT = 500; 
    static int RIGHT = 500; 
    static int SWAP = 1000; 

    int[] Values; 
    AtomicInteger WorkerThreads = new AtomicInteger(); 

    public static void main(String[] args) { 
     try { 
      if (args.length == 0) {    
       LENGTH = 32; 
       LEFT = 500; 
       RIGHT = 500; 
       SWAP = 1000; 

      } else if (args.length == 4) { 
       //dw about this 



      } else { 
       throw new Exception("incorrect command-line argument count"); 
      } 

      System.err.format("... LENGTH=%d LEFT=%d RIGHT=%d SWAP=%d%n", LENGTH, LEFT, RIGHT, SWAP); 
      SwingUtilities.invokeAndWait(new QuickSortVisualizer()); 
      System.err.format("... GUI started%n"); 

     } catch (Exception ex) { 
      System.err.format("*** %s%n", ex.getMessage()); 
     } 
    } 

    JButton BoredButton; 
    JButton WorkerButtonSequential; 
    JButton WorkerButtonThreads; 
    JButton WorkerButtonSwingWorkers; 
    SorterPanel MySortPanel; 
    JLabel StatusBar; 

    public void run() { 
     JFrame frame = new JFrame(); 
     frame.setTitle("My Quick Sort Visualizer"); 
     Font font = new Font("Monospaced", Font.BOLD, 18); 

     BoredButton = new JButton("I am bored"); 
     BoredButton.setFont(font); 
     BoredButton.setPreferredSize(new Dimension(180, 30)); 
     BoredButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       BoredButton_Click(); 
      } 
     }); 

     WorkerButtonSequential = new JButton("QS Sequential"); 
     WorkerButtonSequential.setFont(font); 
     WorkerButtonSequential.setPreferredSize(new Dimension(185, 30)); 
     WorkerButtonSequential.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       WorkerButtonSequential_Click(); 
      } 
     }); 

     WorkerButtonThreads = new JButton("QS Threads"); 
     WorkerButtonThreads.setFont(font); 
     WorkerButtonThreads.setPreferredSize(new Dimension(185, 30)); 
     WorkerButtonThreads.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       WorkerButtonThreads_Click(); 
      } 
     }); 

     WorkerButtonSwingWorkers = new JButton("QS SwingWorkers"); 
     WorkerButtonSwingWorkers.setFont(font); 
     WorkerButtonSwingWorkers.setPreferredSize(new Dimension(200, 30)); 
     WorkerButtonSwingWorkers.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       WorkerButtonSwingWorkers_Click(); 
      } 
     }); 

     JPanel strip = new JPanel(new FlowLayout(FlowLayout.CENTER)); 
     strip.add(BoredButton); 
     strip.add(WorkerButtonSequential); 
     strip.add(WorkerButtonThreads); 
     strip.add(WorkerButtonSwingWorkers); 
     frame.getContentPane().add(strip, BorderLayout.NORTH); 

     StatusBar = new JLabel(); 
     StatusBar.setFont(font); 
     StatusBar.setPreferredSize(new Dimension(800, 20)); 
     frame.getContentPane().add(StatusBar, BorderLayout.SOUTH); 

     MySortPanel = new SorterPanel(); 
     frame.getContentPane().add(MySortPanel, BorderLayout.CENTER); 

     frame.getRootPane().setDefaultButton(BoredButton); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(800, 400); 
     frame.setResizable(true); 
     frame.setVisible(true); 
    } 

    public void BoredButton_Click() { 
     String text = Calendar.getInstance().getTime().toString(); 
     StatusBar.setText(text); 
     System.err.format("... now %s%n", text); 
    } 

    public void WorkerButtonSequential_Click() { 
     WorkerButtonSequential.setEnabled(false); 
     WorkerButtonThreads.setEnabled(false); 
     WorkerButtonSwingWorkers.setEnabled(false); 
     System.err.format("... sequential%n"); 

     QSSequential(); 
    } 

    public void WorkerButtonThreads_Click() { 
     WorkerButtonSequential.setEnabled(false); 
     WorkerButtonThreads.setEnabled(false); 
     WorkerButtonSwingWorkers.setEnabled(false); 
     int processors = Runtime.getRuntime().availableProcessors(); 
     int threshold = processors * 2; 
     System.err.format("... parallel threads: processors=%d threshold=%d%n", processors, threshold); 
     QSThreads(threshold); 
    } 

    public void WorkerButtonSwingWorkers_Click() { 
     WorkerButtonSequential.setEnabled(false); 
     WorkerButtonThreads.setEnabled(false); 
     WorkerButtonSwingWorkers.setEnabled(false); 
     int processors = Runtime.getRuntime().availableProcessors(); 
     int threshold = processors * 2; 
     System.err.format("... parallel swingworkers: processors=%d threshold=%d%n", processors, threshold); 
     QSSwingWorkers(threshold); 
    } 

    void QSInit() { 
     Values = new int[LENGTH]; 
     for (int i = 0; i < Values.length; i++) { 
      Values[i] = (int)Math.round(Math.random() * (MySortPanel.getHeight()-10)); 
     } 
     print("... initial values");     

     MySortPanel.setValues(Values);  
    } 

    void QSSequential() { 
     QSInit(); 

     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       QuickSortSequential qss = new QuickSortSequential(Values, 0, Values.length - 1, MySortPanel); 
       System.err.format("... started%n"); 
       qss.run(); 

       DoneAll(); 
      } 
     }); 
    } 

    void QSThreads(int threshold) { 
     QSInit(); 

     QuickSortThread qst = new QuickSortThread(Values, 0, Values.length - 1, threshold, MySortPanel); 
     WorkerThreads.set(0); 
     incWorkerThreads(); 
     System.err.format("... started%n"); 
     qst.start(); 
    } 

    void QSSwingWorkers(int threshold) { 
     QSInit(); 

     QuickSortWorker qsw = new QuickSortWorker(Values, 0, Values.length - 1, threshold, MySortPanel); 
     WorkerThreads.set(0); 
     incWorkerThreads(); 
     System.err.format("... started%n"); 
     qsw.execute();  
    } 

    void print(String caption) { 
     System.err.format("%s%n", caption); 
     for (int i=0; i<Values.length; i++) { 
      System.err.format(" %d:%d", i, Values[i]); 
     } 
     System.err.format("%n"); 
    } 

    void incWorkerThreads() { 
     int w = WorkerThreads.incrementAndGet(); 
     System.err.format("... workers=%d%n", w); 
    } 

    void decWorkerThreads() { 
     int w = WorkerThreads.decrementAndGet(); 
     System.err.format("... workers=%d%n", w); 
     if (w <= 0) DoneAll(); 
    } 

    void DoneAll() { 
     print("... sorted values");     
     WorkerButtonSequential.setEnabled(true);  
     WorkerButtonThreads.setEnabled(true);  
     WorkerButtonSwingWorkers.setEnabled(true);  
     System.err.format("%n"); 
    } 

    // === SorterPanel 

    /* colour codes 
    pivot : YELLOW 
    left item : GREEN 
    right item : BLUE 
    left item just before swap : PINK 
    right item just before swap : PINK 
    left item just after swap : RED 
    right item just after swap : RED 
    */ 

    class SorterPanel extends JComponent { 
     int[] Values;  
     int width; 
     Graphics2D g2; 
     Color pen; 
     Color back; 

     public void setValues(int[] Values) { 
      this.Values = Values; 
      width = super.getWidth()/Values.length; 
      repaint(); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      if (Values == null) return; 

      g2 = (Graphics2D) g; 
      pen = Color.BLACK; // g2.getColor(); 
      back = g2.getBackground(); 

      for (int i = 0; i < Values.length; i++) { 
       g2.draw(new Rectangle2D.Double(width*i+1, 0, width-2, Values[i])); 
      } 
     } 

     public void mark(int i, int value, Color m) { 
      g2 = (Graphics2D) super.getGraphics(); 
      pen = g2.getColor(); 
      g2.setColor(m); 
      //g2.fill(new Rectangle2D.Double(width*i+2, 1, width-4, Values[i]-2)); 
      g2.fill(new Rectangle2D.Double(width*i+2, 1, width-4, value-2)); 
      g2.setColor(pen); 
     } 

     public void unmark(final int i, final int value) { 
      mark(i, value, back); 
     } 

     public void erase(int i, int value) { 
      g2 = (Graphics2D) super.getGraphics(); 
      //g2.clearRect(width*i+1, 0, width-1, Values[i]+1); 
      g2.clearRect(width*i+1, 0, width-1, value+1); 
     } 

     public void redraw(int i, int value) { 
      g2 = (Graphics2D) super.getGraphics(); 
      //g2.draw(new Rectangle2D.Double(width*i+1, 0, width-2, Values[i])); 
      g2.draw(new Rectangle2D.Double(width*i+1, 0, width-2, value)); 
      mark(i, value, back); 
     } 
    } 

    // === QuickSort Sequential 

    class QuickSortSequential implements Runnable { 
     int[] array; 
     int left; 
     int right; 

     // === GUI stuff 

     SorterPanel sortpan; 

     void publish(Runnable gui_update) { 
      gui_update.run(); 
     } 

     void mark(final int idx, final Color color) { 
      final int value = array[idx]; 
      publish(new Runnable() { 
       public void run() { 
        sortpan.mark(idx, value, color); 
       } 
      }); 
     } 

     void unmark(final int idx) { 
      final int value = array[idx]; 
      publish(new Runnable() { 
       public void run() { 
        sortpan.unmark(idx, value); 
       } 
      }); 
     } 

     void erase(final int idx) { 
      final int value = array[idx]; 
      publish(new Runnable() { 
       public void run() { 
        sortpan.erase(idx, value); 
       } 
      }); 
     } 

     void redraw(final int idx) { 
      final int value = array[idx]; 
      publish(new Runnable() { 
       public void run() { 
        sortpan.redraw(idx, value); 
       } 
      }); 
     } 

     void sleep(int period) { 
      try { 
       Thread.sleep(period); 
      } catch (Exception ex) { 
       System.err.format("%s%n", ex.getMessage()); 
      }     
     } 

     // === stuff 

     public QuickSortSequential(final int array[], final int left, final int right, final SorterPanel sortpan) { 
      this.array = array; 
      this.left = left; 
      this.right = right; 
      this.sortpan = sortpan; 
     } 

     public void run() { 
      QuickSort(); 
     } 

     // === QuickSort stuff 

     void QuickSort() { 
      if (left >= right) return; 
      final int pivot = Partition(); 
      if (pivot < 0) return; 

      QuickSortSequential lquick = new QuickSortSequential(array, left, pivot-1, sortpan); 
      QuickSortSequential rquick = new QuickSortSequential(array, pivot, right, sortpan); 

      lquick.run(); 
      rquick.run(); 
     } 

     int Partition() { 
      int leftIdx = left; 
      int rightIdx = right; 
      int pivotIdx = (left + right)/2; 
      final int pivot = array[pivotIdx]; 

      while (true) { 
       if (leftIdx > rightIdx) break; 

       mark(pivotIdx, Color.YELLOW); 
       mark(leftIdx, Color.GREEN); 
       mark(rightIdx, Color.BLUE); 
       sleep(LEFT); 

       while (true) { 
        if (array[leftIdx] >= pivot) break; 
        else { 
         unmark(leftIdx); 
         leftIdx += 1; 
         mark(pivotIdx, Color.YELLOW); 
         mark(leftIdx, Color.GREEN); 
         sleep(LEFT); 
        } 
       } 

       while (true) { 
        if (pivot >= array[rightIdx]) break; 
        else { 
         unmark(rightIdx); 
         rightIdx -= 1; 
         mark(pivotIdx, Color.YELLOW); 
         mark(rightIdx, Color.BLUE); 
         sleep(RIGHT); 
        } 
       } 

       unmark(pivotIdx); 
       unmark(leftIdx); 
       unmark(rightIdx); 

       if (leftIdx <= rightIdx) {     
        if (leftIdx < rightIdx) { 
         mark(pivotIdx, Color.YELLOW); 
         mark(leftIdx, Color.PINK); 
         mark(rightIdx, Color.PINK); 
         sleep(SWAP); 

         erase(leftIdx); 
         erase(rightIdx); 

         int temp = array[rightIdx]; 
         array[rightIdx] = array[leftIdx]; 
         array[leftIdx] = temp; 

         if (pivotIdx == leftIdx) pivotIdx = rightIdx; 
         else if (pivotIdx == rightIdx) pivotIdx = leftIdx; 

         redraw(leftIdx); 
         redraw(rightIdx); 

         mark(pivotIdx, Color.YELLOW); 
         mark(leftIdx, Color.RED); 
         mark(rightIdx, Color.RED); 
         sleep(SWAP); 

        } 

        unmark(pivotIdx); 
        unmark(leftIdx); 
        unmark(rightIdx); 

        leftIdx += 1; 
        rightIdx -= 1; 
       } 
      } 

      return leftIdx; 
     } 
    } 

    // === QuickSort with Threads 

    class QuickSortThread extends Thread { 
     int[] array; 
     int left; 
     int right; 
     int threshold; 

     // === GUI stuff 

     SorterPanel sortpan; 



     // === Thread etc stuff 

     public QuickSortThread(final int array[], final int left, final int right, final int threshold, final SorterPanel sortpan) { 
      this.array = array; 
      this.left = left; 
      this.right = right; 
      this.sortpan = sortpan; 
      this.threshold = threshold; 
     } 

     @Override 
     public void run() { 

      decWorkerThreads(); 
     } 


    } 

    // === QuickSort with SwingWorkers 

    class QuickSortWorker extends SwingWorker<Boolean, Runnable> { 
     int[] array; 
     int left; 
     int right; 
     int threshold; 

     // === GUI stuff 

     SorterPanel sortpan; 



     // === SwingWorker stuff 

     public QuickSortWorker(final int array[], final int left, final int right, final int threshold, final SorterPanel sortpan) { 
      this.array = array; 
      this.left = left; 
      this.right = right; 
      this.threshold = threshold; 
      this.sortpan = sortpan; 

     } 

     @Override 
     public Boolean doInBackground() { 


      return true; 
     } 

     @Override 
     public void process(java.util.List<Runnable> gui_updates) { 

     } 

     @Override 
     public void done() { 

      decWorkerThreads(); 
     } 


    } 
} 
+0

到底是什么问题了吗?什么阻止你重新开始排序? –

+0

完全没有问题。代码执行得很好,但我希望它在完成排序后重新启动,即我的所有按钮都需要设置为true。等待病态发布我的整个代码。 – Jay

+0

@Jay我试着在这里发布的代码,所以漂亮的输出,卓越的想法,实现SwingWorker#cancel(),并为JPanels布局寻找CardLayout +1 – mKorbel

回答

1

没有直接回答你的问题,但我看三个方面,我认为你的代码错过

通知请仔细阅读How to get Exception from SwingWorker

+0

我还没有完成代码,这就是为什么它缺少一些部分。 – Jay

+1

@Jay :-)修复后,请将您的想法分发到一些JavaExampleDepots :-),因为在当前形式中有这个代码非常好,并有趣的输出到屏幕 – mKorbel

+0

是的dw多数民众赞成如果我在一个星期内完成它或我马只是离开它 – Jay