Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
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!");
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);
}
}
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.
Related
I'm designing a JPanel in which there are some buttons which have their own action listeners and would do certain things when clicked (for example, one of them would remove the panel). In case the user closes the program, panels shouldn't be deleted and should be retrieved. for this purpose I serialize panels and deserialize them when needed. but the problem is listeners such as action listeners and mouse listeners wouldn't work when the panel is retrieved. is there any way to solve this problem? or is there any alternative to do the same thing without problem?
My panel code in case it's needed:
import jdk.internal.org.objectweb.asm.commons.SerialVersionUIDAdder;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.URL;
import java.text.Format;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Random;
public class Download extends JPanel implements Serializable {
private String fileName;
private boolean removed = false;
private double downloadSpeed;
private double downloadedSize;
private double sizeOfFile;
LocalTime downloadTime;
LocalDate downloadDate;
private boolean checked = false;
private static final long serialVersionUID = 1113799434508676095L;
JLabel test = new JLabel("test");
public Download (MainPage c,URL url,LocalTime time,LocalDate date) {
setLayout(null);
downloadDate = date;
downloadTime = time;
fileName = url.getFile();
JCheckBox checkbox = new JCheckBox();
checkbox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
setChecked(true);
else
setChecked(false);
}
});
checkbox.setBackground(new Color(186,212,215));
checkbox.setBounds(95,42,17,15);
add(checkbox);
MouseAdapter a = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
super.mouseEntered(e);
setBackground(new Color(224,235,252));
checkbox.setBackground(new Color(224,235,252));
}
#Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
setBackground(new Color(186,212,255));
checkbox.setBackground(new Color(186,212,255));
}
};
UIManager.put("ProgressBar.background", new Color (235,255,255));
UIManager.put("ProgressBar.foreground", new Color (10,109,63));
UIManager.put("ProgressBar.selectionBackground", Color.RED);
UIManager.put("ProgressBar.selectionForeground", Color.GREEN);
setBackground(new Color(186,212,255));
setPreferredSize(new Dimension(600,100));
JPanel file = new JPanel();
/* test fileImg = new test("file.png");
fileImg.setBounds(10,10,40,50);
add(fileImg); */
JLabel fileNameLabel = new JLabel(fileName);
fileNameLabel.setBounds(100,5,400,15);
fileNameLabel.setForeground(new Color(109,111,114));
add(fileNameLabel);
JProgressBar jpb = new JProgressBar(0,100);
Random r = new Random();
jpb.setValue(r.nextInt(100));
jpb.setBounds(100,25,400,10);
JLabel progressBarValue = new JLabel("%" + jpb.getValue() + "");
progressBarValue.setBounds(510,18,25,20);
add(progressBarValue);
this.setBorder(BorderFactory.createMatteBorder(0,0,2,0,new Color(18,42,79)));
addMouseListener(a);
add(jpb);
JButton trash = new JButton(new ImageIcon("trash.png"));
trash.setBounds(130,40,25,25);
/* trash.setContentAreaFilled(false);
trash.setFocusPainted (false);
trash.setBorderPainted(false); */
trash.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("text");
}
});
add(trash);
test.setBounds(180,40,25,25);
test.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
System.out.println("text");
}
});
add(test);
double lower = 0;
double upper = 999.99;
sizeOfFile = Math.random() * (upper - lower) + lower;
downloadSpeed = Math.random() * (upper - lower) + lower;
downloadedSize = jpb.getValue() * sizeOfFile / 100;
JLabel downloadSpeedLabel = new JLabel (String.format ("%.1fKbs",downloadSpeed));
JLabel downloadedSizeLabel = new JLabel (String.format ("%.1fMG / %.2fMG",downloadedSize,sizeOfFile));
downloadedSizeLabel.setForeground(new Color(109,111,114));
downloadSpeedLabel.setForeground(new Color(109,111,114));
downloadSpeedLabel.setBounds(250,35,100,30);
downloadedSizeLabel.setBounds(420,35,150,30);
add(downloadSpeedLabel); add(downloadedSizeLabel);
}
public boolean isRemoved() {
return removed;
}
public void setRemoved(boolean removed) {
this.removed = removed;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public double getDownloadSpeed() {
return downloadSpeed;
}
public void setDownloadSpeed(double downloadSpeed) {
this.downloadSpeed = downloadSpeed;
}
public double getDownloadedSize() {
return downloadedSize;
}
public void setDownloadedSize(double downloadedSize) {
this.downloadedSize = downloadedSize;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
public double getSizeOfFile() {
return sizeOfFile;
}
public void setSizeOfFile(double size) {
this.sizeOfFile = size;
}
}
I'm trying to make a counter that counts every 1/100 of a second until the program is closed, but it appears to be a little slower than that. Here's what I have:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import javax.swing.*;
public class counterTest extends JFrame
{
JLabel label;
long counter = 0;
String counterStr;
public counterTest()
{
super("counter");
ActionListener listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
counter++;
counterStr = Long.toString(counter);
label.setText(counterStr);
}
};
label = new JLabel();
setLayout(new FlowLayout());
setSize(100,100);
setResizable(false);
setVisible(true);
add(label);
javax.swing.Timer timer = new javax.swing.Timer(10, listener);
timer.setInitialDelay(0);
timer.start();
}
public static void main(String args[])
{
counterTest c = new counterTest();
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
The "10" in the line where I declare "timer" should cause "listener" to run every 1/100 second, correct? It seems a bit slower... what is wrong here?
EDIT: Full code posted.
A Swing Timer is not built to be 100% accurate, and 1/100 may be pushing it's limits. Consider using the Swing Timer but displaying absolute time differences, calculated by getting the time.
e.g.,
private class MyTimerListener implements ActionListener {
private long startTime = 0;
public void reset() {
startTime = System.currentTimeMillis();
}
#Override
public void actionPerformed(ActionEvent e) {
long time = System.currentTimeMillis();
long delta = (time - startTime) / 10L;
label.setText(String.valueOf(delta));
}
}
OK, my mini-program:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyTimer2 extends JPanel implements GuiTimer {
private static final String TIME_FORMAT = "%03d:%03d";
private static final int EXTRA_WIDTH = 50;
private JLabel timerLabel = new JLabel();
private TimerControl timerControl = new TimerControl(this);
public MyTimer2() {
JPanel topPanel = new JPanel();
topPanel.add(new JLabel("Time:"));
topPanel.add(timerLabel);
JPanel centerPanel = new JPanel();
centerPanel.add(new JButton(timerControl.getStartAction()));
centerPanel.add(new JButton(timerControl.getStopAction()));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(centerPanel, BorderLayout.CENTER);
setDeltaTime(0);
}
#Override
public void setDeltaTime(int delta) {
int secs = (int) delta / 1000;
int mSecs = (int) delta % 1000;
timerLabel.setText(String.format(TIME_FORMAT, secs, mSecs));
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = superSz.width + EXTRA_WIDTH;
int prefH = superSz.height;
return new Dimension(prefW, prefH);
}
private static void createAndShowGui() {
MyTimer2 mainPanel = new MyTimer2();
JFrame frame = new JFrame("MyTimer2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
interface GuiTimer {
public abstract void setDeltaTime(int delta);
}
#SuppressWarnings("serial")
class TimerControl {
private static final int TIMER_DELAY = 10;
private long startTime = 0;
private long pauseTime = 0;
private Timer timer;
private GuiTimer gui;
private StartAction startAction = new StartAction();
private StopAction stopAction = new StopAction();
public TimerControl(GuiTimer gui) {
this.gui = gui;
}
public Action getStopAction() {
return stopAction;
}
public Action getStartAction() {
return startAction;
}
enum State {
START("Start", KeyEvent.VK_S),
PAUSE("Pause", KeyEvent.VK_P);
private String text;
private int mnemonic;
private State(String text, int mnemonic) {
this.text = text;
this.mnemonic = mnemonic;
}
public String getText() {
return text;
}
public int getMnemonic() {
return mnemonic;
}
};
private class StartAction extends AbstractAction {
private State state;
public StartAction() {
setState(State.START);
}
public final void setState(State state) {
this.state = state;
putValue(NAME, state.getText());
putValue(MNEMONIC_KEY, state.getMnemonic());
}
#Override
public void actionPerformed(ActionEvent e) {
if (state == State.START) {
if (timer != null && timer.isRunning()) {
return; // the timer's already running
}
setState(State.PAUSE);
if (startTime <= 0) {
startTime = System.currentTimeMillis();
timer = new Timer(TIMER_DELAY, new TimerListener());
} else {
startTime += System.currentTimeMillis() - pauseTime;
}
timer.start();
} else if (state == State.PAUSE) {
setState(State.START);
pauseTime = System.currentTimeMillis();
timer.stop();
}
}
}
private class StopAction extends AbstractAction {
public StopAction() {
super("Stop");
int mnemonic = KeyEvent.VK_T;
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
if (timer == null) {
return;
}
timer.stop();
startAction.setState(State.START);
startTime = 0;
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
long time = System.currentTimeMillis();
long delta = time - startTime;
gui.setDeltaTime((int) delta);
}
}
}
This question already has answers here:
How to evaluate a math expression given in string form?
(26 answers)
Closed 6 years ago.
This is a simple calculator where the user can type out the calculation and hit enter, and the calculator would determine if it is a valid calculation or not. If it is a valid calculation, the calculation is carried out. If not, an error message is written to the screen.
The calculation is carried out part isn't finished.
Can someone suggest a solutions to the getAnswer() method.
It would be very much appreciated.
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
#SuppressWarnings("serial")
public class Calculator extends JFrame{
private interface CalculatorInterface {
public void writeToScreen(String text);
public void clearScreen();
public String getScreenText();
}
private class CalculatorPanel extends JPanel implements CalculatorInterface {
private class NumberPanel extends JPanel implements CalculatorInterface {
private static final int NUMTOTAL = 10;
private CalculatorPanel calcPanel;
private JButton[] numButtons;
public NumberPanel(CalculatorPanel calcPanel) {
this.calcPanel = calcPanel;
buildLayout();
addButtons();
}
private void buildLayout() {
this.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
GridLayout layout = new GridLayout(4,3);
layout.setHgap(1);
layout.setVgap(1);
this.setLayout(new GridLayout(4,3));
}
private void addButtons() {
numButtons = new JButton[NUMTOTAL];
for(int i = numButtons.length -1; i >= 0 ; i--) {
numButtons[i] = new JButton("" + i);
numButtons[i].setPreferredSize(new Dimension(60,40));
numButtons[i].setFont(new Font("Sans serif", Font.PLAIN, 18));
numButtons[i].addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = ((JButton)e.getSource()).getText().trim();
if(getScreenText().equals("Invalid Calc")) {
clearScreen();
writeToScreen(text);
}else {
writeToScreen(text);
}
}
});
this.add(numButtons[i]);
}
}
#Override
public void writeToScreen(String text) {
calcPanel.writeToScreen(text);
}
#Override
public void clearScreen() {
calcPanel.clearScreen();
}
#Override
public String getScreenText() {
return calcPanel.getScreenText();
}
}
private class OperPanel extends JPanel implements CalculatorInterface {
private static final int ADD = 0;
private static final int SUB = 1;
private static final int MULT = 2;
private static final int DIV = 3;
private static final int OPENB = 4;
private static final int CLOSEB = 5;
private static final int CLEAR = 6;
private static final int EQL = 7;
private static final int OPERTOTAL = 8;
private CalculatorPanel calcPanel;
private JButton[] operButtons;
public OperPanel(CalculatorPanel calcPanel) {
this.calcPanel = calcPanel;
buildLayout();
addButtons();
}
private void buildLayout() {
GridLayout layout = new GridLayout(4,1);
layout.setHgap(1);
layout.setVgap(1);
this.setLayout(new GridLayout(4,1));
}
private void addButtons() {
operButtons = new JButton[OPERTOTAL];
operButtons[ADD] = makeButton(ADD, "+");
operButtons[SUB] = makeButton(SUB, "-");
operButtons[MULT] = makeButton(MULT, "*");
operButtons[DIV] = makeButton(DIV, "/");
operButtons[CLEAR] = makeButton(CLEAR, "CL");
operButtons[EQL] = makeButton(EQL, "=");
operButtons[OPENB] = makeButton(OPENB, "(");
operButtons[CLOSEB] = makeButton(CLOSEB, ")");
for(JButton button: operButtons) {
this.add(button);
}
}
private JButton makeButton(int index, String label) {
operButtons[index] = new JButton(label);
operButtons[index].addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = ((JButton)e.getSource()).getText();
if(text.equals("=")) {
String screenText = getScreenText();
clearScreen();
try {
writeToScreen(getAnswer(screenText));
}catch(Exception excep) {
writeToScreen("Invalid Calc");
}
}else if(text.equals("CL")) {
clearScreen();
}else {
writeToScreen(text);
}
}
});
return operButtons[index];
}
private String getAnswer(String text) throws Exception {
/*I'm trying to solve for any input by the user e.g
*(the stuff in square brackets represents what is displayed
* on the screen:.
*[1+1] (hits equals) [2]
*[1+2-3] (hits equals) [0]
*[1+2*3] (hits equals) [7]
*[10*(14+1/2)] (hits equals) [145]
*/
throw new Exception();
}
#Override
public String getScreenText() {
return calcPanel.getScreenText();
}
#Override
public void clearScreen() {
calcPanel.clearScreen();
}
#Override
public void writeToScreen(String text) {
calcPanel.writeToScreen(text);
}
}
private NumberPanel numPanel;
private OperPanel operPanel;
private JTextField calcScreen;
public CalculatorPanel(JTextField calcScreen) {
this.calcScreen = calcScreen;
buildNumPanel();
buildOperPanel();
buildCalcPanel();
}
private void buildNumPanel() {
this.numPanel = new NumberPanel(this);
}
private void buildOperPanel() {
this.operPanel = new OperPanel(this);
}
private void buildCalcPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
this.add(numPanel);
this.add(operPanel);
}
#Override
public void writeToScreen(String text) {
calcScreen.setText(getScreenText() + text);
}
#Override
public String getScreenText() {
return calcScreen.getText();
}
#Override
public void clearScreen() {
calcScreen.setText("");
}
}
private JPanel mainPanel;
private JTextField calcScreen;
private CalculatorPanel calcPanel;
public Calculator() {
buildScreen();
buildCalcPanel();
buildMainPanel();
buildCalculator();
}
private void buildScreen() {
this.calcScreen = new JTextField();
this.calcScreen.setPreferredSize(new Dimension(150,50));
this.calcScreen.setHorizontalAlignment(JTextField.CENTER);
this.calcScreen.setFont(new Font("Sans serif", Font.PLAIN, 30));
}
private void buildCalcPanel() {
this.calcPanel = new CalculatorPanel(this.calcScreen);
}
private void buildMainPanel() {
this.mainPanel = new JPanel();
this.mainPanel.setBorder(new EmptyBorder(10,10,10,10));
this.mainPanel.setLayout(new BoxLayout(this.mainPanel, BoxLayout.Y_AXIS));
this.mainPanel.add(calcScreen);
this.mainPanel.add(calcPanel);
}
private void buildCalculator() {
this.add(mainPanel);
this.setTitle("Calculator");
this.pack();
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Calculator calc = new Calculator();
}
}
How can I check to see if a string is a valid calculation for a simple calculator?
Edit 1: Fixed a silly bug in the makeButton() method were I passed in the text of the button to be verified instead of the text on screen. (I'm an idiot.)
Edit 2: Removed the isValid(String text) from the code and make it so the getAnswer() method just threw an exception if input is not a valid calculation.
As well mentioned in a previous StackOverflow answer (Evaluating a math expression given in string form), you could use Javascript's ScriptEngine to calculate expressions based on strings that you would retrieve from the Text Field. Place it in a try-catch block first to see if there's an error in the expression. In the catch block, set the variable storing whether its a valid expression or not to false.
boolean validExpression = true;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String input = textField.getText() // Modify this to whatever variable you have assigned to your text field
try {
System.out.println(engine.eval(foo));
}
catch (ScriptException e) {
validExpression = false;
System.out.println("Invalid Expression");
}
Make sure you include the following imports:
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
Although you could try to implement Shunting-Yard Algorithm or another arithmetic parser, this is simply a way more pragmatic solution.
nice job , now i just wanna know why if i add into while loop the instruction System.out.println below the progress is shown on both , cmd and Pgbar in the Gui ?? :
while(progress < 99){
System.out.println("into while of PBar Thread progress = "+progress);
if(progress != Path.operationProgress){
operationProgressBar.setValue(progress);
progress = Path.operationProgress;
operationProgressBar.repaint(); } }
need some help around , i can't get the JProgressBar to update, i
can't use SwingWorker, i have to solve this without it . the variable
Path.operationProgress is a static variable from a "Path" class
instance, and it's updated from another thread, so i think the PBar
and Path instances are both executed in user's Threads and not in the
EDT . here is the Code of the progress bar :
import javax.swing.*;
public class Pbar extends Thread {
JProgressBar operationProgressBar;
public Pbar(JProgressBar operationProgressBar) {
this.operationProgressBar = operationProgressBar;
}
#Override
public void run() {
int progress = Path.operationProgress;
while(progress < 99) {
if(progress != Path.operationProgress) {
operationProgressBar.setValue(progress);
progress = Path.operationProgress;
operationProgressBar.repaint();
}}}
}
this is the action that launches the threads :
private javax.swing.JProgressBar operationProgressBar;
private javax.swing.JLabel pathImage;
private javax.swing.JButton simulatedAnnelingButton;
public class TSPGUI extends javax.swing.JFrame {
TSPMG tspInstance;
Path p, result;
String filename = "";
int neighborHood_Type = 1, i = 0;
// ......Constructor Stuff and init()
private void simulatedAnnelingButtonActionPerformed(java.awt.event.ActionEvent evt)
{
Thread sa = new Thread(){
#Override
public void run(){
result = p.SimulatedAnnealing(neighborHood_Type);
String lastCostString = result.Cost() + "";
lastCostLabel.setText(lastCostString);
}};
sa.start();
Pbar pb = new Pbar(operationProgressBar);
pb.start();
}
//Some other Stuff ...
}
If you can't use SwingWorker then use SwingUtilities.invokeLater, e.g.:
if (progress != Path.operationProgress) {
final int progressCopy = progress; // Probably not final so copy is needed
SwingUtilities.invokeLater(new Runnable() {
#Override
void run() {
operationsProgressBar.setValue(progressCopy);
}
});
}
Note: When doing this, everything used in run has to be final or there have to be other measures to access the variables. This code is symbolic in that regard.
You need to do operations on Swing components outside the event dispatching thread, there is no way around this.
I would use a PropertyChangeListener to allow you to make the annealing progress value a "bound" property of the class. Than any observer can follow this property if desired. For example:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
#SuppressWarnings("serial")
public class TspGui2 extends JPanel {
private static final String ANNEALING_PROGRESS = "Annealing Progress";
private JProgressBar progBar = new JProgressBar(0, 100);
private JLabel valueLabel = new JLabel();
private JButton beginAnnealingBtn = new JButton("Begin Annealing");
private MyAnnealing myAnnealing = new MyAnnealing(this);
public TspGui2() {
beginAnnealingBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
beginAnnealing();
}
});
myAnnealing.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(MyAnnealing.ANNEALING)) {
// be sure this is done on the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int annealedValue = myAnnealing.getAnnealedValue();
setValue(annealedValue);
if (annealedValue >= MyAnnealing.MAX_ANNEALED_VALUE) {
beginAnnealingBtn.setEnabled(true);
}
}
});
}
}
});
progBar.setString(ANNEALING_PROGRESS);
progBar.setStringPainted(true);
JPanel northPanel = new JPanel(new GridLayout(1, 0));
northPanel.add(beginAnnealingBtn);
northPanel.add(valueLabel);
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(northPanel);
add(progBar);
}
public void setValue(int value) {
valueLabel.setText("Value:" + value);
progBar.setValue(value);
}
public void beginAnnealing() {
beginAnnealingBtn.setEnabled(false);
setValue(0);
myAnnealing.reset();
new Thread(new Runnable() {
public void run() {
myAnnealing.beginAnnealing();
}
}).start();
}
private static void createAndShowGui() {
TspGui2 mainPanel = new TspGui2();
JFrame frame = new JFrame("TspGui2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyAnnealing {
public static final String ANNEALING = "Annealing";
public static final int MAX_ANNEALED_VALUE = 100;
private SwingPropertyChangeSupport propChangeSupport =
new SwingPropertyChangeSupport(this);
private TspGui2 gui;
private int annealedValue;
public MyAnnealing(TspGui2 gui) {
this.gui = gui;
}
public void addPropertyChangeListener(
PropertyChangeListener listener) {
propChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(
PropertyChangeListener listener) {
propChangeSupport.removePropertyChangeListener(listener);
}
public void reset() {
setAnnealedValue(0);
}
// simulate some long process...
public void beginAnnealing() {
long sleepDelay = 100;
while (annealedValue < MAX_ANNEALED_VALUE) {
setAnnealedValue(annealedValue + 1);
try {
Thread.sleep(sleepDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getAnnealedValue() {
return annealedValue;
}
private void setAnnealedValue(int value) {
final int oldValue = this.annealedValue;
this.annealedValue = value;
propChangeSupport.firePropertyChange(ANNEALING, oldValue, annealedValue);
}
}
Greetings,
I have been studying Obserser/Observable implementation to Model-View-Controller.
I may also misused the pattern but here's what I've done so far.
In my code. When Submit was press, it triggers the makeChange() of the Model.
But never triggers the update() of Testing.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Testing implements Observer {
public Testing() {
model.addObserver(this);
loadListener1();
}
private void loadListener1() {
view1.submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model = new Model(view1.data1Field.getText(), view1.data2Field.getText());
model.makeChange();
model.notifyObservers();
}
});
}
public void update(Observable o, Object arg) { System.out.println("Notify - Observer"); }
public static void main(String[] a) { Testing testing = new Testing(); }
private View view1 = new View("1");
private Model model = new Model();
}
class View extends JFrame {
public View(String frame) {
super("Frame: " + frame);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
setVisible(true);
setLayout(new GridLayout(3, 2));
add(data1Label); add(data1Field);
add(data2Label); add(data2Field);
add(submitButton); add(cancelButton);
}
private final JLabel data1Label = new JLabel("Data1");
private final JLabel data2Label = new JLabel("Data2");
public final JTextField data1Field = new JTextField();
public final JTextField data2Field = new JTextField();
public final JButton submitButton = new JButton("Submit");
public final JButton cancelButton = new JButton("Cancel");
}
class Model extends Observable {
public Model() { }
public Model(String data1, String data2) {
setData1(data1);
setData2(data2);
}
public String getData1() { return data1; }
public final void setData1(String data1) { this.data1 = data1; }
public String getData2() { return data2; }
public final void setData2(String data2) { this.data2 = data2; }
public void makeChange() {
setChanged();
notifyObservers();
System.out.println("Notify - Observable");
}
private String data1;
private String data2;
}
Can you guide me thru?
Your reply is highly appreciated.
Thanks,
Cyril H.
In constructor of clas Testing your register itself to instance of Model that is created during field initialisation.
In actionPerformed method of submit button you creatd a new instance of Model and later call on this new instance the method notifyObservers which has no registered observers!
Try this code:
private void loadListener1() {
view1.submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setData1(view1.data1Field.getText()),
model.setData2(view1.data2Field.getText());
model.makeChange();
}
});
}