gpt4 book ai didi

java - 如何设置该程序以匹配 MVC 设计模式

转载 作者:行者123 更新时间:2023-12-02 08:26:58 25 4
gpt4 key购买 nike

我相信我已经掌握了这个程序 - Game Of Life 的大部分 MVC 部分。但是我无法让 MouseListener 正常工作。我怎样才能改变这个匹配MVC设计模式?

查看

package lifepreparation;
import java.awt.Color;
import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;
import javax.swing.*;
import java.awt.event.MouseListener;

public class LifeView extends JFrame {
//Label used to house cells
private LifeModel[][] cellHouse;
private LifeModel model;

//Timer used to fire the next generation
private Timer timer;

//Generation counter - used to count the number of generations
private int generationCount = 0;
private JLabel generationLabel = new JLabel("Generation: 0");

//Declare action buttons
private JButton startB = new JButton("Start");
private JButton pauseB = new JButton("Pause");
private JButton clearB = new JButton("Clear");

//Slider to adjust the time interval between generations
private static final int minSpeed = 0;
private static final int maxSpeed = 1000;
private static final int speedMajorTicks = (maxSpeed-minSpeed)/5;
private static final int speedMinorTicks = (maxSpeed-minSpeed)/20;
JSlider generationS = new JSlider(minSpeed,maxSpeed);

//Identifies game status: false=pause, true=running
private boolean runStatus = false;

//Panel for the city
private JPanel panel;

public LifeView(int boardRow, int boardCol, LifeModel model) {
super("Game Of Life");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//**START Create labels to house cells, +2 more
cellHouse = new LifeModel[boardRow+2][boardCol+2];
for(int r = 0; r < boardRow+2; r++) {
for(int c = 0; c < boardCol+2; c++) {
cellHouse[r][c] = new LifeModel();
}
}
//--END Create Labels

//Panel to hold cell houses
panel = new JPanel(new GridLayout(boardRow, boardCol, 1, 1));
panel.setBackground(Color.BLACK);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

//Add cellHouses to the panel
for(int r = 1; r < boardRow+1; r++) {
for(int c = 1; c < boardCol+1; c++) {
panel.add(cellHouse[r][c]);
cellHouse[r][c].addNeighbor(cellHouse[r-1][c]); //Add to TOP ^
cellHouse[r][c].addNeighbor(cellHouse[r+1][c]); //Add to BOTTOM _
cellHouse[r][c].addNeighbor(cellHouse[r][c-1]); //Add to left <-
cellHouse[r][c].addNeighbor(cellHouse[r][c+1]); //Add to right ->
cellHouse[r][c].addNeighbor(cellHouse[r-1][c-1]); //Add to top left ^<-
cellHouse[r][c].addNeighbor(cellHouse[r-1][c+1]); //Add to top right ^->
cellHouse[r][c].addNeighbor(cellHouse[r+1][c-1]); //Add to bottom left _<-
cellHouse[r][c].addNeighbor(cellHouse[r+1][c+1]); //Add to bottom right _->
}
}

//Panel with cellHouses added to the container
add(panel, BorderLayout.CENTER);

//South Panel to hold buttons and widgets with extra features
JPanel panelBottom = new JPanel();

//buttonPanel to hold start, pause, clear features
JPanel buttonPanel = new JPanel();

buttonPanel.add(clearB);
pauseB.setEnabled(false);
buttonPanel.add(pauseB);
buttonPanel.add(startB);

//speedPanel to hold slider to adjust the time interval
JPanel speedPanel = new JPanel();
JLabel speedText = new JLabel("Set Speed:");
generationS.setMajorTickSpacing(speedMajorTicks);
generationS.setMinorTickSpacing(speedMinorTicks);
generationS.setPaintTicks(true);
// the labels for the Slider
Hashtable<Integer, JLabel> speedLabel = new Hashtable<Integer, JLabel>();
for(int i = 0; i <= maxSpeed; i++) {
speedLabel.put( new Integer( i * speedMajorTicks ), new JLabel("" + i) );
}
generationS.setLabelTable(speedLabel);
generationS.setPaintLabels(true);


generationLabel.setHorizontalAlignment(SwingConstants.CENTER);

speedPanel.add(speedText);
speedPanel.add(generationS);

panelBottom.add(buttonPanel);
panelBottom.add(speedPanel);
panelBottom.add(generationLabel);

// add bottom panel to the JFrame
add(panelBottom, BorderLayout.SOUTH);

// put the frame on
setLocation(20, 20);
pack();
setVisible(true);
}

//Action to take dependent on the action referenced by the JButton and Timer
public void startPauseClear(ActionEvent e) {
//Get action reference
Object o = e.getSource();

//Action reference is to clear
if(o == clearB) {
timer.stop(); //Stop the timer
runStatus = false; //Set game as not running
pauseB.setEnabled(false); //Disable the pause button
startB.setEnabled(true); //Enable the start button
//Remove/Clear all cells from the cellHouse
for(int r = 1; r < cellHouse.length -1; r++) {
for(int c = 1; c < cellHouse[r].length -1; c++) {
cellHouse[r][c].clear();
}
}
//Reset the generation count
generationCount = 0;
generationLabel.setText("Generation: 0");
return;
}
//Action reference is to pause
if(o == pauseB) {
timer.stop(); //Stop the timer
runStatus = false; //Set game as not running
pauseB.setEnabled(false); //Disable the pause button
startB.setEnabled(true); //Enable the start button
return;
}
//Action reference is to start
if(o == startB) {
pauseB.setEnabled(true); //Enable the pause button
startB.setEnabled(false); //Disable the start button
runStatus = true; //Set game as running
timer.setDelay(maxSpeed - generationS.getValue()); //Adjust the speed
timer.start();
return;
}

//If the action is set by timer, set speed
timer.setDelay(maxSpeed - generationS.getValue());

//If the game is not running, exit and do nothing more
if(!runStatus) return;

//Update generation count and display
++generationCount;
generationLabel.setText("Generation: " + generationCount);

//Check to see if the cell should be buried
for(int r = 0; r < cellHouse.length; r++) {
for(int c = 0; c < cellHouse[r].length; c++) {
cellHouse[r][c].checkGeneration();
}
}

//Update to the next generation
for(int r = 0; r < cellHouse.length; r++) {
for(int c = 0; c < cellHouse[r].length; c++) {
cellHouse[r][c].updateGeneration();
}
}
}
public void addActionListener(ActionListener e) {
clearB.addActionListener(e);
pauseB.addActionListener(e);
startB.addActionListener(e);
timer = new Timer(maxSpeed - generationS.getValue(), e);
}

}

