重绘问题

时间:2010-06-03 18:45:43

标签: java swing repaint

我在方法 move 中重绘了一个问题。我不知道该怎么做,代码在下面

import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
import java.lang.*;

public class bbb extends JPanel
{
    public Stack<Integer> stacks[];
    public JButton auto, jugar, nojugar;
    public JButton ok, ok2;
    public JLabel info = new JLabel("Numero de Discos: ");
    public JLabel instruc = new JLabel("Presiona la base de las torres para mover las fichas");
    public JLabel instruc2 = new JLabel("No puedes poner una pieza grande sobre una pequenia!");
    public JComboBox numeros = new JComboBox();
    public JComboBox velocidad = new JComboBox();
    public boolean seguir = false, parar = false, primera = true;
    public int n1, n2, n3;
    public int click1 = 0;
    public int opcion = 1, tiempo = 50;
    public int op = 1, continuar = 0, cont = 0;
    public int piezas = 0;
    public int posx, posy;
    public int no;

    public bbb() throws IOException
    {
        stacks = new Stack[3];
        stacks[0] = new Stack<Integer>();
        stacks[1] = new Stack<Integer>();
        stacks[2] = new Stack<Integer>();
        setPreferredSize(new Dimension(1366, 768));
        ok = new JButton("OK");
        ok.setBounds(new Rectangle(270, 50, 70, 25));
        ok.addActionListener(new okiz());
        ok2 = new JButton("OK");
        ok2.setBounds(new Rectangle(270, 50, 70, 25));
        ok2.addActionListener(new vel());
        add(ok2);
        ok2.setVisible(false);
        auto = new JButton("Automatico");
        auto.setBounds(new Rectangle(50, 80, 100, 25));
        auto.addActionListener(new a());
        jugar = new JButton("PLAY");
        jugar.setBounds(new Rectangle(100, 100, 70, 25));
        jugar.addActionListener(new play());
        nojugar = new JButton("PAUSE");
        nojugar.setBounds(new Rectangle(100, 150, 70, 25));
        nojugar.addActionListener(new stop());
        setLayout(null);
        info.setBounds(new Rectangle(50, 50, 170, 25));
        info.setForeground(Color.white);
        instruc.setBounds(new Rectangle(970, 50, 570, 25));
        instruc.setForeground(Color.white);
        instruc2.setBounds(new Rectangle(970, 70, 570, 25));
        instruc2.setForeground(Color.white);
        add(instruc);
        add(instruc2);
        add(jugar);
        add(nojugar);
        jugar.setVisible(false);
        nojugar.setVisible(false);
        add(info);
        info.setVisible(false);
        add(ok);
        ok.setVisible(false);
        add(auto);

        numeros.setBounds(new Rectangle(210, 50, 50, 25));
        numeros.addItem(1);
        numeros.addItem(2);
        numeros.addItem(3);
        numeros.addItem(4);
        numeros.addItem(5);
        numeros.addItem(6);
        numeros.addItem(7);
        numeros.addItem(8);
        numeros.addItem(9);
        numeros.addItem(10);
        add(numeros);
        numeros.setVisible(false);

        velocidad.setBounds(new Rectangle(150, 50, 100, 25));
        velocidad.addItem("Lenta");
        velocidad.addItem("Intermedia");
        velocidad.addItem("Rapida");
        add(velocidad);
        velocidad.setVisible(false);
    }

    public void Mover(int origen, int destino)
    {
        for (int i = 0; i < 3; i++)
        {
            System.out.print("stack " + i + ": ");
            for (int n : stacks[i])
            {
                System.out.print(n + ";");
            }
            System.out.println("");
        }
        System.out.println("de <" + origen + "> a <" + destino + ">");
        stacks[destino].push(stacks[origen].pop());
        System.out.println("");
        this.validate();
        this.repaint();
    }

    public void hanoi(int origen, int destino, int cuantas)
    {
        while (parar)
        {
        }
        if (cuantas <= 1)
        {
            Mover(origen, destino);
        }
        else
        {
            hanoi(origen, 3 - (origen + destino), cuantas - 1);
            Mover(origen, destino);
            hanoi(3 - (origen + destino), destino, cuantas - 1);
        }
    }

