如何在Java中的for循环中的每个update()之后强制重绘()?

时间:2014-06-27 09:46:02

标签: java awt

我写过一个小型的,基本的万花筒式程序,应该在六个不同的点和不同的方向逐渐绘制相同的模式(随着时间的推移)。

为此,我创建了一个数组来存储每个像素的颜色(它的初始颜色是黑色,用数字0表示),然后数组中的6个起始点的颜色变为绿色(由数字1代表)。这些点应该出现在屏幕上,然后根据前面的6个点来显示。进一步创造了6个点。然后应显示更新的屏幕。重复,重复,重复......

我的问题是,在绘制屏幕之前,所有针对新像素的更新都在执行。我已经检查了一些其他帖子和网络教程等,并收集AWT是足够的,以避免浪费时间重新绘制微小的变化。似乎还有一些名为paintManager的东西。我相信问题是我在for循环中重新绘制。我发现这非常令人沮丧,因为在我看来,这应该是一件简单的事情。确实有一种简单的方法来说服java以我想要的方式描绘这些微小的变化吗?

我在下面全部包含了代码:

package paranoid;

import javax.swing.JFrame;

public class MasterFrame {

    public static void main(String[] args) {
            // TODO Auto-generated method stub
    new MasterFrame();
    }


    public MasterFrame(){
        JFrame f = new JFrame();
        f.setTitle("Kaleidoscope");
        f.add(new Trip2());
        f.setSize(500,300);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        f.setResizable(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

}

和...

package paranoid;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;


public class Trip2 extends JPanel {

    private static final long serialVersionUID = 1L;

    private int xmin = 0,
                xmax = 499,
                ymin = 0,
                ymax = 279;
    private int x = 120;
    private int y = 80;
    private int dx = 1;
    private int dy = 1;
    private int temp = 0;
    private int update_counter = 0;
    private int repaint_counter = 0;
    private int x_pos[] = new int[6];
    private int y_pos[] = new int[6];
    private int screen[][] = new int[500][280];


    public Trip2() {

        initialisation();
        for(int i = 0; i < 5000; i++)
        {
            update();
            System.out.println("Just returned from update()");

            repaint();                                          //This repaint is not being activated until all updates 
            System.out.println("Just returned from paint()");   //have been completed, but I want a repaint after EVERY update.
        }
    }

    public void initialisation(){
        System.out.println("initialising...");
        x_pos[0] = x;
        y_pos[0] = y;

        x_pos[1] = xmax - x;
        y_pos[1] = y;

        x_pos[2] = x;
        y_pos[2] = ymax - y;

        x_pos[3] = xmax - x;
        y_pos[3] = ymax - y;

        x_pos[4] = (int)(xmax/2)-50;
        y_pos[4] = (int)(ymax/2);

        x_pos[5] = (int)(xmax/2)+50;
        y_pos[5] = (int)(ymax/2);

        for(int j = 0; j<280; j++){
            for(int i = 0; i<500; i++){
                screen[i][j] = 0;
            }
        }
    } //end of initialisation()

    public void update(){
        System.out.println("updating... for the "+update_counter+"th time");

        temp = (int)Math.floor(Math.random()*100);
        if(temp < 40){ // 40% chance that the direction is changed
            dx = (int)Math.floor(Math.random()*3);
            dy = (int)Math.floor(Math.random()*3);
            dx = dx - 1;
            dy = dy - 1;
        }


        x_pos[0] = x_pos[0]+dx;
        y_pos[0] = y_pos[0]+dy;

        x_pos[1] = x_pos[1]-dx;
        y_pos[1] = y_pos[1]+dy;

        x_pos[2] = x_pos[2]+dx;
        y_pos[2] = y_pos[2]-dy;

        x_pos[3] = x_pos[3]-dx;
        y_pos[3] = y_pos[3]-dy;

        x_pos[4] = x_pos[4]-dy;
        y_pos[4] = y_pos[4]-dx;

        x_pos[5] = x_pos[5]+dy;
        y_pos[5] = y_pos[5]+dx;

        for(int k = 0; k < 6; k++){
            if(x_pos[k] < 0){
                x_pos[k] = 0;
            }
            if(x_pos[k] > 499){
                x_pos[k] = 499;
            }
        }

        for(int k = 0; k < 6; k++){
            if(y_pos[k] < 0){
                y_pos[k] = 0;
            }
            if(y_pos[k] > 279){
                y_pos[k] = 279;
            }
        }


        screen[x_pos[0]][y_pos[0]] = 1;
        screen[x_pos[1]][y_pos[1]] = 1;
        screen[x_pos[2]][y_pos[2]] = 1;
        screen[x_pos[3]][y_pos[3]] = 1;
        screen[x_pos[4]][y_pos[4]] = 1;
        screen[x_pos[5]][y_pos[5]] = 1;

        update_counter = update_counter + 1;

    } //end of update()

    public void paint(Graphics g){
        System.out.println("painting screen for the "+repaint_counter+"th time");

            g.setColor(Color.BLACK);
            g.fillRect(xmin, ymin, xmax, ymax);

            for(int j = 0; j<280; j++){
                for(int i = 0; i<500; i++){
                    if(screen[i][j] == 0){
                        g.setColor(Color.BLACK);
                    } else 
                    {   
                        g.setColor(Color.GREEN);    
                    }
                    g.drawLine(i,j,i,j); //plots pixel
                }
            }


            try{
                Thread.sleep(100);
            }
            catch(InterruptedException e){  
            }

            repaint_counter = repaint_counter + 1;


    }//end of paint(Graphics g)

}//end of Trip2 class

2 个答案:

答案 0 :(得分:2)

发生了什么事情,你被困在你的for-loop中,直到它完成处理,然后你重新粉刷。您应该做的是,因为您正在扩展JPanel,所以您可以访问Component的paintComponent方法,该方法在您第一次绘制和重新绘制组件时调用。

喜欢这样

@Override
public void paintComponent(Graphics g) {

}

而不是你的

public void paint(Graphics g) {

}

但是,当您覆盖paintComponent时,您需要确保将其称为父亲的paintComponent

像这样:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
}

当我们在这里时,我们可以在你所有的绘画之前或之后调用你的Update方法,我在我的例子中选择了所有内容:

@Override
public void paintComponent(Graphics g) {
    update();
    super.paintComponent(g); // Super is used to reference the parent


    // All of your painting methodology


    repaint(); // Force the component to repaint so this gets called over and over.
}

务必删除for循环;当然,如果你想在绘图之前获得大量数据,你可以随时保留它。

如果你真的想要,你可以随时保留完全相同的代码,但遵循我上面所说的类似模式。

像这样:

public void paint(Graphics g) {
    update();


    // All of your painting methodology


    repaint(); // Force the component to repaint so this gets called over and over.
}

答案 1 :(得分:2)

这里的一个主要问题是你在paint方法中调用Thread.sleep() - 这不是一个好主意,因为它将停止在那段时间内进一步重新绘制你的应用程序。 (事件调度线程/绘图线程不得用于任何慢速操作)

您希望在此处实现的常规流程如下(可能比您需要的更详细):

