将java GUI更新为模型更改的内部状态
我在更新gui时出现问题,因为模拟模型更改的内部状态。类模拟器运行一定数量的步骤。每一步计算机的内部状态都会改变。桂然后得到通知,并应重新绘制其计算机的图形表示,包括当前状态的文本。不幸的是,对于下面详述的类,gui只会在仿真运行的最后一步之后更新更改。我使用观察者(计算机)和可观察(GUICanvas)模式。我做错了什么,GUI不会在模拟的中间步骤重绘?将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();
}
}
}
}
你很可能会占用事件调度线程或EDT与消费是在事件线程上运行的代码位长的运行时间:
public void simulate() {
for(int step = 0; step < simulationSteps; step++) {
for(Computer computer : computers) {
computer.tick()
}
}
}
尝试使用SwingWorker或其他背景线程来解决这个问题。
这也是我的第一个想法,但对'simulate()'的调用在'main()'中。 – 2012-02-25 03:39:11
@RussellZahniser:是的,你说得对。虽然这个代码被遗漏了,但代码还是很多的,所以我仍然怀疑Swing问题的并发性。 – 2012-02-25 03:47:42
除非您有Thread.sleep()
的某个地方在tick()
或simulate()
中没有显示,否则仿真应该几乎立即运行。所有的repaint()调用都将被合并为一个重绘对象。
编辑:
这里有一个简单的例子,其中零星更新Observable
S于该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();
}
}
}
你的代码缩进是一个烂摊子,你的代码示例不编译。这是第一个问题。 – 2012-02-24 20:06:46