Controller

package lifepreparation;    
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class LifeController {
//Run App
LifeModel model;
LifeView view;

//Constructor
public LifeController(LifeModel model, LifeView view) {
this.model = model;
this.view = view;

//Add Listeners
view.addActionListener(new LifeActionListener());
view.addMouseListener(new LifeMouseListener());
}

class LifeActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
view.startPauseClear(e);
}
}

class LifeMouseListener implements MouseListener {
public void mouseClicked(MouseEvent arg0) {
model.unselectCell();
}

//If the mouse is in a cellHouse while being pressed, cell becomes alive
public void mouseEntered(MouseEvent arg0) {
model.selectCells();
}

public void mouseExited(MouseEvent arg0) {

}

//If the mouse is clicked on a cellHouse, cell comes to life
public void mousePressed(MouseEvent arg0) {
model.selectACell();
}

//Set mouse as not being held anymore
public void mouseReleased(MouseEvent arg0) {
model.setMouseHold();
}
}
}

型号

package lifepreparation;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


//LifeModel to handle cell life and death algorithm
public class LifeModel extends JLabel {
//Cell Color: cell[0] = dead cell, cell[1] = live cell.
private static final Color[] color = {Color.LIGHT_GRAY, Color.GREEN};

//Size of cells
private static final int cellSize = 15;
private static final Dimension citySize = new Dimension(cellSize, cellSize);

//checks if the mouse is still pressed or not
private boolean mouseHold = false;

private int currentStatus, newStatus;
private int nbNeighbor;
private LifeModel[] Neighbor = new LifeModel[8];

LifeModel() {
currentStatus = newStatus = 0; //Currently Dead
setOpaque(true); //Show color
setBackground(color[0]); //Light Gray color
this.setPreferredSize(citySize); //Set the dimension of the board
}
//Add a neighbor
void addNeighbor(LifeModel n) {
Neighbor[nbNeighbor++] = n;
}

//Check to see if a cell should live or not
void checkGeneration() {
//Number of neighbors that are alive
int nbAlive = 0;

//Check the status of the neighbors
for(int i = 0; i < nbNeighbor; i++)
nbAlive += Neighbor[i].currentStatus;

//If status of cell is alive
if(currentStatus == 1) {
//Bury cell if it has less than two neighbors
if(nbAlive < 2)
newStatus = 0;
//Bury cell if it has more than three live neighbors
if(nbAlive > 3)
newStatus = 0;
}
else {
//Dead cells with three live neighbors get reborn
if(nbAlive == 3)
newStatus = 1;
}
}
//Switch to next generation
void updateGeneration() {
if(currentStatus != newStatus) { //Adjust color for the new generation
currentStatus = newStatus;
setBackground(color[currentStatus]);
}
}

//Bury all cells in the city
void clear() {
if(currentStatus == 1 || newStatus == 1) {
currentStatus = newStatus = 0;
setBackground(color[currentStatus]);
}
}




public void unselectCell() {
if(currentStatus == 1 || newStatus == 1) {
currentStatus = newStatus = 0;
setBackground(color[currentStatus]);
}
}

//If the mouse is in a cellHouse while being pressed, cell becomes alive
public void selectCells() {
if(mouseHold) {
currentStatus = newStatus = 1;
setBackground(color[1]);
}
}

//If the mouse is clicked on a cellHouse, cell comes to life
public void selectACell() {
mouseHold = true;
currentStatus = newStatus = 1;
setBackground(color[1]);
}

//Set mouse as not being held anymore
public void setMouseHold() {
mouseHold = false;
}

}

