0

У меня возникла проблема с обновлением gui как внутреннего состояния изменений моделирующей модели. Симулятор класса работает для определенного количества шагов. Каждый шаг изменяет внутреннее состояние компьютера. Затем Gui получает уведомление и должен перекрасить его графическое представление компьютера, включая текст для текущего состояния. К сожалению, в приведенных ниже классах gui обновляет изменения только после последнего шага запуска моделирования. Я использую наблюдатель (компьютер) и наблюдаемый (GUICanvas) шаблон. Что я делаю неправильно, что графический интерфейс не перерисовывается на промежуточных этапах моделирования?Обновление java GUI как внутреннего состояния изменений модели

public class NwSim { 


    public NwSim() { 
    } 

    public static void main(String[] args) { 
     JFrame frame; 
     Simulator simulator = new Simulator();  
     canvas = new GUICanvas();   //create gui canvas, which paints guy computers 
     canvas.setBackground(Color.white); 
     contentPane.add(canvas, BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible(true); 
    simulator.simulate(); 
    } 
} 

//represents the controller in the simulation 
public class Simulator { 
List<Computer> computers; 
private int simulationSteps; 

public Simulator() 
    simulationSteps = 200; 
       computers = new ArrayList<Computer>(); 


    public void simulate() { 
     for(int step = 0; step < simulationSteps; step++) { 
     for(Computer computer : computers) { 
     computer.tick() 
    } 
    } 
    } 

    public Computer createComputer() { 
    Computer computer = new Computer(); 
    computers.add(computer) 
    } 
} 



public class Computer extends Observable { 

    public void tick { 
    ….. // update field state of the computer 
     if (state.stateChanged()) { 
      setChanged(); 
      notifyObservers(); //notify observer- gui canvas that the state of computer has changed and it is time to repaint guiComputers 

     } 
} 

public string getState() { 
return state; 
} 
} 

public class GUIComputer { 

private static final long serialVersionUID = 1L; 
private int width; 
private int height; 
private Image image; 
private Computer computer; 


public GUIComputer(int x, int y, Computer computer component, Image image) { 
    this.computer = computer; 
    setX(x); 
    setY(y); 
    this.image = image; 
    width = image.getWidth(null); 
    height = image.getHeight(null); 
} 


@Override 
public void drawGuiComputer(Graphics g){ 
     g.drawImage(image, getX(), getY(), null); 
     Graphics2D g2 = (Graphics2D)g; 
     g2.drawString(computer.getState().toString(), getX() + 20, getY() // repaint the state for each guiComputer taken from Computer 
       + height + 10); 
} 
} 

public class GUICanvas extends JPanel implements Observer { 

// 
private List<GUIComputer> guiComputers; 

public GUICanvas(Simulator simulator) { 
    this.guiComputers = new ArrayList<GUIComputer>(); 
    // create guy computers using method createGuiComputer below , code omitted 
} 

public createGuiComputer(Transferable transferable, Point dropPoint, Computer computer) { 
Image image = Toolkit.getDefaultToolkit().getImage("images/" + imageName); 
     Computer computer = simulator.createComputer(); 
         GUIComputer guiComputer = new GUIComputer(dropPoint.x, dropPoint.y, computer, image); 
         guiComputers.add(guiComputer); 
         guiComputer.addObserver(this); 

} 

    @Override 
    public void paintComponent(Graphics g) { 

     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D)g;  
      if (!GuiComputers.isEmpty()) { 
        for(GUIComputer guiComputer : guiComputers) { 
       // redraw guiComputer 
          guiComputer.drawGuiComputer(g); 
         } 
      } 
} 

    @Override 
    public void update(Observable o, Object o1) { 
    for(final GUIComputer guiComputer : guiComputers) { 
       if(guiComputer.getComputer().equals(o)) { 
        //if update requested by Computer object then update gui, redrawing all guiComputers 
        revalidate(); 
        repaint(); 
       } 
    } 
} 
} 
+2

Ваш код отступы беспорядок и ваш пример кода не компилируется. Это первая проблема. –

ответ

2

Вы вероятно привязывание диспетчеризации событий нити или EDT с длительными затратами времени немного коды, который работает на потоке событий:

public void simulate() { 
    for(int step = 0; step < simulationSteps; step++) { 
     for(Computer computer : computers) { 
     computer.tick() 
     } 
    } 
} 

Попробуйте использовать SwingWorker или другой фон чтобы решить эту проблему.

+0

Это была моя первая мысль, но вызов 'simulate()' находится в 'main()'. –

+0

@ RussellZahniser: Да, вы правы. В коде есть много кода, хотя это было исключено, поэтому я все еще подозреваю о параллелизме в выпуске Swing. –

1

Если у вас нет Thread.sleep() где-то в tick() или simulate(), который вы не показывали, симуляция должна запускаться почти мгновенно. Все вызовы repaint() будут объединены в одну перерисовку.

Edit:

Вот простой пример, в котором спорадические обновления Observable с на main() нити показаны в GUI наблюдения за ними:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Observable; 
import java.util.Observer; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Animation extends JPanel implements Observer { 
    Simulation simulation; 

    Animation(Simulation simulation) { 
     this.simulation = simulation; 
     setPreferredSize(new Dimension(200, 200)); 

     for(Blob blob : simulation.blobs) { 
      blob.addObserver(this); 
     } 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     Blob blob = (Blob)o; 
     repaint(blob.x - 12, blob.y - 12, 24, 24); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     for(Blob blob : simulation.blobs) { 
      g.setColor(blob.color); 
      g.fillOval(blob.x - 10, blob.y - 10, 20, 20); 
     } 
    } 

    public static void main(String[] args) { 
     Simulation simulation = new Simulation(); 

     JFrame frame = new JFrame(); 
     frame.getContentPane().add(new Animation(simulation)); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 

     simulation.simulate(); 
    } 
} 

class Simulation { 
    List<Blob> blobs = new ArrayList(); 

    Simulation() { 
     for(int i = 0; i < 20; ++i) { 
      blobs.add(new Blob()); 
     } 
    } 

    void simulate() { 
     while(true) { 
      try { 
       Thread.sleep(50); 
      } catch(InterruptedException e) { 
       return; 
      } 
      for(Blob blob : blobs) { 
       blob.tick(); 
      } 
     } 
    } 
} 

class Blob extends Observable { 
    int x = (int)(Math.random() * 180 + 10); 
    int y = (int)(Math.random() * 180 + 10); 
    float hue = (float)Math.random(); 
    Color color = Color.getHSBColor(hue, 1, 1); 

    void tick() { 
     if(Math.random() < 0.05) { 
      x += 4 * Math.random() - 2 + .5; 
      y += 4 * Math.random() - 2 + .5; 
      hue += Math.random() * .1 - .05; 
      hue -= Math.floor(hue); 

      color = Color.getHSBColor(hue, 1, 1); 
      setChanged(); 
      notifyObservers(); 
     } 
    } 
} 
+0

Спасибо Расселу и на воздушной подушке. В действительности проблема была вызвана нитями – Sharissa

+0

У меня на самом деле был Thread.sleep в моем коде раньше ... но мой метод симуляции находился внутри события действия для кнопки ... поэтому имитация() выполнялась внутри EDT, а не основного потока, что объясняет, почему GUI не обновлялся .... Добавление 1 дополнительного потока для запуска имитации() решило проблему, спасибо, ребята. – Sharissa

Смежные вопросы