我有一个递归方法,在每次递归时更改变量的值,然后在JPanel上显示该值,然后我想暂停(这是我的问题)直到我点击(它会在每次新的递归中暂停)。然后,当我单击此方法时,继续进行下一次递归。
以下代码只是我的真实程序的结构以及我如何尝试实现它的结构。我已经尝试过很多方法来使用线程和执行器做这件事,但我失败了。
我创建了两个类,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 :(得分:0)
不要忘记你的Swing Panel将在一个单独的线程中执行。
您需要等待监视器对象(例如,在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教程。
答案 1 :(得分: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);
}
});
}
}