2009-07-26 76 views
0

我有一個遞歸方法,它可以在每次遞歸中更改變量的值,然後在JPanel上顯示該值,然後我想暫停(此處是我的問題)直到我點擊(它暫停在每一個新的遞歸)。然後當我點擊這個方法繼續做下一個遞歸。使遞歸方法在每次遞歸中暫停並繼續點擊

下面的代碼只是我的真實程序的外觀以及我如何實現它的結構。我已經嘗試了很多方法來使用線程和執行程序來做這件事,但我失敗了。

我已經創建了2個類,PanelToBeClicked類是一個JPanel並具有遞歸方法,還有一個PanelMouseListener類收集點擊。

下面的代碼是完全裸線程和執行者。如果有人能夠在此添加一些代碼行來演示正確的方法,我將非常感激,或者給我一些我如何實現它的線索。

下面是代碼:

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

public class PanelToBeClicked extends JPanel { 
    int counter; 

    public PanelToBeClicked() { 
    super(); 
    setPreferredSize(new Dimension(100,100)); 
    addMouseListener(new PanelMouseListener(this)); 
} 

@Override 
protected void paintComponent(Graphics g){ 
    super.paintComponent(g); 
    g.drawString("" + counter, 10, 10); 
} 

public void recursiveMethod(){ 
    counter++; 
    repaint();  

    /* 
    * Pause/wait until the panel is clicked so you proceed the recursions 
    * MISSING CODE HERE. I tried thread.sleep 
    * but I had a monitor exception 
    */ 

    if (counter <10)recursiveMethod(); 
} 

public static void main(String[] args) { 
    final JFrame frame = new JFrame("How can i do that?"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.add(new PanelToBeClicked()); 

    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      frame.pack(); 
      frame.setVisible(true); 
     } 
    }); 
} 
} 

監聽器:

public class PanelMouseListener extends MouseAdapter { 
    private PanelToBeClicked panelToBeClicked; 

    public PanelMouseListener(PanelToBeClicked panelToBeClicked) { 
      this.panelToBeClicked = panelToBeClicked; 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) { 

    /* 
    * start the method PanelToBeClicked.recursiveMethod()... 
    */ 
    panelToBeClicked.recursiveMethod(); 

    /* 
    * if the method is already running and it is not paused do nothing. 
    * ** MISSING CODE 
    * if the method is running and is paused then make the method to continue the recursions 
    * **MISSING CODE */ 

    } 

} 

回答

0

不要忘記,你的揮杆小組將在一個單獨的線程中執行。

您需要等待監視器對象(例如2個線程之間共享的對象),然後點擊面板將向該對象發送通知。遞歸方法需要等待監視器被面板上的點擊操作通知。

在僞代碼(異常等省略)

Object monitor = new Object(); 

void recursiveMethod() { 
    // do stuff and then wait... 
    synchronized (monitor) { 
     monitor.wait(); 
    } 
} 

void doClick() { 
    synchronized (monitor) { 
     monitor.notify(); 
    } 
} 

參見Java Guarded Objects教程的詳細信息。

+0

日Thnx爲您anseer ... 我有設置一個共同的目標監視器的問題..我總是得到illigalMonitorException .... 還有什麼意思通過調用面板?它是否與java反射有關? 我thinkng能夠這樣使用recursiceMethod中的thread.sleep()方法(但我得到一個監視器異常,作爲expecetd ... :(),然後在列表類的mouseClicked處使用thread.notify() – Pitelk 2009-07-26 11:35:57

+0

correnctin .. not htread.sleep().. but thread.wait(); – Pitelk 2009-07-26 11:36:44

0

只是想給爲Java 5+鎖+條件的方式爲例:

package gui; 

import java.awt.Container; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

import javax.swing.GroupLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import javax.swing.GroupLayout.Alignment; 

public class RecursiveContinue extends JFrame { 
    private static final long serialVersionUID = 7149607943058112216L; 
    JLabel value; 
    JButton next; 
    volatile SwingWorker<Void, Void> worker; 
    Lock lock = new ReentrantLock(); 
    Condition cond = lock.newCondition(); 
    boolean continueFlag; 
    public RecursiveContinue() { 
     super("Recursive Continue Example"); 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     value = new JLabel("Recursion depth: None"); 
     next = new JButton("Next"); 
     next.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       doNextClick(); 
      } 
     }); 
     Container c = getContentPane(); 
     GroupLayout gl = new GroupLayout(c); 
     c.setLayout(gl); 
     gl.setAutoCreateContainerGaps(true); 
     gl.setAutoCreateGaps(true); 

     gl.setHorizontalGroup(
      gl.createSequentialGroup() 
      .addComponent(value) 
      .addComponent(next) 
     ); 
     gl.setVerticalGroup(
      gl.createParallelGroup(Alignment.BASELINE) 
      .addComponent(value) 
      .addComponent(next) 
     ); 

     pack(); 
     setLocationRelativeTo(null); 
    } 

    void doNextClick() { 
     if (worker == null) { 
      worker = new SwingWorker<Void, Void>() { 
       @Override 
       protected Void doInBackground() throws Exception { 
        doRecursiveAction(0); 
        SwingUtilities.invokeLater(new Runnable() { 
         @Override 
         public void run() { 
          value.setText("Recursive level: Done"); 
         } 
        }); 
        worker = null; 
        return null; 
       } 
      }; 
      worker.execute(); 
     } else { 
      signal(); 
     } 

    } 
    void signal() { 
     lock.lock(); 
     try { 
      continueFlag = true; 
      cond.signalAll(); 
     } finally { 
      lock.unlock(); 
     } 
    } 
    void await() { 
     lock.lock(); 
     try { 
      while (!continueFlag) { 
       cond.await(); 
      } 
      continueFlag = false; 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } finally { 
      lock.unlock(); 
     } 
    } 
    void doRecursiveAction(final int depth) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       value.setText("Recursive level: " + depth); 
      } 
     }); 
     await(); 
     if (depth < 10) { 
      doRecursiveAction(depth + 1); 
     } 
    } 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new RecursiveContinue().setVisible(true); 
      } 
     }); 
    } 

}