未实现 MVC 的程序

package lifepreparation;

import java.awt.Color;
import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;
import javax.swing.*;

public class LifeView extends JFrame implements ActionListener {

//Cell Color: cell[0] = dead cell, cell[1] = live cell.
private static final Color[] color = {Color.LIGHT_GRAY, Color.GREEN};

//Size of cells
private static final int cellSize = 15;
private static final Dimension citySize = new Dimension(cellSize, cellSize);

//Label used to house cells
private LifeLabel[][] cellHouse;

//Timer used to fire the next generation
private Timer timer;

//Generation counter - used to count the number of generations
private int generationCount = 0;
private JLabel generationLabel = new JLabel("Generation: 0");


//Declare default buttons
private JButton startB = new JButton("Start");
private JButton pauseB = new JButton("Pause");
private JButton clearB = new JButton("Clear");

//Slider to adjust the time interval between generations
private static final int minSpeed = 0;
private static final int maxSpeed = 1000;
private static final int speedMajorTicks = (maxSpeed-minSpeed)/5;
private static final int speedMinorTicks = (maxSpeed-minSpeed)/20;
JSlider generationS = new JSlider(minSpeed,maxSpeed);

//Identifies game status: false=pause, true=running
private boolean runStatus = false;

// if the mouse is down or not
private boolean mouseHold = false;

public LifeView(int boardRow, int boardCol) {
super("Game Of Life");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//**START Create labels to house cells, +2 more to calculate cells that are out of bounds
cellHouse = new LifeLabel[boardRow+2][boardCol+2];
for(int r = 0; r < boardRow+2; r++) {
for(int c = 0; c < boardCol+2; c++) {
cellHouse[r][c] = new LifeLabel();
}
}
//--END Create Labels

//Panel to hold cell houses
JPanel panel = new JPanel(new GridLayout(boardRow, boardCol, 1, 1));
panel.setBackground(Color.BLACK);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

//Add cellHouses to the panel
for(int r = 1; r < boardRow+1; r++) {
for(int c = 1; c < boardCol+1; c++) {
panel.add(cellHouse[r][c]);
cellHouse[r][c].addNeighbor(cellHouse[r-1][c]); //Add to TOP ^
cellHouse[r][c].addNeighbor(cellHouse[r+1][c]); //Add to BOTTOM _
cellHouse[r][c].addNeighbor(cellHouse[r][c-1]); //Add to left <-
cellHouse[r][c].addNeighbor(cellHouse[r][c+1]); //Add to right ->
cellHouse[r][c].addNeighbor(cellHouse[r-1][c-1]); //Add to top left ^<-
cellHouse[r][c].addNeighbor(cellHouse[r-1][c+1]); //Add to top right ^->
cellHouse[r][c].addNeighbor(cellHouse[r+1][c-1]); //Add to bottom left _<-
cellHouse[r][c].addNeighbor(cellHouse[r+1][c+1]); //Add to bottom right _->
}
}

//Panel with cellHouses added to the container
add(panel, BorderLayout.CENTER);

//South Panel to hold buttons and widgets with extra features
JPanel panelBottom = new JPanel();

//buttonPanel to hold start, pause, clear features
JPanel buttonPanel = new JPanel();
clearB.addActionListener(this);
buttonPanel.add(clearB);
pauseB.addActionListener(this);
pauseB.setEnabled(false);
buttonPanel.add(pauseB);
startB.addActionListener(this);
buttonPanel.add(startB);

//speedPanel to hold slider to adjust the time interval
JPanel speedPanel = new JPanel();
JLabel speedText = new JLabel("Set Speed:");
generationS.setMajorTickSpacing(speedMajorTicks);
generationS.setMinorTickSpacing(speedMinorTicks);
generationS.setPaintTicks(true);
// the labels for the Slider
Hashtable<Integer, JLabel> speedLabel = new Hashtable<Integer, JLabel>();
for(int i = 0; i <= maxSpeed; i++) {
speedLabel.put( new Integer( i * speedMajorTicks ), new JLabel("" + i) );
}
generationS.setLabelTable(speedLabel);
generationS.setPaintLabels(true);


generationLabel.setHorizontalAlignment(SwingConstants.CENTER);

speedPanel.add(speedText);
speedPanel.add(generationS);

panelBottom.add(buttonPanel);
panelBottom.add(speedPanel);
panelBottom.add(generationLabel);

// add bottom panel to the JFrame
add(panelBottom, BorderLayout.SOUTH);

// put the frame on
setLocation(20, 20);
pack();
setVisible(true);
// start the thread that run the cycles of life
timer = new Timer(maxSpeed - generationS.getValue(), this);
}

//Action to take dependent on the action referenced by the JButton and Timer
public void actionPerformed(ActionEvent e) {
//Get action reference
Object o = e.getSource();

//Action reference is to clear
if(o == clearB) {
timer.stop(); //Stop the timer
runStatus = false; //Set game as not running
pauseB.setEnabled(false); //Disable the pause button
startB.setEnabled(true); //Enable the start button
//Remove/Clear all cells from the cellHouse
for(int r = 1; r < cellHouse.length -1; r++) {
for(int c = 1; c < cellHouse[r].length -1; c++) {
cellHouse[r][c].clear();
}
}
//Reset the generation count
generationCount = 0;
generationLabel.setText("Generation: 0");
return;
}
//Action reference is to pause
if(o == pauseB) {
timer.stop(); //Stop the timer
runStatus = false; //Set game as not running
pauseB.setEnabled(false); //Disable the pause button
startB.setEnabled(true); //Enable the start button
return;
}
//Action reference is to start
if(o == startB) {
pauseB.setEnabled(true); //Enable the pause button
startB.setEnabled(false); //Disable the start button
runStatus = true; //Set game as running
timer.setDelay(maxSpeed - generationS.getValue()); //Adjust the speed
timer.start();
return;
}

//If the action is set by timer, set speed
timer.setDelay(maxSpeed - generationS.getValue());

//If the game is not running, exit and do nothing more
if(!runStatus) return;

//Update generation count and display
++generationCount;
generationLabel.setText("Generation: " + generationCount);

//Check to see if the cell should be buried
for(int r = 0; r < cellHouse.length; r++) {
for(int c = 0; c < cellHouse[r].length; c++) {
cellHouse[r][c].checkGeneration();
}
}

//Update to the next generation
for(int r = 0; r < cellHouse.length; r++) {
for(int c = 0; c < cellHouse[r].length; c++) {
cellHouse[r][c].updateGeneration();
}
}
}
//Run App
public static void main(String[] arg) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new LifeView(30, 50);
}
});
}

