您好我已经为模拟实现了一个MVC,并且当我遍历一组代理并更新它们在2D数组中的位置时,我正在使用JPanel绘制每个模拟周期。但是重绘方法对我来说无法正常工作,当我单击开始按钮一次时,JPanel应该自动保持刷新。但是,如果我一直点击开始按钮然后用代理的更新位置重新粉刷JPanel我做错了什么?
GUI Class:
public class MainGUI implements Runnable {
public static void main(String[] args) {
EventQueue.invokeLater(new MainGUI());
}
@Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MainPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setSize(400, 400);
f.setVisible(true);
f.repaint();
}
class MainPanel extends JPanel {
public MainPanel() {
super(new BorderLayout());
Simulator model = new Simulator();
GridView view1 = new GridView(model);
Controller control = new Controller(model, view1);
JLabel label = new JLabel("Welcome to the ABM Simulation");
this.add(label, BorderLayout.NORTH);
this.add(view1, BorderLayout.CENTER);
this.add(control, BorderLayout.SOUTH);
}
}
}
View Class:
public class GridView extends JPanel {
private Simulator sim;
private int rows;
private int cols;
private Agent[][] current2DArray;
public GridView(Simulator sim) {
this.sim = sim;
this.rows = sim.getGrid().getRow();
this.cols = sim.getGrid().getColumn();
this.current2DArray = sim.getGrid().getGrid();
JPanel canvas = new JPanel();
canvas.setLayout(null);
canvas.setPreferredSize(new Dimension(rows, cols));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.GRAY);
for(Agent agent : sim.getAgents()) {
g.setColor(agent.getColor());
g.fill3DRect(agent.getLocation().getRow(), agent.getLocation().getCol(), 5, 5, true);
repaint();
}
}
public void drawAgents(Graphics g) {
g.setColor(Color.GRAY);
g.fillRect(0,0,rows,cols);
for(int row = 0; row < current2DArray.length; row++) {
for(int col = 0; col < current2DArray[row].length; col++) {
if(current2DArray[row][col] instanceof Cop) {
if(current2DArray[row][col].getState() == 1) {
g.setColor(Color.RED);
g.fill3DRect(row, col, 5, 5, true);
}
else if(current2DArray[row][col].getState() == 2) {
//no nothing
}
}
else if(current2DArray[row][col] instanceof Citizen) {
if(current2DArray[row][col].getState() == 3) {
g.setColor(Color.BLACK);
g.fill3DRect(row, col, 5, 5, true);
}
else if(current2DArray[row][col].getState() == 4) {
//no nothing
}
}
else if(current2DArray[row][col] == null) {
//if empty do nothing
}
}
}
}
}
public class Controller extends JPanel {
private Simulator sim;
private GridView view;
private JButton start = new JButton("Start");
public Controller(Simulator sim, GridView view) {
this.sim = sim;
this.view = view;
this.add(start);
start.addActionListener(new ButtonHandler());
}
private class ButtonHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand(); {
if("Start".equals(cmd)) {
sim.resumeSimulation();
}
}
}
}
}
答案 0 :(得分:0)
在每个模拟周期后调用JPanel上的repaint()
以重新绘制它。按下按钮会无意中触发此按钮。
因此,在模拟可以访问的某个位置创建对面板的引用,然后调用repaint()
方法,即myGridView.repaint()
。
答案 1 :(得分:0)
如果您想要一个恒定的帧速率,那么您可以设置Timer以强制您的面板重新绘制。
Swing对象通常会尽可能少地做,除非他们的组件或你告诉他们,并期望从那时起的合作会导致心痛。