0

Alright, so, I am trying to make a game using a JFrame that, when you click a button, adds money, and show update some text(a JLabel).

You see, it should just update the Windows.Money variable and display ONLY the new variable on the screen, but, it adds more buttons. Please note: The money part works fine.

It's just that Java doesn't want to replace, only add.

Code:

    package dev.bobdabiulder.classic.main;

import javax.swing.JLabel;

public class Bucket extends Window{

private static final long serialVersionUID = 1L;

public Bucket() throws InterruptedException {

    for(int i = 0; !Window.Paused; ) {
        Window.Money += 2;

            this.wait(1000);

    }

    Window.Buckets++;
    Window.BucketCounter = new JLabel("You have: " + Window.Buckets + " buckets!");


}

}

In the Windows class...

package dev.bobdabiulder.classic.main;

import java.awt.Button;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Window extends JFrame{

public static long Money = 0;
private static final long serialVersionUID = 1L;
private static Thread t1 = new Thread();
private static Thread t2 = new Thread();
private static Thread t3 = new Thread();
private static Thread t4 = new Thread();
private static Thread t5 = new Thread();
public JButton bucket = new JButton("Buy a Bucket!");
public JButton add$ = new JButton("Add Money!");
public JLabel money = new JLabel(Money + "");
public static long Buckets = 0;
public static JLabel BucketCounter = new JLabel("You have: " + Buckets + " buckets!");
public static JPanel buck = new JPanel();
public static boolean Paused = false;
static JFrame jf = new JFrame("Lol!");
//Window Method
public Window() {

    jf.setVisible(true);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    buck.add(bucket);
    buck.add(money);
    buck.add(add$);
    buck.add(BucketCounter);
    jf.setSize(500, 500);
    jf.add(buck);
    bucket.addActionListener(new ActionListener() {
    @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource().equals(bucket)) {
                try {
                    new Bucket();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }

            }
            System.out.println("Action Performed!");


    }
    });
    pack();     

}

//End of ActionPerformed

//Start of start()
public static void start() {
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
}
//
//
//
@SuppressWarnings("deprecation")
public static void stop() {

    t1.stop();
    t2.stop();
    t3.stop();
    t4.stop();
    t5.stop();

}

}

I made some requested edits, and I get errors where I put *, the errors all read:

Cannot make a static reference to the non-static field Window.(anything),

Error Spots:

