I'm in the process of making a GUI where I input a string into a text box and, once I click a Jbutton, a second text box will produce the string I inputted into the first or produce a random string from a method I created (public void associate()). When I run the GUI and click the button to produce the text in the second text box, everything works fine. However, when I click the button a second time so the GUI performs the same action, nothing happens. Is there anything I can do so that I don't have to close the GUI every time I wish to run it multiple times?
public class GUIWindow extends JFrame {
private Joketeller robot= new Joketeller();
private JLabel speakerlabel = new JLabel("Joke");
private JLabel MarcoLabel= new JLabel ("Marco");
private JTextField speakerfield= new JTextField ("Enter Joke Here");
private JTextField Marcofield= new JTextField ("",20);
private JButton Jokebutton=new JButton("Recite Joke >>>");
public GUIWindow() {
JPanel dataPanel= new JPanel(new GridLayout(2,2,12,16));
dataPanel.add(speakerlabel);
dataPanel.add(MarcoLabel);
dataPanel.add(speakerfield);
dataPanel.add(Marcofield);
JPanel buttonPanel= new JPanel();
buttonPanel.add(Jokebutton);
Container container = getContentPane();
container.add(dataPanel,BorderLayout.CENTER);
container.add(buttonPanel,BorderLayout.SOUTH);
Jokebutton.addActionListener(new JokeListener());
}
private class JokeListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String input=speakerfield.getText();
if (Jokebutton.isEnabled()) {
robot.setJoke(input);
String Response= robot.getResponse();
Marcofield.setText(Response);}
Joketeller class:
public class Joketeller {
private static String Marco;
private static String Response;
static int i= (int)(Math.random()*((5-1)+1)+1);
static String r;
public void setMarco(String Joke ) {
Marco=Joke;
}
public void setJoke(String Joke) {
Marco=Joke;
associate();
}
public String getJoke() {
return Marco;
}
public static String getMarco() {
return Marco;
}
public static void associate(){
if(i==1)
r= "Connect Angie";
else if(i==2)
r= "*Cloud Laugh*";
else if(i==3)
r= "Community";
else if(i==4)
r=getMarco();
else if(i==5)
r= "Indeed!";
Response=r;
}
public String getResponse() {
return Response;
}
}
Any help is appreciated. Thank you.
The first thing that jumps out at me, is the overuse of static...
public class Joketeller {
private static String Marco;
private static String Response;
static int i= (int)(Math.random()*((5-1)+1)+1);
static String r;
This is not helping your here, and if done right, shouldn't be needed.
The next issue is with i...
static int i = (int) (Math.random() * ((5 - 1) + 1) + 1);
public static void associate() {
if (i == 1) {
r = "Connect Angie";
} else if (i == 2) {
r = "*Cloud Laugh*";
} else if (i == 3) {
r = "Community";
} else if (i == 4) {
r = getMarco();
} else if (i == 5) {
r = "Indeed!";
}
Response = r;
}
i is never changed. Because it's static, you can create as many instance of Joketeller as you like and it will need change, so the response will always be the same.
While there are a number of possible ways to fix it, the simplest would be to remove all the static and make i a local variable within associate, as it's really not used anywhere else..
public void associate() {
int rnd = (int) (Math.random() * ((5 - 1) + 1) + 1);
if (rnd == 1) {
r = "Connect Angie";
} else if (rnd == 2) {
r = "*Cloud Laugh*";
} else if (rnd == 3) {
r = "Community";
} else if (rnd == 4) {
r = getMarco();
} else if (rnd == 5) {
r = "Indeed!";
}
response = r;
}
This means you don't need to create a new instance of Joketeller in order to get a different response.
For example....
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GUIWindow extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GUIWindow wnd = new GUIWindow();
wnd.pack();
wnd.setLocationRelativeTo(null);
wnd.setVisible(true);
}
});
}
private Joketeller robot = new Joketeller();
private JLabel speakerlabel = new JLabel("Joke");
private JLabel marcoLabel = new JLabel("Marco");
private JTextField speakerfield = new JTextField("Enter Joke Here");
private JTextField marcofield = new JTextField("", 20);
private JButton jokebutton = new JButton("Recite Joke >>>");
public GUIWindow() {
JPanel dataPanel = new JPanel(new GridLayout(2, 2, 12, 16));
dataPanel.add(speakerlabel);
dataPanel.add(marcoLabel);
dataPanel.add(speakerfield);
dataPanel.add(marcofield);
JPanel buttonPanel = new JPanel();
buttonPanel.add(jokebutton);
Container container = getContentPane();
container.add(dataPanel, BorderLayout.CENTER);
container.add(buttonPanel, BorderLayout.SOUTH);
jokebutton.addActionListener(new JokeListener());
}
private class JokeListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String input = speakerfield.getText();
if (jokebutton.isEnabled()) {
robot.setJoke(input);
String Response = robot.getResponse();
marcofield.setText(Response);
}
}
}
public class Joketeller {
private String marco;
private String response;
private String r;
public void setMarco(String Joke) {
marco = Joke;
}
public void setJoke(String Joke) {
marco = Joke;
associate();
}
public String getJoke() {
return marco;
}
public String getMarco() {
return marco;
}
public void associate() {
int rnd = (int) (Math.random() * ((5 - 1) + 1) + 1);
if (rnd == 1) {
r = "Connect Angie";
} else if (rnd == 2) {
r = "*Cloud Laugh*";
} else if (rnd == 3) {
r = "Community";
} else if (rnd == 4) {
r = getMarco();
} else if (rnd == 5) {
r = "Indeed!";
}
response = r;
}
public String getResponse() {
return response;
}
}
}
Related
I am making a stock market simulator and I keep getting an error from each of my 3 classes the first class MYOSM the error is:
"Cannot find symbol- class stock"
The second class MarketTable outputs:
Cannot find MarketDataModel
And the third class MarketDataModel outputs the error:
Cannot find symbol- class stock
Have I gone wrong somewhere in my code I have checked it multiple times and I can't seem to locate it.
Here is my code:
MYOSM class:
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class MYOSM extends JFrame implements Runnable {
Stock[] market = {
new Stock("JTree", 14.57),
new Stock("JTable", 17.44),
new Stock("JList", 16.44),
new Stock("JButton", 7.21),
new Stock("JComponent", 27.40)
};
boolean monitor;
Random rg = new Random();
Thread runner;
public MYOSM() {
// Not meant to be shown as a real frame
super("Thread only version . . .");
runner = new Thread(this);
runner.start();
}
public MYOSM(boolean monitorOn) {
super("Stock Market Monitor");
setSize(400, 100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
monitor = monitorOn;
getContentPane().add(new JLabel("Trading is active. " +
"Close this window to close the market."),
BorderLayout.CENTER);
runner = new Thread(this);
runner.start();
}
public void run() {
while(true) {
int whichStock = Math.abs(rg.nextInt()) % market.length;
double delta = rg.nextDouble() - 0.4;
market[whichStock].update(delta);
if (monitor) {
market[whichStock].print();
}
try {
Thread.sleep(1000);
}
catch(InterruptedException ie) {
}
}
}
public Stock getQuote(int index) {
return market[index];
}
// This method returns the list of all the symbols in the market table
public String[] getSymbols() {
String[] symbols = new String[market.length];
for (int i = 0; i < market.length; i++) {
symbols[i] = market[i].symbol;
}
return symbols;
}
public static void main(String args[]) {
MYOSM myMarket = new MYOSM(args.length > 0);
myMarket.setVisible(true);
}
}
MarketTable class:
import java.awt.*;
import javax.swing.*;
public class MarketTable extends JFrame {
public MarketTable() {
super("Dynamic Data Test");
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
MarketDataModel mdm = new MarketDataModel(5);
mdm.setStocks(new int[] { 0, 1, 2 });
JTable jt = new JTable(mdm);
JScrollPane jsp = new JScrollPane(jt);
getContentPane().add(jsp, BorderLayout.CENTER);
}
public static void main(String args[]) {
MarketTable mt = new MarketTable();
mt.setVisible(true);
}
}
MarketDataModel class:
import javax.swing.table.*;
import javax.swing.*;
public class MarketDataModel extends AbstractTableModel
implements Runnable {
Thread runner;
MYOSM market;
int delay;
public MarketDataModel(int initialDelay) {
market = new MYOSM();
delay = initialDelay * 1000;
Thread runner = new Thread(this);
runner.start();
}
Stock[] stocks = new Stock[0];
int[] stockIndices = new int[0];
String[] headers = {"Symbol", "Price", "Change", "Last updated"};
public int getRowCount() { return stocks.length; }
public int getColumnCount() { return headers.length; }
public String getColumnName(int c) { return headers[c]; }
public Object getValueAt(int r, int c) {
switch(c) {
case 0:
return stocks[r].symbol;
case 1:
return new Double(stocks[r].price);
case 2:
return new Double(stocks[r].delta);
case 3:
return stocks[r].lastUpdate;
}
throw new IllegalArgumentException("Bad cell (" + r + ", " + c +")");
}
public void setDelay(int seconds) { delay = seconds * 1000; }
public void setStocks(int[] indices) {
stockIndices = indices;
updateStocks();
fireTableDataChanged();
}
public void updateStocks() {
stocks = new Stock[stockIndices.length];
for (int i = 0; i < stocks.length; i++) {
stocks[i] = market.getQuote(stockIndices[i]);
}
}
public void run() {
while(true) {
updateStocks();
fireTableRowsUpdated(0, stocks.length - 1);
try { Thread.sleep(delay); }
catch(InterruptedException ie) {}
}
}
}
You're missing a Stock class there. Should be something like this I suppose:
public class Stock {
public Stock(String string, double d) {
this.symbol = string;
this.price = d;
}
public String symbol;
public double price;
public double delta;
public String lastUpdate;
public void print() {
System.out.println(this);
}
public void update(double delta2) {
this.delta = delta2;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Stock [symbol=").append(symbol).append(", price=").append(price).append(", delta=").append(delta).append(", lastUpdate=")
.append(lastUpdate).append("]");
return builder.toString();
}
}
Or is it just in a different package than those classes?
Also it's weird your error message has "stock" in lowercase.
With the Stock class added as above, I have managed to start your code, but I'm not sure what it was supposed to be doing. I must note it is poorly written in general, with some basic mistakes like usage of default package.
So I am trying to highlight the keywords in java,which I have stored in a text file, as the user opens a .java file or writes to .java file. I think I know how to tell if the file is of the right type. However, I do not know how to change the color of certain keywords. If anyone could help out that would be great because right now it's pretty confusing. I was wondering if I could use my replace function somehow. I have tried to go about trying to do this with the few methods I have, yet it's still not clear. I have taken out he majority of the methods and listeners, just know they are there but kept out to make it easier to read.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
import java.util.Scanner;
import java.io.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.Highlighter.HighlightPainter;
import javax.swing.text.JTextComponent;
import java.net.URI;
import java.util.*;
public class MyTextEditor extends JFrame implements ActionListener
{
private JPanel panel = new JPanel(new BorderLayout());
private JTextArea textArea = new JTextArea(0,0);
private static final Color TA_BKGRD_CL = Color.BLACK;
private static final Color TA_FRGRD_CL = Color.GREEN;
private static final Color TA_CARET_CL = Color.WHITE;
private JScrollPane scrollPane;
private MenuBar menuBar = new MenuBar();
public MyTextEditor()
{
this.setSize(750,800);
this.setTitle("Zenith");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea.setFont(new Font("Consolas", Font.BOLD, 14));
textArea.setForeground(TA_FRGRD_CL);
textArea.setBackground(TA_BKGRD_CL);
textArea.setCaretColor(TA_CARET_CL);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVisible(true);
textArea.add(scrollPane,BorderLayout.EAST);
final LineNumberingTextArea lineNTA = new LineNumberingTextArea(textArea);
DocumentListener documentListen = new DocumentListener()
{
public void insertUpdate(DocumentEvent documentEvent)
{
lineNTA.updateLineNumbers();
}
public void removeUpdate(DocumentEvent documentEvent)
{
lineNTA.updateLineNumbers();
}
public void changedUpdate(DocumentEvent documentEvent)
{
lineNTA.updateLineNumbers();
}
};
textArea.getDocument().addDocumentListener(documentListen);
// Line numbers
lineNTA.setBackground(Color.BLACK);
lineNTA.setForeground(Color.WHITE);
lineNTA.setFont(new Font("Consolas", Font.BOLD, 13));
lineNTA.setEditable(false);
lineNTA.setVisible(true);
textArea.add(lineNTA);
scrollPane.setVisible(true);
scrollPane.add(textArea);
getContentPane().add(scrollPane);
}
public void findKeyWords(String ext)
{
ArrayList<String> wordsInTA = new ArrayList<String>();
int index = 0;
if(ext == "java")
{
for(String line : textArea.getText().split(" "))
{
wordsInTA.add(line);
index++;
}
try
{
while(index>0)
{
String temp = wordsInTA.get(index);
boolean isKeyWord = binarySearch(temp);
if(isKeyWord)
{
//Code that has not yet been made
}
index--;
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
private ArrayList<String> loadJavaWords() throws FileNotFoundException
{
ArrayList<String> javaWords = new ArrayList<String>();
Scanner scan = new Scanner(new File("JavaKeyWords.txt"));
while(scan.hasNext())
{
javaWords.add(scan.next());
}
scan.close();
return javaWords;
}
private boolean binarySearch(String word) throws FileNotFoundException
{
ArrayList<String> javaWords = loadJavaWords();
int min = 0;
int max = javaWords.size()-1;
while(min <= max)
{
int index = (max + min)/2;
String guess = javaWords.get(index);
int result = word.compareTo(guess);
if(result == 0)
{
return true;
}
else if(result > 0)
{
min = index +1;
}
else if(result < 0)
{
max = index -1;
}
}
return false;
}
public void replace()
{
String wordToSearch = JOptionPane.showInputDialog(null, "Word to replace:");
String wordToReplace = JOptionPane.showInputDialog(null, "Replacement word:");
int m;
int total = 0;
int wordLength = wordToSearch.length();
for (String line : textArea.getText().split("\\n"))
{
m = line.indexOf(wordToSearch);
if(m == -1)
{
total += line.length() + 1;
continue;
}
String newLine = line.replaceAll(wordToSearch, wordToReplace);
textArea.replaceRange(newLine, total, total + line.length());
total += newLine.length() + 1;
}
}
public static void main(String args[])
{
MyTextEditor textEditor = new MyTextEditor();
textEditor.setVisible(true);
}
}
My program generates random numbers from 0 to 12 but if the result is 12 it would set dash as the text of JLabel, instead of the number generated.
Now, I wanted to sort my JPanel in ascending order based on the JLabel contents. In case of similarities in numbers, the black JPanels are placed on the left. It works fine except when there are dashes included, in which it doesn't sort properly. I would like to insert the JPanels containing dashes anywhere but it's not working as expected.
Screencaps from a shorter version of my program:
Pure numbers:
Dash included:
Here's the shorter version of my code (using the logic of integer sorting):
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Comparator;
public class SortFrames extends JFrame
{
static ArrayList<JPanel> panels = new ArrayList<JPanel>();
JPanel panel = new JPanel();
JPanel sortPane = new JPanel();
int toWrite = 0;
int colorGen = 0;
int comparison = 0;
Random rand = new Random();
public SortFrames()
{
for(int i = 0; i<4;i++)
{
panels.add(new JPanel());
}
for(JPanel p: panels)
{
toWrite = rand.nextInt(13);
colorGen = rand.nextInt(2);
p.add(new JLabel());
JLabel lblToSet = (JLabel)p.getComponent(0);
if(colorGen == 0)
{
p.setBackground(Color.BLACK);
lblToSet.setForeground(Color.WHITE);
}
if(colorGen == 1)
{
p.setBackground(Color.WHITE);
lblToSet.setForeground(Color.BLACK);
}
if(toWrite != 12){lblToSet.setText("" +toWrite);}
if(toWrite == 12){lblToSet.setText("-");}
p.setPreferredSize(new Dimension(30, 30));
panel.add(p);
}
sortMethod();
for(JPanel p: panels)
{
panel.add(p);
panel.revalidate();
}
add(panel);
panel.setPreferredSize(new Dimension(300, 300));
setPreferredSize(new Dimension(300, 300));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
pack();
setLocationRelativeTo(null);
}
public void sortMethod()
{
for(int i = 0; i<(panels.size());i++)
{
for(int j = i+1; j<(panels.size());j++)
{
JLabel one = (JLabel)(panels.get(i)).getComponent(0);
JLabel two = (JLabel)(panels.get(j)).getComponent(0);
String lblOne = one.getText();
String lblTwo = two.getText();
if(!lblOne.equals("-") && !lblTwo.equals("-"))
{
int comp1 = Integer.parseInt(lblOne);
int comp2 = Integer.parseInt(lblTwo);
JPanel pnl1 = panels.get(i);
JPanel pnl2 = panels.get(j);
if(comp1 == comp2)
{
if(pnl1.getBackground() == Color.BLACK && pnl2.getBackground() == Color.WHITE)
{
panels.set(i, pnl1);
panels.set(j, pnl2);
}
if(pnl1.getBackground() == Color.WHITE && pnl2.getBackground() == Color.BLACK)
{
panels.set(i, pnl2);
panels.set(j, pnl1);
}
}
if(comp1 != comp2)
{
if(comp1>comp2)
{
panels.set(i, pnl2);
panels.set(j, pnl1);
}
}
}
if(lblOne.equals("-") && !lblTwo.equals("-"))
{
JPanel pnl1 = panels.get(i);
panels.set(rand.nextInt(panels.size()), pnl1);
}
if(!lblOne.equals("-") && lblTwo.equals("-"))
{
JPanel pnl2 = panels.get(j);
panels.set(rand.nextInt(panels.size()), pnl2);
}
}
}
}
public static void main(String args[])
{
new SortFrames();
}
}
I also have another method, which is by using Comparator class which also creates the same problem (this sorts equal numbers based on foreground but still the same as to sort equal numbers based on background so it has no effect on the said issue).
private static class JPanelSort implements Comparator<JPanel>
{
#Override
public int compare(JPanel arg0, JPanel arg1)
{
JLabel one = ((JLabel) arg0.getComponent(0));
JLabel two = ((JLabel) arg1.getComponent(0));
String firstContent = one.getText();
String secondContent = two.getText();
try
{
comparisonRes = Integer.compare(Integer.parseInt(firstContent), Integer.parseInt(secondContent));
if(comparisonRes == 0)
{
if(one.getForeground() == Color.BLACK && two.getForeground() == Color.WHITE)
{
comparisonRes = 1;
}
if(two.getForeground() == Color.BLACK && one.getForeground() == Color.WHITE)
{
comparisonRes = -1;
}
}
}
catch(NumberFormatException e)
{
comparisonRes = 0;
}
return comparisonRes;
}
}
Please tell me your ideas. Thank you.
It's much easier to sort data than to sort JPanels.
Here's mu GUI displaying your numbers.
So, lets create a Java object to hold the card data.
public class DataModel {
private final int number;
private final int colorNumber;
private final Color backgroundColor;
private final Color foregroundColor;
public DataModel(int number, int colorNumber, Color backgroundColor,
Color foregroundColor) {
this.number = number;
this.colorNumber = colorNumber;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public int getNumber() {
return number;
}
public int getColorNumber() {
return colorNumber;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
}
Pretty straightforward. We have fields to hold the information and getters to retrieve the information. We can make all the fields final since we're not changing anything once we set the values.
The sort class is pretty simple as well.
public class DataModelComparator implements Comparator<DataModel> {
#Override
public int compare(DataModel o1, DataModel o2) {
if (o1.getNumber() < o2.getNumber()) {
return -1;
} else if (o1.getNumber() > o2.getNumber()) {
return 1;
} else {
if (o1.getColorNumber() < o2.getColorNumber()) {
return -1;
} else if (o1.getColorNumber() > o2.getColorNumber()) {
return 1;
} else {
return 0;
}
}
}
}
Since we keep the color number, sorting by color is as easy as sorting a number.
Now that we've moved the data to it's own List, we can concentrate on creating the GUI.
package com.ggl.testing;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SortFrames implements Runnable {
private List<DataModel> dataModels;
private JPanel[] panels;
private JLabel[] labels;
private Random random = new Random();
public SortFrames() {
this.dataModels = new ArrayList<>();
this.random = new Random();
for (int i = 0; i < 4; i++) {
int number = random.nextInt(13);
int colorNumber = random.nextInt(2);
Color backgroundColor = Color.BLACK;
Color foregroundColor = Color.WHITE;
if (colorNumber == 1) {
backgroundColor = Color.WHITE;
foregroundColor = Color.BLACK;
}
dataModels.add(new DataModel(number, colorNumber, backgroundColor,
foregroundColor));
}
Collections.sort(dataModels, new DataModelComparator());
}
#Override
public void run() {
JFrame frame = new JFrame("Sort Frames");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
panels = new JPanel[dataModels.size()];
labels = new JLabel[dataModels.size()];
for (int i = 0; i < dataModels.size(); i++) {
DataModel dataModel = dataModels.get(i);
panels[i] = new JPanel();
panels[i].setBackground(dataModel.getBackgroundColor());
labels[i] = new JLabel(getDisplayText(dataModel));
labels[i].setBackground(dataModel.getBackgroundColor());
labels[i].setForeground(dataModel.getForegroundColor());
panels[i].add(labels[i]);
mainPanel.add(panels[i]);
}
frame.add(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
private String getDisplayText(DataModel dataModel) {
if (dataModel.getNumber() == 12) {
return "-";
} else {
return Integer.toString(dataModel.getNumber());
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new SortFrames());
}
public class DataModel {
private final int number;
private final int colorNumber;
private final Color backgroundColor;
private final Color foregroundColor;
public DataModel(int number, int colorNumber, Color backgroundColor,
Color foregroundColor) {
this.number = number;
this.colorNumber = colorNumber;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public int getNumber() {
return number;
}
public int getColorNumber() {
return colorNumber;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
}
public class DataModelComparator implements Comparator<DataModel> {
#Override
public int compare(DataModel o1, DataModel o2) {
if (o1.getNumber() < o2.getNumber()) {
return -1;
} else if (o1.getNumber() > o2.getNumber()) {
return 1;
} else {
if (o1.getColorNumber() < o2.getColorNumber()) {
return -1;
} else if (o1.getColorNumber() > o2.getColorNumber()) {
return 1;
} else {
return 0;
}
}
}
}
}
The lessons to be learned here are:
Separate the data from the view.
Focus on one part of the problem at a time. Divide and conquer.
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.
package game;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JOptionPane;
public interface Listeners
{
static PatternGame game = new PatternGame();
InputGame game2 = new InputGame();
static class inst implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if ("inst".equals(e.getActionCommand()))
{
}
}
}
static class play implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if ("play".equals(e.getActionCommand()))
{
menu.mf.dispose();
PatternGame.gameStart();
}
}
}
static class exit implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if ("exit".equals(e.getActionCommand()))
{
System.exit(0);
}
}
}
static class input implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (InputGame.numOfClicks != 0)
{
InputGame.button = (JButton) e.getSource();
InputGame.button.setText("X");
InputGame.numOfClicks--;
}
else
{
if (InputGame.checkCorrect())
{
JOptionPane.showConfirmDialog(null, "Would you like another pattern?");
PatternGame.order++;
PatternGame.gameStart();
}
else
{
JOptionPane.showMessageDialog(null, "Incorrect!");
menu.start();
}
}
}
}
}
package game;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class InputGame implements Properties,Listeners{
public static JFrame gf = new JFrame();
public static JButton button = new JButton();
public static int height = 800;
public static int width = 600;
public static int gsize = 4;
public static int order =1;
public static Dimension size = new Dimension(height,width);
public static menu Menu = new menu();
public static GridLayout Ggrid = new GridLayout(gsize,gsize);
public static int numOfClicks =0;
public static int numCorrect=0;
public static int[][] input = new int[][]{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};
//public static Thread d;
public static void setup() {
gf.dispose();
gf = new JFrame();
gf.setLocation(300,100);
gf.setSize(size);
gf.setResizable(false);
gf.setLayout(Ggrid);
gf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PatternGame.clear();
blank();
gf.setVisible(true);
System.out.print(numOfClicks);
}
public static void blank()
{
for (int a =0;a<4;a++)
{
for (int b =0;b<4;b++)
{
button = new JButton("");
button.setActionCommand("");
button.addActionListener(new input());
gf.add(button);
}
}
}
public static void input()
{
for (int a=0;a<4;a++)
{
for(int b=0;b<4;b++)
{
String x = button.getText();
if (x.equals("X"))
{
input[a][b] = 1;
}
else if (x.equals(""))
{
input[a][b] = 0;
}
System.out.println(input[a][b]);
}
}
}
public static boolean checkCorrect()
{
input();
for (int a=0;a<4;a++)
{
for(int b=0;b<4;b++)
{
if (order == 1)
{
if (handlebars[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
if (order == 2)
{
if (ys[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
if (order == 3)
{
if (spaceShip[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
if (order == 4)
{
if (flock[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
if (order == 5)
{
if (percent[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
if (order == 6)
{
if (square[a][b] == 1)
{
JButton button = new JButton("X");
InputGame.numOfClicks++;
}
else
{
JButton button = new JButton("");
}
}
}
}
return false;
}
}
Ok, this is my code. Now what I want the program to accomplish is for the program to display the blank screen(which I have done) then when the user clicks one of the buttons and it places a X on that button. Then after 6 clicks for the program to translate the pattern they put in to the input array, so I can compare the input array to the pattern array, and be able to tell the user if its correct or not and move on. What this program does now is it displays the blank screen then when a button is pressed it displays the X. I got it to check for one button but I don't know how to check for all of them. So how could I check each button for the text it holds.
You can call getComponents() on the parent container- whether panel, frame or window and then check if it is an instance of button, then check the text set on it like this:
Component[] comps = parent.getComponents();
for(Component c:comps){
if(c instanceof JButton){
JButton btn = (JButton) c;
String text = btn.getText();
//Use text for whatever, add it to an array or something
}
}
Hope you get the idea