Java: NullPointerException thrown when JButton is clicked in the Flash Card Game - java

Details: It's a Flash Card game, each Card has question and answer.
QuizCard is the class of Cards having functions like getQuestion(), getAnswer(), setQuestion(), setAnswer() and two String Instances as question and answer. A parameterised constructor takes two strings, first as question and second as answer.
I saved questions and answers in a text file, where question and answer is separated by a "/". All new questions start from a new line.
E.g. -> What is the Capital of India?/New Delhi
Where is the Taj Mahal?/Agra
Rest of the code can be easily understood.
Problem: When the "nextButton" is clicked it throws a NullPointerException and doesn't change the text on the "nextButton".
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class QuizCardPlayer
{
private JFrame frame;
private JTextArea display;
private boolean isAnswer = true;
private JButton nextButton;
private ArrayList<QuizCard> cardList;
private int currentCardIndex;
public static void main(String[] args)
{
QuizCardPlayer player = new QuizCardPlayer();
player.go();
}
public void go()
{
frame = new JFrame("Quiz Card Player");
display = new JTextArea(6,20);
JPanel mainPanel = new JPanel();
Font bigFont = new Font("serif", Font.BOLD, 24);
display.setFont(bigFont);
JScrollPane scroller = new JScrollPane(display);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
display.setText("Lets Start!");
JButton nextButton = new JButton("Show Question");
mainPanel.add(scroller);
mainPanel.add(nextButton);
nextButton.addActionListener(new NextButtonListener());
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem loadMenuItem = new JMenuItem("Load card set");
loadMenuItem.addActionListener(new LoadMenuListener());
fileMenu.add(loadMenuItem);
menuBar.add(fileMenu);
frame.setJMenuBar(menuBar);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setVisible(true);
frame.setSize(300,300);
}
public class NextButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.print("Called!!");
if(isAnswer)
{
nextButton.setText("Show Answer");
if( currentCardIndex < cardList.size() )
{
display.setText(cardList.get(currentCardIndex).getQuestion());
isAnswer = false;
}
else
{
display.setText("That was last Card.");
nextButton.setEnabled(false);
}
}
else
{
nextButton.setText("Next Card");
display.setText(cardList.get(currentCardIndex).getAnswer());
isAnswer = true;
currentCardIndex++;
}
}
}
public class LoadMenuListener implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
JFileChooser openFile = new JFileChooser();
openFile.showOpenDialog(frame);
loadFile(openFile.getSelectedFile());
}
}
public void loadFile(File loadFile)
{
try
{
BufferedReader reader = new BufferedReader(new FileReader(loadFile));
String line="";
cardList = new ArrayList<QuizCard>();
while( (line = reader.readLine()) != null )
{
String[] result = line.split("/");
QuizCard card = new QuizCard(result[0] , result[1]);
cardList.add(card);
currentCardIndex=0;
}
reader.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
I am novice in Java having a experience of just one month, any suggestion is most welcome.

You are creating nextButton as an instance variable of class QuizCardPlayer, but inside go() method, you initializing the local variable nextButton and adding Listener to this local copy, and adding this local copy of nextButton to the mainPanel (which is visible on the VIEW ).
Though the instance variable remains null, as you never did assigned it to anythingy, and you trying to access this null variable inside NextButtonListener class, as follows:
nextButton.setText("Show Answer");
EDIT 1:
Simply replace this line inside go () method:
JButton nextButton = new JButton("Show Question");
to
nextButton = new JButton("Show Question");
This will work :-)

Related

how can i make save button work by writing this code?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class DiceFrame extends JFrame{
ImageIcon[] dice_im = new ImageIcon[7];
String score="start";
JPanel mainPanel= new JPanel();
JPanel scorePanel=new JPanel();
JPanel buttonPanel =new JPanel();
JLabel picLabel = new JLabel();
JTextArea scorefield = new JTextArea();
JButton roll= new JButton("roll the dice");
JButton save = new JButton("save");
ActionListener action;
ActionListener output;
public DiceFrame(){
super();
setSize(600, 600);
setTitle("Dice Program");
loadImage();
getContentPane().add(mainPanel, BorderLayout.CENTER);
getContentPane().add(scorePanel, BorderLayout.EAST);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
buttonPanel.add(save);
buttonPanel.add(roll);
mainPanel.add(picLabel);
picLabel.setIcon(dice_im[0]);
scorePanel.add(scorefield);
scorefield.setText(score);
action = new DiceActionListener();
roll.addActionListener(action);
}
private void loadImage(){
dice_im [0]= new ImageIcon("1.jpg");
dice_im[1] = new ImageIcon("2.jpg");
dice_im[2] = new ImageIcon("3.JPG");
dice_im[3] = new ImageIcon("4.JPG");
dice_im[4] = new ImageIcon("5.JPG");
dice_im[5] = new ImageIcon("6.JPG");
}
public static void main(String args[]){
DiceFrame frame = new DiceFrame();
frame.setDefaultLookAndFeelDecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class DiceActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Random rg = new Random();
int k = rg.nextInt(6) + 1;
picLabel.setIcon(dice_im[k]);
}
}
class SaveActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) { //NEW code
String out_file_name = "dice_score.txt";
try {
File outputfile = new File(out_file_name);
PrintStream out = new PrintStream(
new FileOutputStream(outputfile));
out.println(score);
out.flush();`
out.close();
} catch (IOException y) {
System.out.println("IO problem.");
}
}
}
}
How can i make save button work by writing this code?
Whenever i run it roll button works but the save button doesn't work?
this is a program for the rolling the dice but i need to make the save button work, Can anyone please help with that?
how can i link dice_score.txt file to this program?
Action listener is not added to Save Button.
save.addActionListener(new SaveActionListener());
Add this at the end of DiceFrame():
save.addActionListener(new SaveActionListener());
See
action = new DiceActionListener();
roll.addActionListener(action);
well you have to follow this pattern and do
SaveActionListener action2 = new SaveActionListener ();
save.addActionListener(action2);
Although in reality it is not necessary to create a named instance and you can simply do
save.addActionListener (new SaveActionListener ());

Java - Broken JLabel after proper disposal of different JFrame

I'm currently making our project and I'm having problem reseting JLabel back to "0". Here's the code
main code snippet (check note 1 for frame disposal method used):
import javax.swing.*; //import library
import java.awt.event.*;
import java.awt.*;
import java.util.*;
public class draft_main //class name
{
public static void main(String[] args)
{ //method name
JFrame f0 = new JFrame("POS"); //frame
JPanel p0 = new JPanel(); //panel inside the frame
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
JPanel p6 = new JPanel();
JPanel p7 = new JPanel();
JLabel l0 = new JLabel("Amount:"); //label inside the panel
JLabel l1 = new JLabel("0");
JLabel l2 = new JLabel("Menu Code: ");
JLabel l3 = new JLabel("--Menu--");
JTextField tf0 = new JTextField("", 12); //user input for menu code
JButton b0 = new JButton("Checkout"); //buttons
JButton b1 = new JButton("Cancel");
JButton b2 = new JButton("Exit");
JButton b4 = new JButton("Accept");
JButton b7 = new JButton("Remove");
JOptionPane jop = new JOptionPane(); //JOptionPane
JTextField tf1 = new JTextField("1. Hot Pockets Pizza", 20); //list of menu
JTextField tf2 = new JTextField("2. Burger with Fries", 20);
JTextField tf3 = new JTextField("3. Sticky Rice (Bico)", 20);
ArrayList<String> ar = new ArrayList<String>(); //list of array
try{
b4.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) //what the accept button does
{
String order = tf0.getText(), tots="", temp="";
int o = Integer.parseInt(order);
int tot=0;
switch(o) //menu choice
{
case 1 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+250; tots = Integer.toString(tot); l1.setText(tots); ar.add("Hot Pockets Pizza"); break;
case 2 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+65; tots = Integer.toString(tot); l1.setText(tots); ar.add("Burger with Fries"); break;
case 3 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+12; tots = Integer.toString(tot); l1.setText(tots); ar.add("Sticky Rice (Bico)"); break;
default : jop.showMessageDialog(null, "Menu code not listed in menu", "Error", jop.INFORMATION_MESSAGE); break;
}
}
});
b0.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) //what the checkout button does
{
JFrame f1 = new JFrame("Checkout");
JFrame f2 = new JFrame("Order");
JPanel p8 = new JPanel();
JPanel p9 = new JPanel();
JPanel p10 = new JPanel();
JPanel p11 = new JPanel();
JPanel p12 = new JPanel();
JPanel p13 = new JPanel();
JPanel p14 = new JPanel();
JLabel l5 = new JLabel("Order list");
JLabel l6 = new JLabel(/*convert ArrayList to String then put here*/);
JLabel l4 = new JLabel("Cash");
JTextField tf4 = new JTextField("", 14);
JButton b5 = new JButton("Accept");
JButton b6 = new JButton("Cancel");
JButton b7 = new JButton("Ok");
b5.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String cas = l1.getText(), in = tf4.getText();
int cash = Integer.parseInt(cas), inp = Integer.parseInt(in), cahs=0;
if(cash>inp)
{
jop.showMessageDialog(null, "Insufficient funds", "Lacking cash? Work for it.", jop.INFORMATION_MESSAGE);
}
else if(cash<inp)
{
cahs = inp - cash;
jop.showMessageDialog(null, "Change: " +cahs+". Thank you");
f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
}
else if(cash==inp)
{
jop.showMessageDialog(null, "Thank you.", "Thank you.", jop.INFORMATION_MESSAGE);
f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
}
}
});
b6.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
}
});
b7.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
f2.dispatchEvent(new WindowEvent(f2, WindowEvent.WINDOW_CLOSING));
}
});
p9.add(l0);
p9.add(l1);
p10.add(l4);
p10.add(tf4);
p11.add(b5);
p11.add(b6);
p12.add(l5);
p12.add(l6);
p13.add(b7);
p14.add(p12);
p14.add(p13);
p8.add(p10);
p8.add(p11);
p8.add(p9);
f1.add(p8);
f1.pack();
f1.setSize(240,170);
f1.setLocationRelativeTo(null);
f1.setResizable(false);
f1.setDefaultCloseOperation(f1.DISPOSE_ON_CLOSE);
f1.setVisible(true);
f2.add(p14);
f2.pack();
f2.setSize(270,100);
f2.setResizable(false);
f2.setLocationRelativeTo(null);
f2.setDefaultCloseOperation(f2.DISPOSE_ON_CLOSE);
f2.setVisible(true);
}
});
b1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
l1.setText("0");
}
});
b2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
f0.dispose();
}
});
}
catch(Exception e)
{
jop.showMessageDialog(null, "Error");
}
tf1.setEditable(false);
tf2.setEditable(false);
tf3.setEditable(false);
p4.add(tf1);
p5.add(tf2);
p6.add(tf3);
p7.add(l3);
p3.add(l2);
p3.add(tf0);
p3.add(b4);
p1.add(l0);
p1.add(l1);
p2.add(b0);
p2.add(b1);
p2.add(b2);
p0.add(p3);
p0.add(p1);
p0.add(p2);
p0.add(p7);
p0.add(p4);
p0.add(p5);
p0.add(p6);
f0.add(p0);
f0.pack();
f0.setSize(303,280);
f0.setLocationRelativeTo(null);
f0.setResizable(false);
f0.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f0.setVisible(true);
}
}
what happens is when the main window opens it asks for which from the menu did a guy order then it displays the price. During checkout the user will be asked to input amount of cash given and gives change if there's any. After then the checkout frame is then "properly" disposed (so as I think so), exposing the main frame. However the JLabel does not seem to update when I place another order or clear the current order and it bothers me since the main frame is supposed to be fully interactive until the main frame is closed.
note #1: I have used different methods on how to dispose the 2nd and 3rd frame which pops up since I thought it may have been because of the dispose(); does not really destroys the frame but let's it run in the background.
note #2: yes the program is not finished yet, but those don't matter for now for those will just be some minor features of the application.
You've several problems with this code, but the major ones that I see (and I haven't gone through all of it yet, so there may be more)
First and foremost, those JFrame sub-windows shouldn't be JFrames at all, but rather should be modal JDialogs. The reason for this is this gives you complete control over program flow when these dialogs are used, since you'll then know that the main program flow will be put on hold while the modal dialog is visible, and then the flow will resume as soon as the dialog is no longer visible. This way you can query the state of the dialog after it has been dealt with, and then use this information to update your GUI.
Your amount is shown in the l1 variable, and this will never change unless you specifically call setText(...) on this variable. You don't seem to be doing it when the order has been processed. Again modal dialogs will help you with this.
Your variable naming is bad. Instead of using meaningless letters and numbers for names, use names that make sense and that make your code self-commenting. So for instance, instead of l1, use amountLabel or something similar.
Your code is one huge god class with everything stuffed into the static main method, and this makes for a debugging nightmare. Java is an object-oriented language, and if used properly OOP techniques can help you reduce program complexity making your code easier for yourself and for us to understand. Start OOP-ifying your program and you'll see immediate dividends.
And I found your bug -- you're adding the l1 JLabel to another container, and so it is effectively being removed from the original JFrame. If you minimize your original GUI and then restore it, you'll see the amount l1 JLabel disappear.
Here's some sample code not yet done, but to give you an idea about adding OOP to the program:
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Draft2 extends JPanel {
private List<MyItem> selectedItems = new ArrayList<>();
private NumberFormat formatter = NumberFormat.getCurrencyInstance();
private double total;
private JLabel totalAmountLabel = new JLabel(formatter.format(total));
private DefaultComboBoxModel<MyItem> comboModel = new DefaultComboBoxModel<>();
private JComboBox<MyItem> menuCombo = new JComboBox<>(comboModel);
public Draft2() {
// monospaced to make names and price line up
menuCombo.setFont(new Font(Font.MONOSPACED, Font.BOLD, 12));
// fill the JComboBox with items
comboModel.addElement(new MyItem("Baseball", 21.5));
comboModel.addElement(new MyItem("Bat", 50.8));
comboModel.addElement(new MyItem("Football", 22.26));
// create a JPanel to hold selection components and add components
JPanel selectionPanel = new JPanel();
selectionPanel.add(new JLabel("Menu:"));
selectionPanel.add(menuCombo);
selectionPanel.add(new JButton(new AcceptAction("Accept", KeyEvent.VK_A)));
// create a JPanel to hold the total amount information
JPanel totalAmountPanel = new JPanel();
totalAmountPanel.add(new JLabel("Total Amount:"));
totalAmountPanel.add(totalAmountLabel);
// create a JPanel to hold buttons, uses grid layout with a single row
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
btnPanel.add(new JButton(new CheckOutAction("Check Out", KeyEvent.VK_C)));
btnPanel.add(new JButton(new CancelAction("Cancel", KeyEvent.VK_N)));
btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(selectionPanel);
add(Box.createVerticalStrut(5)); // so don't crowd things
add(totalAmountPanel);
add(Box.createVerticalStrut(5));
add(btnPanel);
}
public void setTotalAmount(double total) {
totalAmountLabel.setText(formatter.format(total));
}
private class AcceptAction extends AbstractAction {
public AcceptAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
MyItem myMenuItem = (MyItem) menuCombo.getSelectedItem();
if (myMenuItem == null) {
return; // nothing selected, get out
}
selectedItems.add(myMenuItem);
double total = 0.0;
for (MyItem myItem : selectedItems) {
total += myItem.getCost();
}
setTotalAmount(total);
}
}
private class CheckOutAction extends AbstractAction {
public CheckOutAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Finish....
// open JDialog or JOptionPane
}
}
private class CancelAction extends AbstractAction {
public CancelAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Finish...
}
}
private class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My GUI Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Draft2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
class MyItem {
private NumberFormat formatter = NumberFormat.getCurrencyInstance();
private String name;
private double cost;
public MyItem(String name, double cost) {
this.name = name;
this.cost = cost;
}
public String getName() {
return name;
}
public double getCost() {
return cost;
}
#Override
public String toString() {
return String.format("%-10s %s", name, formatter.format(cost));
}
}

Cannot find a way to create a loading screen

I was just messing around with GUI in Java and created a little game. In it, 105 randomly placed buttons are created and then an instruction screen pops up, telling the user which button to find. I've tried to figure out how to program a "Loading..." JDialog, which will pop up while the buttons are being created in the background. The trouble is, when I run the program the JDialog doesn't load until AFTER all the buttons have been created, which kind of defeats the purpose of the box in the first place. How can I force the "Loading..." box to load BEFORE the buttons begin to be created??? Thanks in advance.
Because I've just been tinkering, my code is not perfect but here it is:
import java.util.Scanner;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Random;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.ProgressMonitor;
public class ButtonGame {
private static int butNum = 1;
private static JFrame frame;
private static ActionListener notIt;
private static ActionListener it;
private static Random rand = new Random();
private static int butToFind = rand.nextInt(105);
private static JFrame frameToClose;
//private static int mouseClicks;
//private static double time;
public static void main(String[] args) {
//actionlistener for all incorrect buttons (buttons that are "not it")
notIt = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component component = (Component) e.getSource();
JFrame frame5 = (JFrame) SwingUtilities.getRoot(component);
frame5.dispose();
}
};
//actionlistener for the correct button (the button that's "it")
it = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame youWin = new JFrame("YOU WON!");
//removes all panels to begin game again
JButton again = new JButton("Play again");
again.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
java.awt.Window windows[] = java.awt.Window.getWindows();
for(int i=0;i<windows.length;i++){
if (windows[i] != frame) { windows[i].dispose(); }
butToFind = rand.nextInt(105);
butNum = 1;
youWin.dispose();
}
frame.setVisible(true);
}
});
//quits game
JButton win = new JButton("Quit");
win.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//layout
youWin.setSize(775, 300);
youWin.setLayout(new FlowLayout());
JLabel label1 = new JLabel("Fantastic!");
Font font1 = new Font("Courier", Font.BOLD,120);
label1.setFont(font1);
label1.setHorizontalAlignment(JLabel.CENTER);
JLabel label2 = new JLabel("You beat the game!");
Font font2 = new Font("Courier", Font.BOLD,60);
label2.setFont(font2);
label2.setHorizontalAlignment(JLabel.CENTER);
youWin.add(label1);
youWin.add(label2);
JPanel panel = new JPanel();
youWin.add(panel);
panel.add(again);
panel.add(win);
youWin.setLocation(260, 100);
youWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
youWin.setVisible(true);
java.awt.Window windows[] = java.awt.Window.getWindows();
}
};
//start window
frame = new JFrame("Window");
frame.setLocation(400, 200);
JButton button1 = new JButton("Click to begin");
//button to begin game
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// JDialog load = new JDialog();
// load.setAlwaysOnTop(true);
// load.setSize(500,500);
// load.setVisible(true);
// load.add(new Label("Loading..."));
// load.pack();
frame.setVisible(false); // "start" window's visibility
// try {
// Thread.sleep(100000);
// } catch (Exception t) {
// }
// creates buttons
for (int i = 0; i < 105; i++) {
JFrame nextFrame = newFrame(butNum);
nextFrame.setVisible(true);
butNum++;
}
//creates instructions and tells user what button to find
JFrame instructions = new JFrame("How to play");
instructions.setSize(300,175);
instructions.setLayout(new GridLayout(4,1));
JPanel instPanel = new JPanel();
//button to remove instruction panel
JButton ok = new JButton("Ok");
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
instructions.dispose();
}
});
instPanel.add(ok);
instructions.setLocation(400,200);
//layout of instruction panel
JLabel find = new JLabel("Your goal is to find Button " + butToFind + ".");
find.setHorizontalAlignment(JLabel.CENTER);
JLabel find2 = new JLabel("Click a button to make it disappear.");
find2.setHorizontalAlignment(JLabel.CENTER);
JLabel find3 = new JLabel("Good luck!");
find3.setHorizontalAlignment(JLabel.CENTER);
instructions.add(find);
instructions.add(find2);
instructions.add(find3);
instructions.add(instPanel);
instructions.setVisible(true);
}
});
frame.add(button1);
frame.setSize(150,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//creates frame with button in it
public static JFrame newFrame(int num) {
JFrame frame2 = new JFrame();
JButton button = new JButton("Button " + num);
if (num == butToFind) {
button.addActionListener(it);
frameToClose = frame2;
} else {
button.addActionListener(notIt);
}
frame2.add(button);
frame2.setSize(randNum(90,200), randNum(50,100));
frame2.setLocation(rand.nextInt(1200), rand.nextInt(800));
frame2.getContentPane().setBackground(new Color(rand.nextInt(255),
rand.nextInt(255),
rand.nextInt(255)));
frame2.setVisible(true);
return frame2;
}
//provides random number between high and low
public static int randNum(int low, int high) {
int result = -1;
while (result < low || result > high) {
result = rand.nextInt(high);
}
return result;
}
}
Also, as a side-question, which of the variables defined before main should be static? And how can I get the program to compile without being static? Thanks!
First take a look at The Use of Multiple JFrames, Good/Bad Practice? and understand why I freaked out when I ran your code...
Instead of creating a bunch of frames, why not use something like JButton on another JPanel and add it to the current frame (this would also be a good use for a CardLayout)
JPanel panel = new JPanel(new GridLayout(10, 0));
Random rnd = new Random();
// creates buttons
for (int i = 0; i < 105; i++) {
JButton btn = new JButton(String.valueOf(i));
panel.add(btn);
//JFrame nextFrame = newFrame(butNum);
//nextFrame.setVisible(true);
//butNum++;
}
frame.getContentPane().removeAll();
frame.add(panel);
frame.revalidate();
frame.pack();
Alternatively, if you're really hell bent on using "frames", consider using a JDesktopPane and JInternalFrame instead.
See How to Use Internal Frames for more details
Also, as a side-question, which of the variables defined before main should be static? And how can I get the program to compile without being static?
As much as possible, none. Instead of trying to create the whole thing in the main method, use the classes constructor to initialise the UI and use another method to actually get the game rolling...
public class ButtonGame {
private int butNum = 1;
private JFrame frame;
private ActionListener notIt;
private ActionListener it;
private Random rand = new Random();
private int butToFind = rand.nextInt(105);
private JFrame frameToClose;
//private static int mouseClicks;
//private static double time;
public static void main(String[] args) {
ButtonGame game = new ButtonGame();
game.start();
}
public ButtonGame() {
//... All the code that was once in main...
frame.add(button1);
frame.setSize(150, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void start() {
frame.setVisible(true);
}
Answering to your side questions:
a static method can only accept static global variables
You can put all your code in the constructor and use main to only run the program.
Constructor:
public ButtonGame() {
// All of your code goes here - except the static methods
}
You should also make all other methods non-static.
To run the program:
public static void main(String[] args) {
new ButtonGame();
}

JList doesn't show on JScrollPane

I'm trying to open a text file using JFilechooser and put strings in JList. I think all the strings go into the list but I don't know why the strings don't appear on JScrollPane. Is there any problem with grouplayout? i don't know what to change..
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.List;
public class WordFinder extends JFrame implements ActionListener {
private WordList words = new WordList();
private JScrollPane scroll;
private JLabel label;
private JLabel word;
private JTextField textArea;
private JButton button;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem menuItem, menuItem2;
private JFileChooser fc;
private JList list;
static private final String newline = "\n";
private int lineCount;
public WordFinder() {
super("Word Finder");
fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
menuBar = new JMenuBar();
menu = new JMenu("File");
menuBar.add(menu);
menuItem = new JMenuItem("Open...");
menuItem.addActionListener(this);
menuItem2 = new JMenuItem("Exit");
menuItem2.addActionListener(this);
menu.add(menuItem);
menu.add(menuItem2);
setJMenuBar(menuBar);
label = new JLabel("Find: ");
word = new JLabel(lineCount + " words total");
textArea = new JTextField();
textArea.setEditable(true);
textArea.setPreferredSize(new Dimension(200, 20));
button = new JButton("Clear");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("");
}
});
scroll = makeListView();
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setPreferredSize(new Dimension(200, 230));
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addComponent(label)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(textArea)
.addComponent(word)
.addComponent(scroll))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(button)));
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(label)
.addComponent(textArea)
.addComponent(button))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(word))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
.addComponent(scroll));
setVisible(true);
pack();
// call System.exit() when user closes the window
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private JScrollPane makeListView() {
// String[] labels = {"1", "2", "3"};
// list = new JList(labels);
JScrollPane listScroller = new JScrollPane(list);
return listScroller;
}
private void updateListView(DefaultListModel listModel) {
list = new JList(listModel);
scroll = new JScrollPane(list);
}
public void actionPerformed(ActionEvent e) {
DefaultListModel listModel = new DefaultListModel();
if (e.getSource() == menuItem) {
int returnVal = fc.showOpenDialog(WordFinder.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
String fileName = file.getAbsolutePath();
try {
FileReader files = new FileReader(fileName);
BufferedReader br = new BufferedReader(files);
String str;
while((str = br.readLine()) != null) {
listModel.addElement(str);
//System.out.println(str);
lineCount++;
}
System.out.println(lineCount);
updateListView(listModel);
br.close();
} catch (Exception ex) {
ex.printStackTrace(System.out);
System.out.println("can't read file");
}
System.out.println("Opening: " + file.getName() + newline);
}
} else if (e.getSource() == menuItem2) {
setVisible(false);
dispose();
}
}
/**
* Main method. Makes and displays a WordFinder window.
* #param args Command-line arguments. Ignored.
*/
public static void main(String[] args) {
// In general, Swing objects should only be accessed from
// the event-handling thread -- not from the main thread
// or other threads you create yourself. SwingUtilities.invokeLater()
// is a standard idiom for switching to the event-handling thread.
SwingUtilities.invokeLater(new Runnable() {
public void run () {
// Make and display the WordFinder window.
new WordFinder();
}
});
}
}
When you call makeListView the JList is null as it hasn't been initialized yet...thus, you are basically saying scroll = new JScrollPane(null);...which isn't particularly helpful...
Next, when you call updateListView, you create a new instance of the JList and JScrollPane and do nothing with them...
private void updateListView(DefaultListModel listModel) {
list = new JList(listModel);
scroll = new JScrollPane(list);
}
so they will never be displayed on the screen...
To rectify this, you will need to make some modifications...
Create an instance of the JList and assign it to the instance field list, before you create the JScrollPane
Instead of creating new instances of the list and scroll, simply use JList#setModel
You may also like to have a look at Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
With JList, you affect the size of the JScrollPane through the use of JList#setVisibleRowCount and JList#setPrototypeCellValue

Trouble with integer validation and showing users have entered invalid data

This is for a Java program I'm working on as part of a homework assignment. I don't want the work done for me, but I'm stuck. I'm fairly new to Java, and using NetBeans IDE 7.0.1.
I'm having difficulty with some exception handling when trying to validate user input. This program will log charitable donations from user input. However, I've not been successful in validating the donation amount text field input. If a user inputs text instead of numbers, I would like them to be notified that their input was invalid, and I'd like the exception handling to handle the error and carry on after the user fixes their entry. Any help is greatly appreciated.
Here is my code:
package donorgui;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.io.*;
import java.awt.*;
public class DonorGUI extends JFrame
{
// Components
private JPanel panel;
private JTextArea results;
private JButton entryButton;
private JButton exitButton;
private JButton clearButton;
private JTextField donorField;
private JTextField charityField;
private JTextField pledgeField;
//create variables
String[] donorName = new String[20];
String[] charityName = new String[20];
double[] donationAmt = new double[20];
int i = 0;
// Constants for the window size
private final int WINDOW_WIDTH = 750;
private final int WINDOW_HEIGHT = 510;
//Constructor
public DonorGUI(){
// Set the title.
setTitle("Donor");
// Specify what happens when the close button is clicked.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Build the panel that contains the other components.
buildPanel();
// Add the panel to the content pane.
add(panel);
// Size and display the window.
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setVisible(true);
}
//The buildPanel method creates a panel containing other components.
private void buildPanel(){
// Create labels to display instructions.
JLabel message1 = new JLabel("Name of the Donor:");
JLabel message2 = new JLabel("Name of the Charity:");
JLabel message3 = new JLabel("Amount of the Pledge:");
//instantiate the results area
results = new JTextArea(25,60);
// Create text fields to receive user input
donorField = new JTextField(10);
charityField = new JTextField(10);
pledgeField = new JTextField(10);
//create the user buttons to cause action
entryButton = new JButton("Enter Donation.");
entryButton.addActionListener(new EntryButtonListener());
exitButton = new JButton("EXIT");
exitButton.addActionListener(new ExitButtonListener());
clearButton = new JButton ("Clear Fields");
clearButton.addActionListener(new ClearButtonListener());
// Create a panel.
panel = new JPanel();
//set the LayoutManager
panel.setLayout(new FlowLayout());
// Add the labels, text fields, and button to the panel.
panel.add(message1);
panel.add(donorField);
panel.add(message2);
panel.add(charityField);
panel.add(message3);
panel.add(pledgeField);
panel.add(results);
panel.add(entryButton);
panel.add(exitButton);
panel.add(clearButton);
}
private class EntryButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
donorName[i] = donorField.getText();
charityName[i] = charityField.getText();
donationAmt[i] = Double.parseDouble(pledgeField.getText());
results.append(donorName[i]+" "+charityName[i]+" "+donationAmt[i]+"\n ");
i++;
}
}
public boolean donationAmt(String amount) {
int i = 0;
try {
i = Integer.parseInt (amount);
return true;
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Invalid Input. Please enter a dollar amount");
return false;
}
}
private class ClearButtonListener implements ActionListener {
#Override
public void actionPerformed (ActionEvent e) {
donorField.setText("");
charityField.setText("");
pledgeField.setText("");
}
}
private class ExitButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
/* Application method */
public static void main(String[] args){
DonorGUI rpc = new DonorGUI();
}
}
Here is my revised code. After some user input testing, I'm getting an exception when I use 100.00, 40.00, etc... instead of whole dollar amounts, such as 100, 40, etc.
Any thoughts?
package donorgui;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.io.*;
import java.awt.*;
public class DonorGUI extends JFrame
{
// Components
private JPanel panel;
private JTextArea results;
private JButton entryButton;
private JButton exitButton;
private JButton clearButton;
private JTextField donorField;
private JTextField charityField;
private JTextField pledgeField;
//create variables
String[] donorName = new String[20];
String[] charityName = new String[20];
double[] donationAmt = new double[20];
int i = 0;
// Constants for the window size
private final int WINDOW_WIDTH = 750;
private final int WINDOW_HEIGHT = 550;
//Constructor
public DonorGUI(){
// Set the title.
setTitle("Donor");
// Specify what happens when the close button is clicked.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Build the panel that contains the other components.
buildPanel();
// Add the panel to the content pane.
add(panel);
// Size and display the window.
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setVisible(true);
}
//The buildPanel method creates a panel containing other components.
private void buildPanel(){
// Create labels to display instructions.
JLabel message1 = new JLabel("Name of the Donor:");
JLabel message2 = new JLabel("Name of the Charity:");
JLabel message3 = new JLabel("Amount of the Pledge:");
//instantiate the results area
results = new JTextArea(25,60);
// Create text fields to receive user input
donorField = new JTextField(10);
charityField = new JTextField(10);
pledgeField = new JTextField(10);
//create the user buttons to cause action
entryButton = new JButton("Enter Donation.");
entryButton.addActionListener(new EntryButtonListener());
exitButton = new JButton("EXIT");
exitButton.addActionListener(new ExitButtonListener());
clearButton = new JButton ("Clear Fields");
clearButton.addActionListener(new ClearButtonListener());
// Create a panel.
panel = new JPanel();
//set the LayoutManager
panel.setLayout(new FlowLayout());
// Add the labels, text fields, and button to the panel.
panel.add(message1);
panel.add(donorField);
panel.add(message2);
panel.add(charityField);
panel.add(message3);
panel.add(pledgeField);
panel.add(results);
panel.add(entryButton);
panel.add(exitButton);
panel.add(clearButton);
}
private class EntryButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
donorName[i] = donorField.getText();
charityName[i] = charityField.getText();
if (donationAmt(pledgeField.getText())) {
donationAmt[i] = Double.parseDouble(pledgeField.getText());
}
results.append(donorName[i]+" "+charityName[i]+" "+donationAmt[i]+"\n ");
i++;
}
}
public boolean donationAmt(String amount) {
if(amount==null || amount=="" || amount.length()<1){ //checking for empty field
JOptionPane.showMessageDialog(null, "Please enter a dollar amount");
return false;
}
for(int i = 0; i < amount.length(); i++){ //verifying dollar amount entered as number
if (!Character.isDigit(amount.charAt(i))){
JOptionPane.showMessageDialog(null, "Invalid input. Please enter a dollar amount");
return false;
}
}
return true;
}
private class ClearButtonListener implements ActionListener {
#Override
public void actionPerformed (ActionEvent e) {
donorField.setText("");
charityField.setText("");
pledgeField.setText("");
}
}
private class ExitButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
/* Application method */
public static void main(String[] args){
DonorGUI rpc = new DonorGUI();
}
}
You can use InputVerifier, discussed here.
private class EntryButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
donorName[i] = donorField.getText();
charityName[i] = charityField.getText();
if(donationAmt(pledgeField.getText())){
donationAmt[i] = Double.parseDouble(pledgeField.getText());
results.append(donorName[i] + " " + charityName[i] + " " + donationAmt[i] + "\n ");
i++;
}
}
}
Something like this would work. This checks so that the amount is not empty and contains only digits based on your exisiting method.
public boolean donationAmt(String amount) {
if(amount==null || amount=="" || amount.length()<1){ //check so that the amount field is not empty, pherhaps you can add a check so the amound is not 0 :)
JOptionPane.showMessageDialog(null, "Invalid Input. The amount cannot be empty");
return false;
}
for(int i = 0; i < amount.length(); i++){ //loop thru the string and check so that each char is a digit
if (!Character.isDigit(amount.charAt(i))){
JOptionPane.showMessageDialog(null, "The amount can contain only numbers");
return false;
}
return true;
If you want to make sure that the amount is not 0, one approach would be to parse amount to int, and check so that parsedAmount<0. This should be done after it's verified that the amount is not empty and is only digits (e.i last:) ) to avoid NPE's and numberformatexception

Categories