for(int i = 0; !*Window.Paused; ) {
        *Window.Money += 2;

            this.wait(1000);

    }

    *Window.Buckets++;
    *Window.BucketCounter = new JLabel("You have: " + *Window.Buckets + "       buckets!");
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Bobdabiulder
  • 160
  • 3
  • 12
  • 1
    This code doesn't look like it has anything to do with buttons. But your for loop looks strange. Show us what `wait()` does. Also, give us some code that will literally compile if we try it. – Daniel Kaplan Mar 24 '14 at 21:21
  • I still have no idea what's going on based on the current code. – Hovercraft Full Of Eels Mar 24 '14 at 21:31
  • That is the Method that sets up all the stuff for the JFrame – Bobdabiulder Mar 24 '14 at 21:32
  • It looks like there should be a Swing concurrency issue based on the code presented, but that's not the mal-behavior you're describing. Again, there are too many unexplained assumptions for me at least to venture a guess at what could be wrong. – Hovercraft Full Of Eels Mar 24 '14 at 21:34
  • You mean buck and Bucket? buck is the JPanel, and bucket is the button, finally, Bucket() refers to the first code block(a different class) – Bobdabiulder Mar 24 '14 at 21:35
  • 2
    It's kind of an art, trying to decide how much information and code to post, and it is something you'll get better at with experience, but try to put yourself in our shoes, folks who don't have even the least clue as to your problem and your code, and try to see just what we might need to gain that clue, and then you'll know what we need. – Hovercraft Full Of Eels Mar 24 '14 at 21:37
  • It sounds like you need the full class, let me make that edit... – Bobdabiulder Mar 24 '14 at 21:38
  • 2
    It looks like you're relying on static variables which will lead you into a mess of problems – MadProgrammer Mar 24 '14 at 21:39
  • 2
    we don't need anyhting, you want to do post an SSCCE/MCVE/MCTRE, short, runnable, compilable with hardcoded valuse in local variables – mKorbel Mar 24 '14 at 21:39
  • That better, guys? Also, how can I fix that, MadProgrammer? – Bobdabiulder Mar 24 '14 at 21:43
  • Ayyy, there is massive over-use of statics. You fix that by making pretty much all of your static variables non-static, and then working your program so that it compiles. – Hovercraft Full Of Eels Mar 24 '14 at 21:46
  • And you're calling `Thread#stop()`?? There's a very good reason that this method is deprecated and should never be used. Please read the Thread API for the important details on this. Sorry, but consider starting over from first principles. – Hovercraft Full Of Eels Mar 24 '14 at 21:47
  • Is this program for school or for your own education? – Hovercraft Full Of Eels Mar 24 '14 at 21:50
  • For my own game, hover. Read edits above. Also, what is the issue w/ thread.stop()? That is if it is paused. – Bobdabiulder Mar 24 '14 at 21:53
  • The compiler already has told you that the method is deprecated. When that happens, read the API which in this case will lead you to [this informative link](http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html). Bottom line, **never** use `Thread.stop()`. Ever. My suggestion to you is to go through an introduction to Java book starting with the first chapter as it will save you much frustration and will be the most time efficient way to get this project going, and going well. – Hovercraft Full Of Eels Mar 24 '14 at 21:55
  • I have gone through a book on that many times. What exactly must be fixed? Should I add a protected modifier, considering the fact that the classes are all in the same package? – Bobdabiulder Mar 24 '14 at 21:57
  • No, not a book "on that", a book on basic Java. All of Java. How to say this gently..... I'm not 100% sure what you're trying to do with this code, but I am 100% sure that how you're going about doing it is all wrong. You need to start over completely, don't try to salvage this code, and you need to use good Java principles that you've learned in your book(s). – Hovercraft Full Of Eels Mar 24 '14 at 22:03
  • By "on that", I did mean on Java... #InferencesPlease – Bobdabiulder Mar 24 '14 at 22:04
  • What are you trying to do? I don't get a clear picture based on what you've posted in your question. – Hovercraft Full Of Eels Mar 24 '14 at 22:05
  • I fixed some part of this code, reproduced your issue but I still can't figure out what you're trying to do, how to say it... as @HovercraftFullOfEels said, start over all this and *trying to don't sound rude* try with something easier so you can improve your programming skills – Frakcool Mar 24 '14 at 22:07
  • Or even go with this project, but start over and without static variables (or with minimal static variables, mainly constants) and with a decent program structure and plan, such as an MVC (model-view-control) design structure. I question what your Threads are doing as well. – Hovercraft Full Of Eels Mar 24 '14 at 22:09
  • Alright. I am trying to make a game slightly like cookie clicker - you click a button, get rain drops, and you can spend them to collect more faster. The bucket will get you 2 drops/second, but when you click the button for getting a bucket, it creates MORE buttons. Also, the threads speed up the program, thus their existance. – Bobdabiulder Mar 24 '14 at 22:12
  • This is too much of a "code dump" question. Here's a link explaining the aforementioned concept of [MCVE](http://stackoverflow.com/help/mcve). Please read this [advice on how to ask good questions](http://stackoverflow.com/help/how-to-ask). Be sure to follow the link at the bottom to Jon Skeet's blog post [Writing the perfect question](http://msmvps.com/blogs/jon_skeet/archive/2010/08/29/writing-the-perfect-question.aspx). – Adi Inbar Mar 24 '14 at 22:14
  • Code dump? Also, I gave every last bit of the code, and according to MCVE, that is perfect: you can try it out! – Bobdabiulder Mar 24 '14 at 22:16

2 Answers2

2

Brief example of MVC, well really Model-View. What this does is uses a Swing Timer and not Threads (not directly that is) to increment a JLabel held in a different class. It also uses PropertyChangeListener and support to notify the view (the GUI) of changes in the state of the model.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;

/**
 * http://stackoverflow.com/q/22620807/522444
 * http://stackoverflow.com/a/22621767/522444
 * @author Pete
 *
 */
@SuppressWarnings("serial")
public class ShortMvc extends JPanel {
   private JTextField moneyField = new JTextField(10);
   private JTextField bucketField = new JTextField(10);
   private MoneyModel model = new MoneyModel();
   private Timer timer = new Timer(model.getTimerDelay(), new TimerListener());
   private JButton moneyButton = new JButton("Add Money");
   private JButton bucketButton = new JButton("Add Bucket");

   public ShortMvc() {
      moneyField.setEditable(false);
      moneyField.setFocusable(false);

      bucketField.setEditable(false);
      bucketField.setFocusable(false);

      bucketField.setText(String.valueOf(model.getBuckets()));

      add(new JLabel("Money:"));
      add(moneyField);
      add(moneyButton);
      add(new JLabel("Buckets:"));
      add(bucketField);
      add(bucketButton);

      moneyButton.getModel().addChangeListener(new MoneyBtnModelListener());
      moneyButton.setMnemonic(KeyEvent.VK_M);
      bucketButton.addActionListener(new BucketButtonListener());
      bucketButton.setMnemonic(KeyEvent.VK_B);

      model.addPropertyChangeListener(new ModelListener());
      timer.setInitialDelay(0);
   }

   private class BucketButtonListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         model.incrementBuckets();
      }
   }

   private class MoneyBtnModelListener implements ChangeListener {
      private boolean pressed = false;

      @Override
      public void stateChanged(ChangeEvent e) {
         ButtonModel model = (ButtonModel) e.getSource();
         if (pressed == model.isPressed()) {
            return;
         }
         pressed = model.isPressed();
         if (pressed) {
            timer.start();
         } else {
            timer.stop();
         }
      }
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         model.incrementMoney(model.getMoneyIncrementAmount());
      }
   }

   private class ModelListener implements PropertyChangeListener {
      private NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();

      public ModelListener() {
         moneyField.setText(moneyFormat.format(model.getMoney()));
      }

      @Override
      public void propertyChange(PropertyChangeEvent pcEvt) {
         if (MoneyModel.MONEY.equals(pcEvt.getPropertyName())) {
            moneyField.setText(moneyFormat.format(model.getMoney()));
         }
         else if (MoneyModel.BUCKETS.equals(pcEvt.getPropertyName())) {
            int buckets = model.getBuckets();
            bucketField.setText(String.valueOf(buckets));
            timer.setDelay(model.getTimerDelay());
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Short Mvc");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new ShortMvc());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class MoneyModel {
   public static final String MONEY = "money";
   public static final String BUCKETS = "buckets";
   private static final int INIT_TIMER_DELAY = 500;
   public static final long MONEY_INCREMENT_AMOUNT = 2L;
   private long money = 0L;
   private int buckets = 1;
   private int timerDelay = INIT_TIMER_DELAY;
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public void setMoney(long money) {
      long oldValue = this.money;
      long newValue = money;
      this.money = money;
      pcSupport.firePropertyChange(MONEY, oldValue, newValue);
   }

   public long getMoneyIncrementAmount() {
      return MONEY_INCREMENT_AMOUNT;
   }

   public void incrementMoney(long addToMoney) {
      long oldValue = this.money;
      long newValue = money + addToMoney;
      this.money = newValue;
      pcSupport.firePropertyChange(MONEY, oldValue, newValue);
   }

   public long getMoney() {
      return money;
   }

   public void setBuckets(int buckets) {
      int oldValue = this.buckets;
      int newValue = buckets;
      this.buckets = newValue;
      timerDelay = INIT_TIMER_DELAY / buckets;
      pcSupport.firePropertyChange(BUCKETS, oldValue, newValue);
   }

   public void incrementBuckets(int incrementAmount) {
      int newValue = this.buckets + incrementAmount;
      setBuckets(newValue);
   }

   // increment by one
   public void incrementBuckets() {
      incrementBuckets(1);
   }

   public int getBuckets() {
      return buckets;
   }

   public int getTimerDelay() {
      return timerDelay;
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

}

Note that I can't use an ActionListener for this to work since an ActionListener only gets activated when the button is released. I'm assuming that you want to accumulate money when the button is pressed, and then stop accumulating when it is released. To do this, you must extract the JButton's model, add a ChangeListener to it, and then react to changes to the model's isPressed() method. I use it to start and stop the Swing Timer that increments the model.


Edit
Next iteration with better MVC (model-view-control) separation:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
import javax.swing.text.JTextComponent;

/**
 * http://stackoverflow.com/q/22620807/522444
 * http://stackoverflow.com/a/22621767/522444
 * @author Pete
 *
 */
public class ShortMvc {

   private static void createAndShowGui() {
      ShortView view = new ShortView();
      MoneyModel model = new MoneyModel();
      ShortControl control = new ShortControl(model, view);
      control.init();

      JFrame frame = new JFrame("Short MVC");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(view.getMainPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ShortView {
   private JTextField moneyField = new JTextField(10);
   private JTextField bucketField = new JTextField(10);
   private JButton moneyButton = new JButton();
   private JButton bucketButton = new JButton();
   private JPanel mainPanel = new JPanel();

   public ShortView() {
      moneyField.setEditable(false);
      moneyField.setFocusable(false);

      bucketField.setEditable(false);
      bucketField.setFocusable(false);

      mainPanel.add(new JLabel("Money:"));
      mainPanel.add(moneyField);
      mainPanel.add(moneyButton);
      mainPanel.add(new JLabel("Buckets:"));
      mainPanel.add(bucketField);
      mainPanel.add(bucketButton);
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

   public JTextComponent getMoneyField() {
      return moneyField;
   }

   public JTextComponent getBucketField() {
      return bucketField;
   }

   public AbstractButton getMoneyButton() {
      return moneyButton;
   }

   public AbstractButton getBucketButton() {
      return bucketButton;
   }   
}

@SuppressWarnings("serial")
class ShortControl {
   private MoneyModel model;
   private ShortView view;
   private Timer timer;
   private MoneyBtnAction moneyBtnAction = new MoneyBtnAction("Add Money", KeyEvent.VK_M);
   private BucketButtonAction bucketAction = new BucketButtonAction("Add Buckets", KeyEvent.VK_B);

   public ShortControl(MoneyModel model, ShortView view) {
      this.model = model;
      this.view = view;
      timer = new Timer(model.getTimerDelay(), new TimerListener());
   }

   public void init() {
      timer.setInitialDelay(0);
      view.getBucketField().setText(String.valueOf(model.getBuckets()));

      view.getMoneyButton().setAction(moneyBtnAction);
      view.getMoneyButton().getModel().addChangeListener(moneyBtnAction);
      view.getBucketButton().setAction(bucketAction);

      model.addPropertyChangeListener(new ModelListener());
   }

   private class BucketButtonAction extends AbstractAction {
      public BucketButtonAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         model.incrementBuckets();
      }
   }

   private class MoneyBtnAction extends AbstractAction implements ChangeListener {
      private boolean pressed = false;

      public MoneyBtnAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // empty
      }

      @Override
      public void stateChanged(ChangeEvent e) {
         ButtonModel model = (ButtonModel) e.getSource();
         if (pressed == model.isPressed()) {
            return;
         }
         pressed = model.isPressed();
         if (pressed) {
            timer.start();
         } else {
            timer.stop();
         }
      }
   }

   private class ModelListener implements PropertyChangeListener {
      private NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();

      public ModelListener() {
         view.getMoneyField().setText(moneyFormat.format(model.getMoney()));
      }

      @Override
      public void propertyChange(PropertyChangeEvent pcEvt) {
         if (MoneyModel.MONEY.equals(pcEvt.getPropertyName())) {
            view.getMoneyField().setText(moneyFormat.format(model.getMoney()));
         }
         else if (MoneyModel.BUCKETS.equals(pcEvt.getPropertyName())) {
            int buckets = model.getBuckets();
            view.getBucketField().setText(String.valueOf(buckets));
            timer.setDelay(model.getTimerDelay());
         }
      }
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         model.incrementMoney(model.getMoneyIncrementAmount());
      }
   }

}

class MoneyModel {
   public static final String MONEY = "money";
   public static final String BUCKETS = "buckets";
   private static final int INIT_TIMER_DELAY = 500;
   public static final long MONEY_INCREMENT_AMOUNT = 2L;
   private long money = 0L;
   private int buckets = 1;
   private int timerDelay = INIT_TIMER_DELAY;
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public void setMoney(long money) {
      long oldValue = this.money;
      long newValue = money;
      this.money = money;
      pcSupport.firePropertyChange(MONEY, oldValue, newValue);
   }

   public long getMoneyIncrementAmount() {
      return MONEY_INCREMENT_AMOUNT;
   }

   public void incrementMoney(long addToMoney) {
      long oldValue = this.money;
      long newValue = money + addToMoney;
      this.money = newValue;
      pcSupport.firePropertyChange(MONEY, oldValue, newValue);
   }

   public long getMoney() {
      return money;
   }

   public void setBuckets(int buckets) {
      int oldValue = this.buckets;
      int newValue = buckets;
      this.buckets = newValue;
      timerDelay = INIT_TIMER_DELAY / buckets;
      pcSupport.firePropertyChange(BUCKETS, oldValue, newValue);
   }

   public void incrementBuckets(int incrementAmount) {
      int newValue = this.buckets + incrementAmount;
      setBuckets(newValue);
   }

   // increment by one
   public void incrementBuckets() {
      incrementBuckets(1);
   }

   public int getBuckets() {
      return buckets;
   }

   public int getTimerDelay() {
      return timerDelay;
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

Ok, this should help a bit... missing Timer but you can get an idea of how to manage ActionListeners:

Main class

public class WindowInit{
    public static void main(String args[]){
        WindowHelp wh = new WindowHelp();
    }
}

WindowHelp (This one does the magic)

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

public class WindowHelp{
    JButton b1;
    JButton b2;
    JLabel label;
    long money;
    long buckets;
    JFrame jf;
    Timer timer;
    public WindowHelp(){
        money = 0;
        buckets = 0;
        b1 = new JButton("Add buckets");
        b2 = new JButton("Add money");
        label = new JLabel("");
        jf = new JFrame("My Game");
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                buckets += 2;
                label.setText("Buckets: " + buckets);
            }
        });
        b1.setBounds(50,50,100,30);
        b2.setBounds(200,50,100,30);
        label.setBounds(300,50,200,30);
        jf.add(b1);
        jf.add(b2);
        jf.add(label);
        jf.setSize(500,600);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Yes, one is the main class you compile "WindowInit" and run that one.

For timers, gimme some time while I implement it.

Frakcool
  • 10,915
  • 9
  • 50
  • 89