I need to create a lottery program that will allow user to select 4 numbers (image of the buttons here)
which then should be inputed into an array, I cannot get the array to fill fully, I have tried different versions of adding an int into array and I just can't seem to find the right one..
int hold;
int userNumbers[] = new int[3];
public lotteryGUI() {
initComponents();
}
private void twentyoneActionPerformed(java.awt.event.ActionEvent evt) {
hold = 21;
hold += userNumbers[0];
}
private void nineActionPerformed(java.awt.event.ActionEvent evt) {
hold = 9;
userNumbers[0]= hold + userNumbers[0];
}
private void oneActionPerformed(java.awt.event.ActionEvent evt) {
hold = 1;
userNumbers[0] = userNumbers[0] + hold ;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println(Arrays.toString(userNumbers));
}
This is just a sample with 3 buttons, As you can probably tell the output i get is (10,0,0).
#edit
I have contacted my lecturer about this project and I received a little hint. I am supposed to add ActionListener and if the button is checked I am supposed to add it to an array. Not really sure how to do that, I'm going to look at some tutorials and edit this post if necessary
I would hate to hard code it, but it is really up to you to figure out how to do that for 28 buttons. Here is example for 1 button:
int counter = 0;
int[] userNumbers = new int[3];
public lotteryGUI() {
initComponents();
JButton number1 = new JButton("1");
JButton number2 = new JButton("2");
number1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
userNumbers[counter] = 1;
counter = counter + 1;
if (counter == 3)
// disable all buttons and display result maybe?
}
}
// ... the rest 27 buttons maybe?
}
Related
I ran into an issue with my java code where the action listener is not working. I am supposed to create a GUI that has a menu bar that performs some actions when those buttons are clicked. For example, if the user selects an option on the "Meals" menu and an option on the "Dorms" menu, it should calculate the values that each of those items has assigned and then outputted to the total cost JField.
This is what my code looks like
private class MenuActionListener implements ActionListener {
//The user has chosen a new dorm or new meal plan
//Get the choices from the dormBox and mealBox and recalculate charges
//Display the new charges in the totalField
public void actionPerformed(ActionEvent arg0) {
//Get the choices from the dormBox and mealBox
int totalCost;
int dormIndex = menu.getComponentCount();
int dormCost=dormCosts[dormIndex];
int mealIndex=dorm.getComponentCount();
int mealCost=mealCosts[mealIndex];
//Calculate the charges
totalCost=dormCost+mealCost;
//Display the new charges
totalField.setText("$"+Integer.toString(totalCost));
}
}
How should I get it working well..?
Don’t write listeners which try to guess about the right values to use. When you register a listener to a specific component, you already know which component it is, so you can register a listener doing the right thing for exactly that component.
In this case, when the costs are stored in an array, there should also be a corresponding array used for building the menu items, which allows constructing items and corresponding listeners.
E.g.
static String[] dorms = { "Allen Hall", "Pike Hall", "Farthing Hall" };
static int[] dormCosts = { 10, 20, 40 };
static String[] meals = { "7 / weak", "14 / week", "unlimited" };
static int[] mealCosts = { 5, 8, 15 };
JTextField totalField = new JTextField();
int dormCost = dormCosts[0];
int mealCost = mealCosts[0];
void updateTotalCosts() {
int totalCost = dormCost + mealCost; // really plus not multiply?
totalField.setText("$" + totalCost);
}
JMenuBar buildMenu() {
final JMenuBar mb = new JMenuBar();
JMenu menu = mb.add(new JMenu("Meals"));
for(int ix = 0; ix < meals.length; ix++) {
int currMealCosts = mealCosts[ix];
menu.add(meals[ix]).addActionListener(ev -> {
mealCost = currMealCosts;
updateTotalCosts();
});
}
menu = mb.add(new JMenu("Dorms"));
for(int ix = 0; ix < dorms.length; ix++) {
int currDormCosts = dormCosts[ix];
menu.add(dorms[ix]).addActionListener(ev -> {
dormCost = currDormCosts;
updateTotalCosts();
});
}
return mb;
}
In each loop iteration we do already know which item we’re creating and which costs are associated with it, so we register a listener using exactly those costs.
If you can’t use lambda expressions, the pre-Java 8 variant of the construction method would look like
JMenuBar buildMenu() {
final JMenuBar mb = new JMenuBar();
JMenu menu = mb.add(new JMenu("Meals"));
for(int ix = 0; ix < meals.length; ix++) {
final int currMealCosts = mealCosts[ix];
menu.add(meals[ix]).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
mealCost = currMealCosts;
updateTotalCosts();
}
});
}
menu = mb.add(new JMenu("Dorms"));
for(int ix = 0; ix < dorms.length; ix++) {
final int currDormCosts = dormCosts[ix];
menu.add(dorms[ix]).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
dormCost = currDormCosts;
updateTotalCosts();
}
});
}
return mb;
}
I'm afraid that this approach won't work. You cannot access your UI components from inside the ActionListener.
You might want to try to add an anonymous listener to your JMenuItems that updates attributes of you class to perform the calculation.
Edit: Check Holger's answer for a nice solution :)
This way you can access the outer components or better delegate this to a model class.
See here: https://www.codejava.net/java-core/the-java-language/java-8-lambda-listener-example
The java KeyListener class has no option for a double key press, so I attempted to make my own using multiple arrays and arraylists.
Here is the relevent code
private ArrayList<Integer> ButtonsPressedChar = new ArrayList<Integer>();
private ArrayList<Long> ButtonsPressedTimes = new ArrayList<Long>();
private int[] PossiblePresses = new int[222];
private ArrayList<Integer> DoublePresses = new ArrayList<Integer>();
private ArrayList<Integer> ToBeRemovedChars = new ArrayList<Integer>();
private ArrayList<Integer> ToBeRemovedTimes = new ArrayList<Integer>();
private Long LastTimeForDoublePress;
private Long NowTime;
private int PositionTime;
private int PositionChar;
public void DetectDoubleKeyPresses(){
PositionTime = 0;
PositionChar = 0;
NowTime = System.currentTimeMillis();
for(int temp : PossiblePresses){
PossiblePresses[temp] = 0;
}
for(Long temp: ButtonsPressedTimes){
if( temp - NowTime >= 300){
ButtonsPressedChar.remove(PositionTime);
ToBeRemovedTimes.add(PositionTime);
System.out.println("removed");
}
PositionTime++;
}
for(int temp: ToBeRemovedTimes){
ButtonsPressedTimes.remove(temp);
System.out.println("DONE");
}
DoublePresses.clear();
for(Integer temp: ButtonsPressedChar){
System.out.println("hi 1");
if( PossiblePresses[temp] == 0){
System.out.println("First Press" + temp + PossiblePresses[temp]);
PossiblePresses[temp] = 2;
}
else if(PossiblePresses[temp] == 2){
DoublePresses.add(temp);
System.out.println(ButtonsPressedChar.size());
ToBeRemovedChars.add(temp);
ButtonsPressedTimes.remove(PositionChar);
System.out.println("DOUBLE PRESS" + temp.toString()+ PossiblePresses[temp]);
}
System.out.println("hi 2");
PositionChar++;
}
for(Integer temp: ToBeRemovedChars){
while(ButtonsPressedChar.contains(temp)){
ButtonsPressedChar.remove(temp);
}
System.out.println("DONE");
}
ToBeRemovedChars.clear();
LastTimeForDoublePress =NowTime;
}
public class Keys implements KeyListener{
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
if(ButtonsHeld.contains(e.getKeyCode())){
Integer tempInteger = new Integer(e.getKeyCode());
ButtonsHeld.remove(tempInteger);
}
else
System.out.println("ERROR");
System.out.println(e.getKeyCode());
ButtonsPressedChar.add( e.getKeyCode());
ButtonsPressedTimes.add(System.currentTimeMillis())
}
#Override
public void keyPressed(KeyEvent e) {
if(ButtonsHeld.contains(e.getKeyCode())){
System.out.println("Error: Attempted Key Press Twice, original press was not removed from ButtonsHeld");
}
else if(!ButtonsHeld.contains(e.getKeyCode())){
ButtonsHeld.add(e.getKeyCode());
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public ArrayList<Integer> ButtonsHeld = new ArrayList<Integer>();
public void KeyHeldChecker(){
}
}
I'm so sorry if some of the brackets are in weird places, i had to adjust everything to get it in the code block
Detect Double Key presses is executed 60 times a second. The 'hi 1' and 'hi 2' were just part of my debugging to see what was being executed. This is what is executed when J (key code 74) is pressed a single time:
74
hi 1
First press740
hi 2
hi 1
1
DOUBLE PRESS742
hi 2
DONE
At first i thought possible presses was not being cleared properly, but the for loop seems to be working. If anyone knows why this isn't working or even just a better way of doing this that would be amazing.
Sorry for the bad format, I honestly can't get it to work and are not finding any quadruple spaces anywhere they shouldn't be. I hope that it doesn't make it too hard to see or understand.
If you are wanting to detect a simple double press there is no real need for any arrays or Arraylists. You only need to really store the previous key press.
Consider this: If you press J then K then J the J is no longer a double press so why do you care about it.
To do this you could use the following:
public class DoubleKeyPressDetection
{
// Below int is the number of milliseconds between the presses to determine
// if it was an intentional double press
// Adjust this for sensitivity required
private static int doublePressSpeed = 500; // Half a second
private static KeyEvent lastKeyEvent;
public static boolean isDoublePress(KeyEvent ke)
{
KeyEvent temp = lastKeyEvent;
lastKeyEvent = ke;
return temp != null
&& temp.getKeyCode() == ke.getKeyCode()
&& ((ke.getWhen() - temp.getWhen()) < doublePressSpeed);
}
}
Then in your KeyListener
#Override
public void keyPressed(KeyEvent e)
{
if(DoubleKeyPressDetection.isDoublePress(e))
System.out.println("You have double pressed " + KeyEvent.getKeyText(e.getKeyCode()));
}
Points to note:
If you put this in both the keyPressed and keyReleased methods then it will action on every keyPress and release - so will not work correctly
If you use the keyTyped method then this might not work as the KeyEvent does not have the keyCode
Not all keys will be tracked by this (depending on your application i.e. Tab in a swing app)
I am in the middle of creating a children's board game, that asks random maths questions and players move if they answer right. I have a main BoardGUI class that includes 2 panels. One for the board, and one for the questions.
I'm having trouble with the Question panel. I'm reading in questions from a text file and saving each question as an object within an array. The issue is I can answer one question correctly and it will refresh the question with a new one, however doesn't keep doing this.
I'll paste the QuestionGUI class, as I think this is the one with issues to do with generating the same question/answers from a random number.
public class QuestionGUI extends JPanel implements ActionListener {
JLabel question;
JButton btnAnswers[];
Reader r1 = new Reader();
Questions q1 = new Questions();
Random rand = new Random();
boolean answered;
int random = rand.nextInt(r1.ArraySize());
int random2 = rand.nextInt(r1.ArraySize());
int length = q1.getArrayItem(random).getAnswers().length;
public QuestionGUI() {
questionInit(random);
}
public void questionInit(int randomNum) {
this.random = randomNum;
//gets the answers from the array obj
String[] answers = q1.getArrayItem(random).getAnswers();
//sets the question from question of array obj (same obj as answers I assumed, using random num)
question = new JLabel("<html>" + (q1.getArrayItem(random).getQuestion()) + "</html>", SwingConstants.CENTER);
question.setPreferredSize(new Dimension(280, 100));
add(question);
btnAnswers = new JButton[length];
for (int i = 0; i < length; i++) {
btnAnswers[i] = new JButton(answers[i]);
btnAnswers[i].setPreferredSize(new Dimension(280, 60));
btnAnswers[i].addActionListener(this);
add(btnAnswers[i]);
}
}
#Override
public void actionPerformed(ActionEvent e) {
//sets the correct answers to question also using the random num
String[] correctAnswers = q1.getArrayItem(random).getCorrectAnswers();
for (int i = 0; i < length; i++) {
if (e.getSource().equals(btnAnswers[i])) {
String tmp1 = btnAnswers[i].getText();
if (Arrays.asList(correctAnswers).contains(tmp1)) {
System.out.println("Correct");
removeAll();
revalidate();
answered = true;
questionInit(random2);
repaint();
} else {
answered = false;
}
}
}
}
public boolean getAnswered() {
return answered;
}
}
It looks like you only generate the random number used as the index once.
int random2 = rand.nextInt(r1.ArraySize());
.
.
.
questionInit(random2);
You need to regenerate a random number each time. You can write a helper method to do this, or just put the code in the argument:
questionInit(rand.nextInt(r1.ArraySize()));
This might require additional refactoring.
Button must add 50 to integer but its not . I dont know well about Jframe so help me guys.
int money = 0;
...
JButton verlan = new JButton("50 kr\u015F");
verlan.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int moremoney = money + 50;
String x=Integer.toString(moremoney);
textArea.setText(x + " cent");
}
});
In your ActionListener you define a new variable on which you add up the value of money and 50, however you never update the initial value of money. Instead you can update money, however you have to make sure that the variable is available in the scope of the ActionListener, e.g. by declaring it as a member variable.
private int money = 0;
...
JButton verlan = new JButton("50 kr\u015F");
verlan.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
money += 50;
String x=Integer.toString(money);
textArea.setText(x + " cent");
}
});
In short, I would like to accumulate a bunch of JButton's to an array, and create one ActionListener class for the array.
I'm trying to create a calculator, and all the numbered buttons, such as "6", are in a JButton array, because I would like to have it input the set number into a temporary int, and it would be easier to create one method, instead of 10. I also have 40 other buttons, that I would like to apply the same principal to, but in a different array, so it would be much faster and easier to put these into a couple of ActionListener methods where the buttons data is implemented to that method.
this is the code I have:
private JButton num0, num1, num2, num3, num4, num5, num6, num7, num8, num9;
private JButton numArray[] = {num0, num1, num2, num3, num4, num5, num6, num7, num8, num9};
public GUI(){
numArray.AddActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
}
});
}
You can consider the proposal of Newb Monad. However, you can use the same listener for all your buttons, as in the following example.
public static void main(String[] args) {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
String text = ((JButton) e.getSource()).getText();
JOptionPane.showMessageDialog(null, text);
}
}
};
JPanel panel = new JPanel(new GridLayout(4,3));
JButton[] array = new JButton[10];
for (int i = 0; i < array.length; i++) {
array[i] = new JButton(String.valueOf(i));
array[i].addActionListener(listener);
panel.add(array[i]);
}
JOptionPane.showMessageDialog(null, panel);
}
You have the right idea. However, array objects do not have an addActionListener() method. You must add an action listener to each JButton individually. You can use the same listener for every button, but then you have to figure out which button was clicked inside the actionPerformed() method. IMO, a cleaner solution is to assign a separate listener to each JButton because that way each ActionListener can know which number is pressed without checking the source of the event. For example, you can create a NumberButtonListener class which takes an int as the only argument to its constructor. You can then create the JButtons and the corresponding NumberButtonListeners at the same time in a small loop.
This seems to work well for me.
I essentially loop through all of the buttons while checking it against the action (e.getSource()).
public void actionPerformed(ActionEvent e){
//loop through allbuttons to check if clicked
for(int i = 0; i < buttonArr.length; i++){
for(int j = 0; j < buttonArr[0].length; j++){
if(e.getSource() == buttonArr[i][j]){
//do stuff
}
}
}
}
I had a similar problem with a 2D array of buttons for a game of "Connect Four". I was able to use a for loop inside ActionListener to test which of my buttons had been pushed. The key was modifying the toString() method from my button class to supply the array element as a string:
Within the JPanel class definition:
...
discs = new RoundButton[6][7]; //my 2D array
...
public class RoundButton extends JButton {
...
public String toString() {
return "discs["+i+"]["+j+"]";
}
...
}
private class ButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent event) {
for (int i = 0; i < discs.length; i++){
for (int j= 0; j < discs[i].length; j++){
if (event.getSource() == discs[i][j]){
discs[i][j].setIcon(yellowDisc); //my particular action for that button
}
}
Sorry this is messy. I've never posted on here before.