  1. 创建一个包含所有数字变量的模型类,特别是您的数字(无UI代码)也会创建各种getter,以便UI稍后访问这些数字。
  2. 允许将此模型类传递给视图类(在您的情况下为Trip1)并设置为实例变量。
  3. 从主控制类创建一个新的线程或计时器,可根据需要定期调整您的型号/内部。
  4. 为模型上的更改创建一个侦听器interface。 (例如ModelChangedListener或类似的)
  5. 在模型中添加一个监听器列表 - 使用register方法只需将监听器添加到列表中。
  6. 如果对模型进行任何更改,即更新号码时,请对已注册的听众进行点击。
  7. 在您的主控制类中,注册一个只调用此模型的侦听器: trip2Panel.repaint();

  8. 在面板的paint()方法中......只需绘制当前的模型。

  9. 发布完整代码:

    package paranoid;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.Timer;
    
    public class MasterFrame {
    
    public static void main(String[] args) {
            // TODO Auto-generated method stub
    new MasterFrame();
    }
    
    
    public MasterFrame(){
        JFrame f = new JFrame();
        f.setTitle("Kaleidoscope");
        final Trip2 trip2UI = new Trip2();
        final TripModel model = new TripModel();
        model.update();
        Timer timer = new Timer(1, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.update();
            }
        });
        timer.setRepeats(true);
        timer.start();
    
        model.addListener(new TripModelListener() {
            @Override
            public void modelChanged() {
                trip2UI.repaint();
            }
        });
        trip2UI.setModel(model);
    
