我正在尝试对算法进行可视化。我有一个工作计划,但是真的很脏,我决定在继续之前重新粉碎它。问题是它在算法完成之前不再重新绘制。 (我尝试使用revalidate代替/与重绘相结合)
选项菜单:
public class BootScreen extends JPanel implements ActionListener {
GridBagConstraints c = new GridBagConstraints();
JFrame frame = new JFrame();
SpinnerNumberModel arraySizeModel = new SpinnerNumberModel(50, 0, 100000, 1);
SpinnerNumberModel speedModel = new SpinnerNumberModel(20, 0, 10000, 1);
SpinnerNumberModel algSelectModel = new SpinnerNumberModel(1, 1, 5, 1);
JSpinner arraySizeSpinner = new JSpinner(arraySizeModel);
JSpinner speedSpinner = new JSpinner(speedModel);
JSpinner algSelectSpinner = new JSpinner(algSelectModel);
JButton start = new JButton("Start");
BootScreen() {
frame.setTitle("Settings");
frame.setSize(500, 250);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(this);
//just creating the options menu, nothing special here (deleted for simplicity)
//...
}
@Override
public void actionPerformed( ActionEvent e ) {
Algorithm alg = new Algorithm(Integer.parseInt(arraySizeModel.getValue().toString()), Integer.parseInt
(speedModel.getValue().toString()));
switch(Integer.parseInt(algSelectModel.getValue().toString())) {
case 1:
alg.alg1();
break;
case 2:
alg.alg2();
break;
case 3:
alg.alg3();
break;
case 4:
alg.alg4();
break;
case 5:
alg.alg5();
break;
}
}
public static void main(String[] Args) {new BootScreen();}
}
主要算法的东西:
public class Algorithm {
int[] A;
GUI gui;
int type;
int[] pointers;
int delay;
int max;
Random r = new Random();
Algorithm( int arraySize, int delaySet) {
A = new int[arraySize];
delay = delaySet;
gui = new GUI(this);
}
void generate(int maxIntSize, int pointersAmount, int typeSet) {
max = maxIntSize;
for( int i = 0; i < A.length; i++ ) {
A[i] = r.nextInt(max);
}
pointers = new int[pointersAmount];
for( int i = 0; i < pointers.length; i++ ) {
pointers[i] = -1;
}
type = typeSet;
}
void step(boolean sleep, int updatePointer, int updatePointerVal) {
pointers[updatePointer] = updatePointerVal;
gui.revalidate();
gui.repaint();
if( sleep ) {
try {
Thread.sleep(delay);
}catch( InterruptedException e ) {
}
}
}
//alg1(), alg2(), .... would be here. They first call generate() and call step() a couple of times. (deleted for simplicity)
}
GUI:
public class GUI extends JPanel {
JFrame frame = new JFrame();
Algorithm alg;
GUI( Algorithm algIn ) {
alg = algIn;
frame.setTitle("Algorithmizer");
frame.setSize(1080, 720);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(this);
}
@Override
protected void paintComponent( Graphics g ) {
super.paintComponent(g);
//drawing alg.A as a bar-graph by looping through it (deleted for simplicity)
}
}
当我在repaint()调用之前放入System.out.println(“1”)时,paintComponent()函数和System.out.println(“3”)中的System.out.println(“2”)在repaint()调用之后它只会打印: 1 3 1 3 1 3 ... 我也试过打印堆栈,也没有得到任何有用的东西。 算法完成后程序会重新绘制,但这对我没用。
答案 0 :(得分:0)
也许采取这样的方法。这将在Event Dispatch Thread的一个工作线程中进行所有计算和填充,然后调用done(),您可以在事件调度线程上进行GUI更新。
@Override
public void actionPerformed( ActionEvent e ) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
runAlg();
return null
}
@Override
protected void done() {
//any of you gui stuff here
}
}.execute();
}
}
public void runAlg(){
Algorithm alg = new Algorithm(Integer.parseInt(arraySizeModel.getValue().toString()), Integer.parseInt
(speedModel.getValue().toString()));
switch(Integer.parseInt(algSelectModel.getValue().toString())) {
case 1:
alg.alg1();
break;
case 2:
alg.alg2();
break;
case 3:
alg.alg3();
break;
case 4:
alg.alg4();
break;
case 5:
alg.alg5();
break;
}
}
答案 1 :(得分:0)
问题是它在算法完成之前不再重新绘制。
您的算法正在Event Dispatch Thread (EDT)
执行,这是GUI用于绘制自身的线程,因此GUI无法重新绘制,直到算法完成。
解决方案是为算法使用单独的线程。
执行此操作的一种方法是使用在单独的线程上执行的Swing Worker
,并允许您发布&#34;算法正在执行的结果。
阅读Concurrency上Swing教程中的部分以获取更多详细信息。本教程有一个Swing Worker示例。