I am currently making a quiz game. I have managed to set the game up as follows -
The user clicks the start button.
From here this opens a text file and retrieves each question and saves them to a string.
It then adds these strings to an Arraylist.
I then have display the first element of the array to a Label (this is the first question).
From here I have managed to make a method that checks the label text and set the text of 4 buttons to 4 different buttons.
If the user selects the correct answer it adds +1 to a score integer and then moves onto the next question(askQues2();). If the user selects the wrong answer it just moves on to the next question(askQues2();).
Once it starts the next question(askQues2();) it changes all of the values that I have told it to. i.e LabelQuestion and the 4 different answer buttons.
If the user selects the correct answer it adds +1 to a score integer and then moves onto the next question(askQues3();).
THIS IS WHERE THE PROBLEM IS
When I chose an answer during the second question, it does not run the 3rd question method.
CODE
public void askQues1 (){
String askQues1 = questions.get(0);
LabelQuestion.setText(askQues1);
ButAnsA.setText("Gillard");
ButAnsB.setText("Howard");
ButAnsC.setText("Rudd");
ButAnsD.setText("Abbott");
ButAnsA.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
Score += 1;
askQues2();
}
});
ButAnsB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues2();
}
});
ButAnsC.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues2();
}
});
ButAnsD.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues2();
}
});
}
public void askQues2(){
String askQues2 = questions.get(1);
LabelQuestion.setText(askQues2);
ButAnsA.setText("1999");
ButAnsB.setText("2004");
ButAnsC.setText("2007");
ButAnsD.setText("2010");
ButAnsA.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues3();
}
});
ButAnsA.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues3();
}
});
ButAnsA.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
askQues3();
}
});
ButAnsA.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent a){
Score += 1;
askQues3();
}
});
}
public void askQues3(){
String askQues3 = questions.get(2);
LabelQuestion.setText(askQues3);
ButAnsA.setText("Broncos");
ButAnsB.setText("Knights");
ButAnsC.setText("Storm");
ButAnsD.setText("Dragons");
}
I can tell that it does not load the 3rd method because the question label or answer buttons change.
I have tried multiple options that I have found on the internet. None of them have fixed this problem.
If you require more information. Please let me know. Like I said it is my first time posting a question so I 'm not familiar with standards.
Thanks.
You're adding actionListener to the buttons. I don't think a button can detect more than 2 actions judging by your problem.
Try setting an onClickListener() to the buttons instead.
Code:
ButAnsA.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
askQues3();
}
});
NOTE: There's a difference between adding and setting listeners. By setting a listener every time, you're only replacing the previous one. But by adding a listener you're increasing the number of listeners on the particular widget.
Your askQues2() method is adding action listeners to ButAnsA 4 times, and no new listeners to the other buttons.
You appear to be adding new listeners to the same buttons with every call, which is generally suboptimal. Since you said you are reading the questions and possible answers from a file, you'd be better off including which is the right answer in the file and having a single listener for all buttons.
pseudocode:
doAction(ActionEvent e)
int buttoncode=0
switch (e.getSource())
case ButAnsA:buttoncode=1;
case ButAnsB:buttoncode=2;
case ButAnsC:buttoncode=3;
case ButAnsD:buttoncode=4;
if (questions.get(questnum).rightAnswer == buttoncode)
score++;
questnum++
updateQuestionText()
updateButtonText()
Related
I am creating a quiz for school. There are several buttons for the questions which, when pressed, display the new question and create 4 different ActionListeners for the buttons of the 4 answers.
Now I need to remove the 4 ActionListeners after one button was pressed.
I am able to remove the ActionListener from the button itself, but I want to remove the other 3 ActionListeners as well.
Every new ActionListener looks like this:
btAnswer1.addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent evt)
{
lResult.setForeground(Color.red);
lResult.setText("Wrong Answer :(");
// The team is changed.
if (aktTeam == 1)
{
aktTeam = 2;
lAktTeam.setText("Team 2");
}
else
{
aktTeam = 1;
lAktTeam.setText("Team 1");
}
// Here, this ActionListener is removed. But the others should
// be removed too.
btAntwort1.removeActionListener(this);
}
});
I hope somebody can help. :)
Edit: Solved by davidxxx. Thanks!
1) In your example you don't remove the ActionListener from the same btn on the which one you have added the listener:
You add it to btAnswer1:
btAnswer1.addActionListener(new java.awt.event.ActionListener()...
But you remove it from btAntwort1:
btAntwort1.removeActionListener(this);
So, it should not work.
Now I need to remove the 4 ActionListeners after one button was
pressed.
2) If removing all the ActionListeners associated to the Button is valid in our use case, you can do :
for( ActionListener listener : btAntwort1.getActionListeners() ) {
btAntwort1.removeActionListener(listener);
}
Otherwise if you don't want to remove all the ActionListeners associated to the button, you should not inline the anonymous ActionListener instances in order to keep a reference on them when you want to remove them from the button.
For example do that :
ActionListener actionListenerOne = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
...
}
};
ActionListener actionListenerTwo = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
...
}
};
Now you have for example two references on the ActionListener instances you may add to the button.
So you may do :
JButton button = ...;
button.addActionListener(actionListenerOne);
button.addActionListener(actionListenerTwo);
and later :
button.removeActionListener(actionListenerOne);
button.removeActionListener(actionListenerTwo);
I have been given a GUI which creates a random bunch of shapes, the user then has the choice to scale them up or down with the + or the - button. However, when I click either of those buttons it calls the scale method:
public void scale(boolean sign) {
shapes.scale(10,false);
}
How do I make it so the + button would scale it up, and the - button would scale it down? I know it's something to do with an if statement somewhere but I am really struggling.
Thanks for your help.
You don't need an if statement here.
You need different actionPerformed methods like:
plusB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
scale(true); // Assuming it scales up for true, and down for false.
}
});
minusB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
scale(false);
}
});
I had 9 hunks of form-identical code such as this:
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btnExitActionPerformed(evt);
}
});
...with 9 corresponding linked hunks of code like this:
private void btnExitActionPerformed(ActionEvent evt) {
// some code *********************
}
... and a large number of similar repeated hunks of code
for FocusListener and MouseListener.
I tried to cut down the number of lines of code by assigning
the button's text to its action command and using this:
public void actionPerformed(ActionEvent e)
{
String c = e.getActionCommand();
switch (c) {
case "Clear output": btnClearOutputActionPerformed(e); break;
case "Search": btnSearchActionPerformed(e); break;
case "Exit": btnExitActionPerformed(e); break;
...
}
}
It works, but that's not a lot better. Still repetitive. Looking for elegant.
I can't believe the following method even compiles, but it doesn't work because doClick() calls the method recursively. I was naively hoping doClick() would execute the method btnPatternMouseClickedActionPerformed().
public void actionPerformed(ActionEvent e){
Component[] c ;
c = theFrame.getComponents();
JButton b;
for(Component x: c)
{
if(x instanceof JButton)
{
b = (JButton) x;
if(b.getText().equals(e.getActionCommand()))
{
b.doClick(); // want it to execute code elsewhere
return;
}
}
}
}
At first I thought the above method was close. Now I'm about to give up.
I have three questions:
(1) Is there a way to cut down on such repeated hunks of code as shown in the first two paragraphs?
(1a) Is the last method above close? Can it be easily fixed?
(2) Would a technique similar to the actionPerformed method above (the one that uses switch) to replace hunks of code for FocusListener and MouseListener be a waste of time to implement?
You could change this:
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btnExitActionPerformed(evt);
}
});
...with 9 corresponding linked hunks of code like this:
private void btnExitActionPerformed(ActionEvent evt) {
// some code *********************
}
to this:
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// same code that was in the btnExitActionPerformed method.
}
});
But perhaps even better still would be to separate your "control" code, the code in the listeners, from your "view" code, your GUI, but how to do this will depend on your problem and current code base.
Edit
You ask:
I will blame Swing GUI builder for that (bad?) habit.
It's not so bad, and is certainly a lot better than having your GUI classes implement listener interfaces.
Why does Swing do that?? Why does Swing do a LOT of what it does!!
I'm not sure what specifically you meant here.
So about "even better": are you saying to separate the listeners into another class file? And are you suggesting that coconuts migr~~...
Yes, and yes. In fact the control -- the listener part could be composed of several classes, but they all might be used in a single master control class.
I mean, that I should abandon the last method in my question?
Yes.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class Example implements ActionListener{
JButton buttons[] = new JButton[12];
public Example(){
for(int c=0; c<buttons.length; c++){
buttons[c]=new JButton("I am button"+c);
buttons[c].addActionListener(this);
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == buttons[0]){}
if(e.getSource() == buttons[1]){}
if(e.getSource() == buttons[2]){}
if(e.getSource() == buttons[3]){}
if(e.getSource() == buttons[4]){}
if(e.getSource() == buttons[5]){}
if(e.getSource() == buttons[6]){}
if(e.getSource() == buttons[7]){}
//....
}
}
This is not enough elegant for you code?
Something other:
If for example you have buttons that are in the same Team, for example:
It's a good idea to have one class(java Object) and then take objects and make buttons.
public class TVButton implements ActionListener{
public TVButton(String name,String whatever){
}
#Override
public void actionPerformed(ActionEvent e){
//actionFor this button
}
}
I started learning programming a few days ago. I tried to make a calculator but i have one problem:
i don't know how to make backspace JButton.
buusun.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
tf.setText(text.getText().length()-1);
}
});
Any ideas?
Try this:
buusun.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
tf.setText(text.getText().substring(0, text.getText().length() - 1));
}
});
It uses the string.substring(start, end) method.
Note that you might need to adjust the exact variables you are using, as I'm not sure whether you need to get the value from tf or text, but this should provide the gist of what you want.
As i have seen many answers are too obscure for a entry level student like me.
i am following the steps by first addActionListner(this) to my JTextField.
what i am trying to do next and confuses the most is under:
public void actionperformed(Actionevent ae){
if(ae.getSource() == "Enter pressed")
{
outArea.setText(result);
}
}
which does not work because i feel like the code ae.getSource() == "Enter presses" is not working correctly and even i replaced the action i took under actionPerformed by a simple print line command like System.out.println("working"), it won't execute.
here is what i do if a button is pressed.
public void actionperformed(Actionevent ae){
if(ae.getSource() == "JButton")
{
System.out.println("JButton was pushed");
}
}
no matter how, lets say i have a GUI with a piece of given code like these:
public static void main(string[] args){
new myProg();
}
public myProg(){
....
buildTheGUI();
...}
}
//GUI Objects
...
JTextField input = new JTextField(10);
...
//method building the GUI
public void buildTheGUI(){
...
input.addActionListner(this);
...
//a method called actionPerformed
public void actionperformed(Actionevent ae){
}
i am now trying to detect the enter key by actionListner not by any other method because it's given.
Firstly, actionPerformed is triggerd by an action event, typically on most systems, this is triggered by the Enter key (with context to the JTextField)...so you don't need to check for it.
Secondly, the source of the ActionEvent is typically the control that triggered it, that would be the JTextField in this case.
Thirdly, String comparison in Java is done via the String#equals method...
if ("Enter presses".equals(someOtherString)) {...
Your actionPerformed method for the Button is wrong, try better this:
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton) {
JButton button = (JButton) e.getSource();
System.out.println("This button was pushed: " + button.getText());
}
}
And your for KeyListener try this to learn how it works:
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
System.out.println(e.getKeyCode());
}
Dont forget to let your class implement ActionListener and KeyListener.