    public void paintComponent(Graphics g)
    {
        ImageIcon fondo = new ImageIcon("fondo.jpg");
        g.drawImage(fondo.getImage(), 0, 0, 1366, 768, null);

        g.setColor(new Color((int) (Math.random() * 254),
            (int) (Math.random() * 255),
            (int) (Math.random() * 255)));
        g.fillRect(0, 0, 100, 100);

        g.setColor(Color.white);
        g.fillRect(150, 600, 250, 25);
        g.fillRect(550, 600, 250, 25);
        g.fillRect(950, 600, 250, 25);
        g.setColor(Color.red);
        g.fillRect(270, 325, 10, 275);
        g.fillRect(270 + 400, 325, 10, 275);
        g.fillRect(270 + 800, 325, 10, 275);

        int x, y, top = 0;
        g.setColor(Color.yellow);

        x = 150;
        y = 580;
        for (int ii : stacks[0])
        {
            g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
        }

        x = 550;
        y = 580;
        for (int ii : stacks[1])
        {
            g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
        }

        x = 950;
        y = 580;
        for (int ii : stacks[2])
        {
            g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
        }

        System.out.println("ENTRO");

        setOpaque(false);
    }

    private class play implements ActionListener //manual 
    {
        public void actionPerformed(ActionEvent algo)
        {
            parar = false;
            if (primera = true)
            {
                hanoi(0, 2, no);
                primera = false;
            }
        }
    }

    private class stop implements ActionListener //manual 
    {
        public void actionPerformed(ActionEvent algo)
        {
            parar = true;
        }
    }

    private class vel implements ActionListener //manual 
    {
        public void actionPerformed(ActionEvent algo)
        {
            if (velocidad.getSelectedItem() == "Lenta")
            {
                tiempo = 150;
            }
            else if (velocidad.getSelectedItem() == "Intermedia")
            {
                tiempo = 75;
            }
            else
            {
                tiempo = 50;
            }
            ok2.setVisible(false);
            jugar.setVisible(true);
            nojugar.setVisible(true);
        }
    }

    private class a implements ActionListener //auto 
    {
        public void actionPerformed(ActionEvent algo)
        {
            auto.setVisible(false);
            info.setVisible(true);
            numeros.setVisible(true);
            ok.setVisible(true);
            op = 3;
        }
    }

    private class okiz implements ActionListener //ok
    {
        public void actionPerformed(ActionEvent algo)
        {
            no = Integer.parseInt(numeros.getSelectedItem().toString());
            piezas = no;
            if (no > 0 && no < 11)
            {
                info.setVisible(false);
                numeros.setVisible(false);
                ok.setVisible(false);
                for (int i = no; i > 0; i--)
                {
                    stacks[0].push(i);
                }
                opcion = 2;
                if (op == 3)
                {
                    info.setText("Velocidad: ");
                    info.setVisible(true);
                    velocidad.setVisible(true);
                    ok2.setVisible(true);
                }
            }
            else
            {
            }
            repaint();
        }
    }
}

调用一个类的另一个类的代码如下:

import java.awt.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.*;
import java.awt.event.*;

public class aaa extends JPanel 
{        
    private ImageIcon Background;
    private JLabel fondo;

    public static void main(String[] args) throws IOException 
    {
        JFrame.setDefaultLookAndFeelDecorated(true);
        final JPanel cp = new JPanel(new BorderLayout());
        JFrame frame = new JFrame ("Torres de Hanoi");

        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setSize(550,550);
        frame.setVisible(true);

        bbb panel = new bbb();

        frame.getContentPane().add(panel);

        frame.pack();
        frame.setVisible(true);
    }
}

1 个答案:

答案 0 :(得分:3)

假设您在println语句中看到了进度但未在屏幕上看到进度,这是因为对重绘的调用不是同步的。 Swing有一个特殊的线程来处理UI - 称为Event Dispatch Thread。对重绘的调用由该线程处理,但是异步 - 在该线程上调度的所有当前事件都已处理完毕后。

当你在actionPerformed中调用hanoi时,这是在同一个UI线程上完成的。会发生什么事情,直到你的递归完全完成后,repaint()调用才会排队。一旦递归完成(并且所有堆栈都已在模型中移动),UI线程将处理所有repaint()请求,绘制 - 我认为 - 最终状态。

您需要做的是将模型处理分离为单独的工作线程。在每个递归步骤中,发出一个repaint()调用并休眠几百毫秒。这将允许UI线程重新绘制模型的当前状态,并让用户实际跟踪进度。