- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在制作测验申请。当我在 View 内按下按键时,模型会通过 Controller 进行更新。但模型中的函数首先被调用 1 次。下次我按某个键时 2 次,下次按 3 次,...等等。
我完全不知道这是怎么发生的。我尝试过调试它,但没有从多个地方调用它。仅来自 1 个地方。这几乎就像关键事件堆积起来并不断调用该方法。
这是我的多个类的代码。
获取关键事件的测验 View :
/**
* This class will show the questions and react on the keyboard events
* @author Matthias Claes
*
*/
public class QuizView extends JPanel implements View {
private Observable $model;
private Controller $controller;
private Question $question;
private boolean $isPressed; /* To check if we already listened to a key press event */
public QuizView(Observable model, Controller controller){
setFocusable(true);
$model = model;
if (controller == null)
$controller = new QuizController(model);
else
$controller = controller;
$question = null;
$isPressed = false;
/* Add a keylistener for every team */
addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
int teamSize; /* team size*/
teamSize = ((QuizModel) getModel()).getTeams().size();
if (Character.getNumericValue(e.getKeyChar()) <= teamSize) { /* If you pressed a number under the teamsize we listen to it, and there hasn't been pressed before */
buttonPressed(Character.getNumericValue(e.getKeyChar()));
// Else ignore the key stroke
}
}
});
}
/**
* If a button gets pressed we call this function
* @param team the team that pressed their button
*/
protected void buttonPressed(int team) {
/* Check if a button is pressed */
if(((QuizModel) getModel()).getTeamPressed() > 0)
$isPressed = true;
else
$isPressed = false;
/* If there hasn't been pressed yet and the question is not null */
if(!$isPressed && $question != null){
minimizeFrame(); /* Minimize the frame */
/* If this question has a media path we need to pause the audio/video, we also check if the user has installed vlcplayer and selected the right path */
if($question.getMediaPath() != null && QuizSoftwareModel.$vlcPath != null)
((QuizController)getController()).pause(); /* Pause the video */
/* Give a pop up message to the admin that a team has pushed their button */
((QuizController)getController()).showScoreView(team);
}
}
public void update(Observable arg0, Object arg1) {
$question = (Question) arg1;
System.out.println("CALLED");
if(((QuizModel) getModel()).getMaximize()) /* Only maximize the JFrame when needed */
maximizeFrame(); /* Maximize the frame first */
repaint();
}
/**
* Maximize the parent JFrame so the teams can see the question
*/
protected void maximizeFrame() {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setState(JFrame.MAXIMIZED_BOTH);
}
/**
* Minimize the parent JFrame so the teams can't see the question anymore
*/
protected void minimizeFrame() {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setState(JFrame.ICONIFIED);
}
该 View 显示一个弹出窗口,其中有一个按钮可以转到下一个问题或在答案错误时重播同一问题。按下恢复按钮就会产生问题。
public class GiveScoreView extends JFrame implements View {
Observable $model;
Controller $controller;
private Question $question; /* Saves the question that is passed by the update */
/*GUI elements */
ArrayList<JLabel> $answerLabels;
ArrayList<JCheckBox> $checkBoxes;
JLabel $questionLabel;
JLabel $teamPressedLabel;
/* 2 buttons to resume/end the question */
JButton $resumeButton;
JButton $calculateButton;
public GiveScoreView(Observable model, Controller controller) {
setModel(model);
setController(controller);
$answerLabels = new ArrayList<JLabel>();
$checkBoxes = new ArrayList<JCheckBox>();
$questionLabel = new JLabel();
$teamPressedLabel = new JLabel();
$resumeButton = new JButton("Resume question"); /* TODO messagebundle */
$calculateButton = new JButton("Calculate score"); /* TODO messagebundle */
initializeFrame();
}
/**
* Initializes the frame
*/
private void initializeFrame() {
setTitle("Give a score to the teams"); /* TODO languagebundle, Change the title of the frame */
getContentPane().setLayout(new GridBagLayout());/* Set the layout to gridbaglayout */
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
pack();
setVisible(false); /* Don't display it on default */
}
@Override
public void update(Observable arg0, Object arg1) {
$question = (Question) arg1;
/* Now we need to display this frame */
if(((QuizModel) getModel()).getDisplayScoreView()){
$teamPressedLabel.setText("Team " + Integer.toString(((QuizModel) getModel()).getTeamPressed()) + " is ready to answer!"); /* TODO messagebundle */
$teamPressedLabel.setFont(new Font("Serif", Font.PLAIN, 34)); /* Change the font */
displayScoreView();
setVisible(true); /* Now display the JFrame */
}
}
private void displayScoreView() {
Multipleanswer multipleanswerQuestion; /* a multiple answer question to display the multipleanswer questions */
Multiplechoice multiplechoiceQuestion; /* a multiple choice question to display the multiplechoice questions */
ArrayList<String> answers = null;
GridBagConstraints c = new GridBagConstraints();
/* Set the position of the JFrame so it's centered */
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
// Determine the new location of the window
int w = getSize().width;
int h = getSize().height;
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 2;
int i = 0;
// Move the window
setLocation(x - 150, y - 150);
/* Set size */
setSize(550, 300);
/* If the question isn't empty */
if (!($question == null)) {
c.anchor = GridBagConstraints.NORTHWEST;
$questionLabel.setText($question.getQuestion()); /* Set the text of the JLabel to the question itself */
$questionLabel.setFont(new Font("Serif", Font.PLAIN, 26)); /* Change the font */
getContentPane().add($teamPressedLabel,c); /* Add the label to the JFrame, the team that has pressed it's button */
c.weighty = 1.0;
/* Display the question under the team pressed text */
c.gridx = 0;
c.gridy = 1;
getContentPane().add($questionLabel,c); /* Add the label to the JFrame, the question itself */
/* If the type of the question is multipleanswer */
if ($question.getType() == QuestionType.MULTIPLEANSWER) {
/* Cast it to multipleanswer question */
multipleanswerQuestion = (Multipleanswer) $question;
/* Get the answers */
answers = multipleanswerQuestion.getAnswers();
} else if ($question.getType() == QuestionType.MULTIPLECHOICE) {
/* Cast it to multiplechoice question */
multiplechoiceQuestion = (Multiplechoice) $question;
/* Get the answers */
answers = multiplechoiceQuestion.getAnswers();
}
/* Speed questions don't show answers so we only display answers if it's not a speed question */
if ($question.getType() != QuestionType.SPEED) {
/* Make a JLabel and JCheckBox for each answer */
for (i = 0; i < answers.size(); i++) {
$answerLabels.add(new JLabel(answers.get(i))); /* Make a new JLabel with answer string as text */
$checkBoxes.add(new JCheckBox()); /* Make a new JCheckBox */
$answerLabels.get(i).setFont(new Font("Serif", Font.PLAIN, 16));
c.gridx = 0;
c.gridy = i + 2;
getContentPane().add($answerLabels.get(i),c); /* Add the label to the JFrame */
c.gridx = 1;
c.gridy = i + 2;
getContentPane().add($checkBoxes.get(i),c); /* Add the checkbox to the JFrame */
}
}
/* Add actionlisteners to the buttons */
$resumeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if($question.getMediaPath() != null && QuizSoftwareModel.$vlcPath != null) /* If there is an audio/video piece */
((GiveScoreController)getController()).resumeMP(); /* Resume the mediaplayer if there is an audio/video piece */
((GiveScoreController)getController()).resumeQuestion(); /* Resume the question */
closeFrame(); /* Close the frame */
}
});
$calculateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if($question.getMediaPath() != null && QuizSoftwareModel.$vlcPath != null) /* If there is an audio/video piece */
((GiveScoreController)getController()).closeMP(); /* Close the mediaplayer */
((GiveScoreController)getController()).nextQuestion(); /* Go on to the next question */
closeFrame(); /* Close the frame */
}
});
/* Place the buttons */
c.gridx = 0;
c.gridy = i + 2;
getContentPane().add($resumeButton);
c.gridx = 1;
c.gridy = i + 2;
getContentPane().add($calculateButton);
}
}
giveScoreView 的 Controller :
/**
* This class represents the controller of the GiveScoreView
* @author Matthias Claes
*
*/
public class GiveScoreController extends AbstractController {
public GiveScoreController(Observable model) {
super(model);
}
/**
* Resume the question so other teams can answer it
*/
public void resumeQuestion() {
((QuizModel) getModel()).resumeQuestion(); /* Resume the question */
}
}
测验模型:
/**
* The model of the quiz
* @author Matthias Claes
*
*/
public class QuizModel extends Observable {
private ArrayList<Question> $questions;
private ArrayList<Team> $teams;
private Question $currentQuestion;
private MediaPlayer $mp;
private int $i; /* The position in the questions, at which question we are at the moment */
private int $teamPressed; /* The team that pressed their button */
private boolean $running;
private boolean $displayScoreView;
private boolean $maximize; /* A boolean that tells the QuizView if we need to maximize this JFrame again */
/**
* Constructor for QuizModel
* @param questions a list of questions
*/
public QuizModel(ArrayList<Question> questions){
$mp = new MediaPlayer(this, null); /* null -> Give the default controller as parameter */
this.addObserver($mp);
$teams = new ArrayList<Team>();
if (questions != null) {
$questions = questions;
}
else
$questions = new ArrayList<Question>();
$currentQuestion = null;
$teamPressed = 0; /* Default value*/
$maximize = false; /* Default value */
$i = 0;
$running = false;
$displayScoreView = false;
}
/**
* Starts the quiz
*/
public void start() {
if (initialized()) {// quiz properly initialized
$running = true;
nextQuestion();
}
else {
// TODO what happens when the quiz isn't properly initialized yet
}
}
/**
* Will create a view where the admin can choose the score if the answer was right, resume if the answer was false.
* @param i the team that pushed the button
*/
public void showScoreView(int i) {
$teamPressed = i;
setDisplayScoreView(true);
/* Update the view */
System.out.println("show score view");
setChanged();
notifyObservers($currentQuestion);
}
/**
* Get the boolean displayScoreView
* @return returns true of false, depending on the displayScoreView boolean
*/
public boolean getDisplayScoreView(){
return $displayScoreView;
}
/**
* Set the $displayScoreView boolean
* @param displayScoreView the new value of $displayScoreView
*/
public void setDisplayScoreView(boolean displayScoreView){
$displayScoreView = displayScoreView;
}
/**
* Goes to the next question in the quiz
*/
public void nextQuestion(){
if($running == true && $i < $questions.size()){
$currentQuestion = $questions.get($i);
$i++;
/* This question has a mediaPath but the user doesn't have vlc installed or selected the wrong folder, so they can't use this question, so we go to the next one */
if($currentQuestion.getMediaPath() != null && QuizSoftwareModel.$vlcPath == null){
JOptionPane.showMessageDialog(null, QuizSoftwareModel.$messages.getString("videoDisplayError"));
nextQuestion(); /* go the next question */
}
/* Display the question */
else{
System.out.println("Diplay first question");
setChanged();
notifyObservers($currentQuestion);
}
} /* End of the quiz */
else{
/* Show winner TODO */
}
}
public Question getCurrentQuestion() {
return $currentQuestion;
}
public int getI() {
return $i;
}
/**
* Resume the question
*/
public void resumeQuestion() {
$teamPressed = 0; /* Reset the team that has pressed so other teams can press aswell */
$maximize = true; /* Maximize the screen again */
$displayScoreView = false;
/* TODO SAVE THE TEAM INTO AN ARRAY SO THIS TEAM CAN'T PRESS AGAIN */
System.out.println("RESUME");
this.setChanged();
this.notifyObservers($currentQuestion);
}
/**
* Return the $maximize boolean
* @return returns the $maximize boolean
*/
public boolean getMaximize() {
return $maximize;
}
}
我得到的输出是这样的:
显示第一个问题
已调用
显示分数 View
已调用
继续
已调用
显示分数 View
已调用
继续
已调用
继续
已调用
因此测验模型中的resume方法被多次调用。
我不知道是否有人可以帮助我,但已经谢谢了。对于这么长的帖子,我深表歉意,但我不知道如何向你们展示它。
最佳答案
在方法 displayScoreView()
中,您将一个 ActionListener
添加到 $resumeButton
引用的按钮,该按钮最终将调用 resumeQuestion()
方法。
因为 displayScoreView()
是一个实例方法,可以多次调用(而且似乎会),而 $resumeButton
在整个生命周期中包含相同的按钮实例在 GiveScoreView
实例中,可能有多个监听器在该按钮上注册执行相同的操作(即调用 resumeQuestion()
)。
请注意,如果很难找出代码实际上在做什么,您应该考虑清理它......
关于java - 函数无故被调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23765921/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!