Java keeps adding buttons! - JFrames - [closed]

2019-06-14 07:29发布

问题:

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!");

回答1:

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);
   }

}


回答2:

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.