        f.add(trip2UI);
        f.setSize(500,300);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        f.setResizable(false);
    
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
        }
    }
    

    TripModelListener

    package paranoid;
    
    public interface TripModelListener {
        void modelChanged();
    }
    

    Trip2(ui)

    package paranoid;
    
    import java.awt.Color;
    import java.awt.Graphics;
    
    import javax.swing.JPanel;
    
    
    public class Trip2 extends JPanel {
    
    private static final long serialVersionUID = 1L;
    
    private TripModel model;
    
    public void paint(Graphics g){
    
        g.setColor(Color.BLACK);
        g.fillRect(model.getXMin(), model.getYMin(), model.getXMax(), model.getYMax());
    
        for (int j = 0; j < 280; j++) {
            for (int i = 0; i < 500; i++) {
                if (model.getScreen()[i][j] == 0) {
                    g.setColor(Color.BLACK);
                } else {
                    g.setColor(Color.GREEN);
                }
                g.drawLine(i, j, i, j); //plots pixel
            }
        }
    }
    
    public void setModel(TripModel model) {
        this.model = model;
    }
    
    }//en
    

    旅行模式

    package paranoid;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class TripModel {
    private List<TripModelListener> listeners = new CopyOnWriteArrayList<TripModelListener>();
    private int xmin = 0,
                xmax = 499,
                ymin = 0,
                ymax = 279;
    private int x = 120;
    private int y = 80;
    private int dx = 1;
    private int dy = 1;
    private int temp = 0;
    private int update_counter = 0;
    private int x_pos[] = new int[6];
    private int y_pos[] = new int[6];
    private int screen[][] = new int[500][280];
    
    
    public TripModel() {
    
        initialisation();
    }
    
    public void initialisation(){
        System.out.println("initialising...");
        x_pos[0] = x;
        y_pos[0] = y;
    
        x_pos[1] = xmax - x;
        y_pos[1] = y;
    
        x_pos[2] = x;
        y_pos[2] = ymax - y;
    
        x_pos[3] = xmax - x;
        y_pos[3] = ymax - y;
    
        x_pos[4] = (int)(xmax/2)-50;
        y_pos[4] = (int)(ymax/2);
    
        x_pos[5] = (int)(xmax/2)+50;
        y_pos[5] = (int)(ymax/2);
    
        for(int j = 0; j<280; j++){
            for(int i = 0; i<500; i++){
                screen[i][j] = 0;
            }
        }
    } //end of initialisation()
    
    public void update(){
        //System.out.println("updating... for the "+update_counter+"th time");
    
        temp = (int)Math.floor(Math.random()*100);
        if(temp < 40){ // 40% chance that the direction is changed
            dx = (int)Math.floor(Math.random()*3);
            dy = (int)Math.floor(Math.random()*3);
            dx = dx - 1;
            dy = dy - 1;
        }
    
    
        x_pos[0] = x_pos[0]+dx;
        y_pos[0] = y_pos[0]+dy;
    
        x_pos[1] = x_pos[1]-dx;
        y_pos[1] = y_pos[1]+dy;
    
        x_pos[2] = x_pos[2]+dx;
        y_pos[2] = y_pos[2]-dy;
    
        x_pos[3] = x_pos[3]-dx;
        y_pos[3] = y_pos[3]-dy;
    
        x_pos[4] = x_pos[4]-dy;
        y_pos[4] = y_pos[4]-dx;
    
        x_pos[5] = x_pos[5]+dy;
        y_pos[5] = y_pos[5]+dx;
    
        for(int k = 0; k < 6; k++){
            if(x_pos[k] < 0){
                x_pos[k] = 0;
            }
            if(x_pos[k] > 499){
                x_pos[k] = 499;
            }
        }
    
        for(int k = 0; k < 6; k++){
            if(y_pos[k] < 0){
                y_pos[k] = 0;
            }
            if(y_pos[k] > 279){
                y_pos[k] = 279;
            }
        }
    
    
        screen[x_pos[0]][y_pos[0]] = 1;
        screen[x_pos[1]][y_pos[1]] = 1;
        screen[x_pos[2]][y_pos[2]] = 1;
        screen[x_pos[3]][y_pos[3]] = 1;
        screen[x_pos[4]][y_pos[4]] = 1;
        screen[x_pos[5]][y_pos[5]] = 1;
    
        update_counter = update_counter + 1;
        fireModelChangedListener();
    } //end of update()
    
    private void fireModelChangedListener() {
        for (TripModelListener listener : listeners) {
            listener.modelChanged();
        }
    }
    
    
    public int getXMin() {
        return xmin;
    }
    
    public int getYMin() {
        return ymin;
    }
    
    public int getYmin() {
        return ymin;
    }
    
    public void setYmin(int ymin) {
        this.ymin = ymin;
    }
    
    public int getXMax() {
        return xmax;
    }
    
    public int getXmax() {
        return xmax;
    }
    
    public void setXmax(int xmax) {
        this.xmax = xmax;
    }
    
    public int getYMax() {
        return ymax;
    }
    
    public int[][] getScreen() {
        return screen;
    }
    
    public void addListener( TripModelListener listener) {
        listeners.add(listener);
    }
    }