- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我相信我已经掌握了这个程序 - 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/
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
.NET 框架:4.5.1 我在 Blend for visual studio 2015 中遇到一个奇怪的错误,我找不到它的来源。 如果我在 VS 中打开我的 WPF 解决方案,它会加载并运行良好。
我经常遇到这样的问题,与 Hierarchical RESTful URL design 非常相似 假设该服务仅提供用户上传文档。 POST, GET /accounts PUT, DELETE /a
在 Rails 应用程序中,我使用 devise 来管理我的用户,而我用来销毁 session 的链接不再有效。它正在工作,现在我添加了事件管理员,但没有。 我的链接是 :delete, :clas
我已经坚持了超过 24 小时,试图按照此处发布的其他解决方案进行操作,但我无法使其正常工作。我是 Rails 新手,需要帮助! 我想让我的/users/edit 页面正常工作,以便我可以简单地更改用户
Devise 在以下情况下不会使用户超时: 用户登录,关闭选项卡,然后在超时 + X 分钟内重新访问该 URL。用户仍处于登录状态。 如果选项卡已打开并且稍后刷新/单击,则超时可以正常工作。这意味着
我想使用这样的 slider 我希望该 slider 根据提供给它的值进行相应调整。到目前为止,我只能应用具有渐变效果的背景,但无法获得这种效果。请通过提供样式代码来帮助我。
您应该为每种方法创建一个请求/响应对象,还是应该为每个服务创建一个? 如果我在所有方法中使用它,我的服务请求对象中将只有 5 个不同的东西,因为我对几乎所有方法使用相同的输入。 响应对象将只有一个字典
我正在尝试在 REST 中对实体的附件进行建模。假设一个缺陷实体可以附加多个附件。每个附件都有描述和一些其他属性(上次修改时间、文件大小...)。附件本身是任何格式的文件(jpeg、doc ...)
我有以下表格: Blogs { BlogName } BlogPosts { BlogName, PostTitle } 博客文章同时建模一个实体和一个关系,根据 6nf(根据第三个宣言)这是无效的。
如果 A 类与 B、C 和 D 类中的每一个都有唯一的交互,那么交互的代码应该在 A 中还是在 B、C 和 D 中? 我正在编写一个小游戏,其中许多对象可以与其他对象进行独特的交互。例如,EMP点击
关于如何记住我与 Omniauth 一起工作似乎有些困惑。 根据这个wiki ,您需要在 OmniauthCallbacksController 中包含以下内容: remember_me(user)
设计问题: 使用 非线程安全 组件(集合,API,...)在/带有 多线程成分 ... 例子 : 组件 1 :多线程套接字服务器谁向消息处理程序发送消息... 组件 2 :非线程安全 消息处理程序 谁
我们目前正在设计一个 RESTful 应用程序。我们决定使用 XML 作为我们的基本表示。 我有以下关于在 XML 中设计/建模应用程序数据的问题。 在 XML 中进行数据建模的方法有哪些?从头开始然
我正在设计一个新的 XSD 来从业务合作伙伴那里获取积分信息。对于每笔交易,合作伙伴必须提供至少一种积分类型的积分值。我有以下几点:
设计支持多个版本的 API 的最佳方法是什么。我如何确保即使我的数据架构发生更改(微小更改),我的 api 的使用者也不会受到影响?任何引用架构、指南都非常有用。 最佳答案 Mark Nottingh
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
我想用 php 创建一个网站,其工作方式与 https://www.bitcoins.lc/ 相同。确实,就每个页面上具有相同布局但内容会随着您更改链接/页面而改变而言,我如何在 php 中使用lay
我有一个关于编写 Swing UI 的问题。如果我想制作一个带有某些选项的软件,例如在第一个框架上,我有三个按钮(新建、选项、退出)。 现在,如果用户单击新按钮,我想将框架中的整个内容更改为其他内容。
我正在尝试找出并学习将应用程序拥有的一堆Docker容器移至Kubernetes的模式和最佳实践。诸如Pod设计,服务,部署之类的东西。例如,我可以创建一个其中包含单个Web和应用程序容器的Pod,但
我是一名优秀的程序员,十分优秀!