我在更新gui时遇到问题,因为模拟模型的内部状态发生了变化。类模拟器运行一定数量的步骤。每一步计算机的内部状态都会发生变化。 Gui然后得到通知,并应重新绘制其计算机的图形表示,包括当前状态的文本。不幸的是,对于下面详述的类,gui仅在模拟运行的最后一步之后更新更改。我正在使用观察者(计算机)和可观察(GUICanvas)模式。我做错了什么,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();
}
}
}
}
答案 0 :(得分:2)
您可能会占用事件调度线程或EDT,但运行时间过长会占用事件线程上运行的一些代码:
public void simulate() {
for(int step = 0; step < simulationSteps; step++) {
for(Computer computer : computers) {
computer.tick()
}
}
}
尝试使用SwingWorker或其他后台线程来解决此问题。
答案 1 :(得分:1)
除非您在Thread.sleep()
或tick()
某处未显示simulate()
,否则模拟应该立即运行。然后,所有对repaint()的调用将合并为一个重绘。
修改强>
这是一个简单的例子,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();
}
}
}