//LifeModel to handle cell life and death algorithm
class LifeLabel extends JLabel implements MouseListener {
private int currentGen, newGen;
private int nbNeighbor;
private LifeLabel[] Neighbor = new LifeLabel[8];

LifeLabel() {
currentGen = newGen = 0; //Currently Dead
setOpaque(true); //Show color
setBackground(color[0]); //Light Gray color
addMouseListener(this); //Add mouseListener
this.setPreferredSize(citySize); //Set the dimension of the board
}
//Add a neighbor
void addNeighbor(LifeLabel n) {
Neighbor[nbNeighbor++] = n;
}

//Check to see if a cell should live or not
void checkGeneration() {
//Number of neighbors that are alive
int nbAlive = 0;

//Check the status of the neighbors
for(int i = 0; i < nbNeighbor; i++)
nbAlive += Neighbor[i].currentGen;

//If status of cell is alive
if(currentGen == 1) {
//Bury cell if it has less than two neighbors
if(nbAlive < 2)
newGen = 0;
//Bury cell if it has more than three live neighbors
if(nbAlive > 3)
newGen = 0;
}
else {
//Dead cells with three live neighbors get reborn
if(nbAlive == 3)
newGen = 1;
}
}
//Switch to next generation
void updateGeneration() {
if(currentGen != newGen) { //Adjust color for the new generation
currentGen = newGen;
setBackground(color[currentGen]);
}
}

//Bury all cells in the city
void clear() {
if(currentGen == 1 || newGen == 1) {
currentGen = newGen = 0;
setBackground(color[currentGen]);
}
}

public void mouseClicked(MouseEvent arg0) {
if(currentGen == 1 || newGen == 1) {
currentGen = newGen = 0;
setBackground(color[currentGen]);
}
}

//If the mouse is in a cellHouse while being pressed, cell becomes alive
public void mouseEntered(MouseEvent arg0) {
if(mouseHold) {
currentGen = newGen = 1;
setBackground(color[1]);
}
}

public void mouseExited(MouseEvent arg0) {

}

//If the mouse is clicked on a cellHouse, cell comes to life
public void mousePressed(MouseEvent arg0) {
mouseHold = true;
currentGen = newGen = 1;
setBackground(color[1]);
}

//Set mouse as not being held anymore
public void mouseReleased(MouseEvent arg0) {
mouseHold = false;
}
}
}

最佳答案

你的代码太难理解了,但我已经在 swing 中使用 mvc 做了一个应用程序。

我的建议是在主类中有这样的东西:

    MainModel      model      = new MainModel();
MainView view = new MainView(model);
MainController controller = new MainController(model, view);

您的 Controller 没问题。

View 看起来不错,但您应该为clearB、startB、pauseB 提供单独的addActionListener 方法(也许这就是问题所在)。

模型是大脑应该在的地方。不要扩展 JLabel,根本没有意义。

希望这有帮助。

关于java - 如何设置该程序以匹配 MVC 设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4300928/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com