I want to change the image a JLabel is viewing during runtime, but I keep getting NullPointerExceptions or nothing happens when I press the magic button that's supposed to do things. Is it even possible in Java?
Here is my code in its entirety:
import java.text.*;
import javax.swing.text.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Shell implements ActionListener, MenuKeyListener
{
JFrame frame;
JWindow window;
JButton PSubmit;
JPanel pane1, pane2;
JRadioButton R1, R2, R3;
ButtonGroup PGroup;
JTabbedPane layout;
String result;
String border = "Border.png";
String DF = "Frame.png";
String list [];
Driver driver;
public Shell()
{
driver = new Driver();
list = new String [6];
}
public void setFrame()
{
frame = new JFrame("Pokemon Program 3 by Systems Ready");
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.getContentPane().setLayout(new BorderLayout());
}
public void frameLayout()
{
layout = new JTabbedPane();
JPanel pane1 = new JPanel();
JPanel pane2 = new JPanel();
JLabel label = new JLabel("Please choose the restrictions:");
JLabel imgLabel1 = new JLabel(new ImageIcon(border));
JLabel notiLabel1 = new JLabel("The Pokemon chosen with these restrictions are: ");
JLabel notiLabel2 = new JLabel("'No Restrictions': No restrictions for the kind of Pokemon chosen based on species or items.");
JLabel notiLabel3 = new JLabel("'Battle Revolution': All Pokemon must have unique items.");
JLabel notiLabel4 = new JLabel("'Battle Tower': All Pokemon must have unique items, Uber and Event Legendaries banned.");
JLabel label2 = new JLabel("Please choose possible Pokemon:");
pane1.add(label);
pearlButtons();
pane1.add(R1);
pane1.add(R2);
pane1.add(R3);
pane1.add(PSubmit);
pane1.add(notiLabel2);
pane1.add(notiLabel3);
pane1.add(notiLabel4);
pane1.add(imgLabel1);
pane1.add(notiLabel1);
JLabel pokeLabel1 = new JLabel(new ImageIcon(DF));
JLabel pokeLabel2 = new JLabel(new ImageIcon(DF));
JLabel pokeLabel3 = new JLabel(new ImageIcon(DF));
JLabel pokeLabel4 = new JLabel(new ImageIcon(DF));
JLabel pokeLabel5 = new JLabel(new ImageIcon(DF));
JLabel pokeLabel6 = new JLabel(new ImageIcon(DF));
pane1.add(pokeLabel1);
pane1.add(pokeLabel2);
pane1.add(pokeLabel3);
pane1.add(pokeLabel4);
pane1.add(pokeLabel5);
pane1.add(pokeLabel6);
pane2.add(label2);
layout.add("Pearl Version", pane1);
layout.add("SoulSilver Version", pane2);
frame.add(layout);
}
public void pearlButtons()
{
PGroup = new ButtonGroup();
R1 = new JRadioButton("No Restrictions", true);
R1.setActionCommand("N");
R1.setVisible(true);
R2 = new JRadioButton("Battle Revolution");
R2.setActionCommand("BR");
R2.setVisible(true);
R3 = new JRadioButton("Battle Tower");
R3.setActionCommand("B");
R3.setVisible(true);
PGroup.add(R1);
PGroup.add(R2);
PGroup.add(R3);
PSubmit = new JButton("Submit");
PSubmit.setActionCommand("pstart");
PSubmit.setVisible(true);
PSubmit.addActionListener(this);
}
public void pearlProcessing()
{
//The "list" array has a bunch of string names that get .png affixed to them (and I named the image files as such when I name them)
String file1 = list[0] + ".png";
String file2 = list[1] + ".png";
String file3 = list[2] + ".png";
String file4 = list[3] + ".png";
String file5 = list[4] + ".png";
String file6 = list[5] + ".png";
/*-------------------------------------------------------------------------------//
This is where the method's supposed to go to change the image...
I've tried pokeLabel = new JLabel(new ImageIcon(file1));, but that yields a NullPointerException.
//-----------------------------------------------------------------------------------*/
}
public static void main(String[] args)
{
Shell test = new Shell();
test.setFrame();
test.frameLayout();
test.frame.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if ("pstart".equals(e.getActionCommand()))
{
result = PGroup.getSelection().getActionCommand();
if (result.equals("N"))
{
list = driver.Prandom();
pearlProcessing();
}
else
System.out.println("Not done yet! ;)");
}
}
public void menuKeyPressed(MenuKeyEvent e)
{
System.out.println("pressed");
}
public void menuKeyReleased(MenuKeyEvent e)
{
System.out.println("menuKeyReleased");
}
public void menuKeyTyped(MenuKeyEvent e)
{
System.out.println("menuKeyTyped");
}
}
Without knowing if this is the cause, I would change
result = PGroup.getSelection().getActionCommand();
if (result.equals("N")) {
to
ButtonModel selection = PGroup.getSelection();
result = (selection==null ? null : selection.getActionCommand());
if ("N".equals(result)) {
// etc...
This guards against likely null pointers.
I highly suggest whenever you get any exception to always look at the stack trace and see where the actual line the exception occurred at was.
But if I were to speculate, you call PGroup.getSelection() in your actionPerformed method. This method may return null if there is no button selected in your radio button group. I also noticed that you do not set an initially selected radio button (call setSelected(true) on the radio button). Thus, if the selected radio button is null calling getActionCommand will result in a NullPointerException.
Related
I am trying to create and Editable JComboBox to allow the user to type the name of the song to purchase. However when I set tunes.setEditable(true); I get an error... any help will be appreciated!
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes2 extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes = new JComboBox();
// set as editable
tunes.setEditable(true);
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes2()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes frame = new JTunes();
frame.setSize(250, 180);
frame.setVisible(true);
}
}
Thank you!
Actually, Java requires that you setup JComponents in the constructor. In order for your code to work, you need to call on setEditable(true) in the constructor, which means that you just need to move tunes.setEditable(true); to the constructor.
Tip: always allocate memory for JComponents in the constructor (you want to draw the components as soon as you create the Jframe). You can have a reference to the JComboBox at the class level.
Here is another version of your code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes2 extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes;
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes2()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
tunes = new JComboBox();
// set as editable
tunes.setEditable(true);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes2 frame = new JTunes2();
frame.setSize(250, 180);
frame.setVisible(true);
}
}
You added the tunes.setEditable(true) at the class level, instead of at the method level. No statements allowed at the class level!
Here's a fixed version: I renamed JTunes2 to JTunes to fix the compilation errors, and moved the setEditable to the constructor. Also I fixed the indentation - this makes it harder to make this mistake:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JTextArea;
public class JTunes extends JFrame implements ItemListener
{
int songNum,songPrice;
int[] songAmount = {2,5,8,1,4,7,12,10,11,3,6,9};
String result;
JComboBox tunes = new JComboBox();
JLabel labelTunes = new JLabel("Song List");
JLabel outputs = new JLabel();
FlowLayout layout = new FlowLayout();
public JTunes()
{
super("Song Selector");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(layout);
tunes.setEditable(true);
// add song names to combo box and register an item listener.
tunes.addItem("Song1");
tunes.addItem("Song2");
tunes.addItem("Song3");
tunes.addItem("Song4");
tunes.addItem("Song5");
tunes.addItem("Song6");
tunes.addItem("Song7");
tunes.addItem("Song8");
tunes.addItem("Song9");
tunes.addItem("Song10");
tunes.addItem("Song11");
tunes.addItem("Song12");
tunes.addItemListener(this);
panel.add(labelTunes);
panel.add(tunes);
panel.add(outputs);
//add panel to the frame
setContentPane(panel);
}
public void itemStateChanged(ItemEvent e)
{
//create source object
Object source = e.getSource();
//check the type size
if(source == tunes)
{
songNum = tunes.getSelectedIndex();
songPrice = songAmount[songNum];
result = "Total Price $" + songPrice;
//Display result
outputs.setText(result);
}
}
public static void main(String[] args)
{
// create class object
JTunes frame = new JTunes();
frame.setSize(250, 180);
frame.setVisible(true);
}
}
I am a beginner Java-coder and a few days ago I felt confident enough in my skills to start my first "big" project. It was basically a calculator, a GUI(only JFrame, JPanels, JLabels and Buttons) that would display data, accept user input, grab some more data from other classes, then calculate stuff and finally update the GUI with the new JLabel values. However I never managed to get the update part done properly, whenever I would press the 'process'-button it would create a new JFrame with the new values, while the old one was still up.
I tried the obvious stuff (repaint(), revalidate(), etc) but that didn't work at all, then I started to shift things around, put parts of the code into new classes, copied code from the net until it eventually worked. However the code was a total mess and I didn't even really understand what went exactly wrong in the first place, so I trashed the entire thing.
Here is a very simplified version of my code before things went downhill:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test_1 extends JFrame {
public static class clicks{
static int clicks = 0;
public int getclicks(){
return clicks;
}
public void setclicks(){
clicks = clicks+1;
}
}
public Test_1(){
clicks getNumber = new clicks();
int x = getNumber.getclicks();
//FRAME AND LAYOUT
JFrame window = new JFrame();
window.getContentPane().setBackground(Color.darkGray);
window.getContentPane().setLayout(new BorderLayout(20,10));
window.setTitle("Test Frame 1");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(true);
// Top JPanel
JPanel northpanel = new JPanel();
LayoutManager northlayout = new FlowLayout();
northpanel.setLayout(northlayout);
// Top JPanel content
JLabel nlabel1 = new JLabel("Hello North");
nlabel1.setPreferredSize(new Dimension(100,20));
northpanel.add(nlabel1);
JPanel westpanel = new JPanel();
LayoutManager westlayout = new BoxLayout(westpanel, BoxLayout.Y_AXIS);
westpanel.setLayout(westlayout);
JLabel wlabel1 = new JLabel("Hello West");
wlabel1.setPreferredSize(new Dimension(100,20));
westpanel.add(wlabel1);
JPanel eastpanel = new JPanel();
LayoutManager eastlayout = new BoxLayout(eastpanel, BoxLayout.Y_AXIS);
eastpanel.setLayout(eastlayout);
JLabel elabel1 = new JLabel ("Hello East");
elabel1.setPreferredSize(new Dimension(100,20));
eastpanel.add(elabel1);
JButton southbutton = new JButton("start");
southbutton.setPreferredSize(new Dimension(400,50));
southbutton.addActionListener(new Action());
JPanel centralpanel = new JPanel();
JLabel clabel1 = new JLabel("Clicks: " + x);
centralpanel.add(clabel1);
window.add(centralpanel, BorderLayout.CENTER);
window.add(southbutton, BorderLayout.SOUTH);
window.add(eastpanel, BorderLayout.EAST);
window.add(westpanel, BorderLayout.WEST);
window.add(northpanel, BorderLayout.NORTH);
window.pack();
window.setVisible(true);
}
public static void main(String[] args) {
Test_1 window_start = new Test_1();
}
static class Action implements ActionListener{
#Override
public void actionPerformed (ActionEvent e){
clicks Numbers = new clicks();
Numbers.setclicks();
int test = Numbers.getclicks();
System.out.println("Button works, Number of clicks: "+test);
Test_1 updateData = new Test_1();
}
}
}
I know that the ActionListener creates a new instance of my JFrame, however that was the closest I ever came to "updating the JFrame" before I turned the code into Spaghetti. I assume that the way I build my code is the cause of my problem but creating the Frame and its content it different classes didn't work at all.
So my questions are:
Is there something really obvious I missing? Would it be possible to make this run the way I want to without completely changing it?
Is there a more efficient way to create a GUI? I get the feeling that the way I made this is total garbage.
I read other questions that dealt with similar problems but maybe it's because I am still pretty bad at Java but I couldn't really tell if they were related to my problem. Also I really want to understand this, so copying someone elses code wouldn't help at all.
Any help or comments are appreciated.
btw, the class click is something I just put there as a placeholder.
Alrighty I managed to get it to work. It's probably against the Etiquette to answer to his own question but I thought it might be useful for some beginners(like me yesterday). So here is my new code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test_1 extends JFrame {
public static class clicks{
static int clicks = 0;
public int getclicks(){
return clicks;
}
public void setclicks(){
clicks = clicks+1;
}
}
clicks getNumber = new clicks();
int x = getNumber.getclicks();
JPanel northpanel, westpanel, eastpanel, southpanel, centralpanel;
static JLabel nlabel1, nlabel2, nlabel3, nlabel4, nlabel5;
static JLabel wlabel1, wlabel2, wlabel3, wlabel4, wlabel5;
static JLabel elabel1, elabel2, elabel3, elabel4, elabel5;
static JLabel clabel1;
JButton southbutton;
String TextnL, TextwL, TexteL;
public Test_1(){
setBackground(Color.darkGray);
setLayout(new BorderLayout(20,10));
setTitle("Test Frame 1");
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setLocationRelativeTo(null);
setVisible(true);
nlabel1 = new JLabel("North_1");
nlabel2 = new JLabel("North_2");
nlabel3 = new JLabel("North_3");
nlabel4 = new JLabel("North_4");
nlabel5 = new JLabel("North_5");
wlabel1 = new JLabel("West_1 ");
wlabel2 = new JLabel("West_2 ");
wlabel3 = new JLabel("West_3 ");
wlabel4 = new JLabel("West_4 ");
wlabel5 = new JLabel("West_5 ");
elabel1 = new JLabel("East_1");
elabel2 = new JLabel("East_2");
elabel3 = new JLabel("East_3");
elabel4 = new JLabel("East_4");
elabel5 = new JLabel("East_5");
clabel1 = new JLabel("START");
southbutton = new JButton("Process");
southbutton.addActionListener(new Action());
northpanel = new JPanel();
northpanel.add(nlabel1);
northpanel.add(nlabel2);
northpanel.add(nlabel3);
northpanel.add(nlabel4);
northpanel.add(nlabel5);
add(northpanel, BorderLayout.NORTH);
westpanel = new JPanel();
LayoutManager wBox = new BoxLayout(westpanel, BoxLayout.Y_AXIS);
westpanel.setLayout(wBox);
westpanel.add(wlabel1);
westpanel.add(wlabel2);
westpanel.add(wlabel3);
westpanel.add(wlabel4);
westpanel.add(wlabel5);
add(westpanel, BorderLayout.WEST);
eastpanel = new JPanel();
LayoutManager eBox = new BoxLayout(eastpanel, BoxLayout.Y_AXIS);
eastpanel.setLayout(eBox);
eastpanel.add(elabel1);
eastpanel.add(elabel2);
eastpanel.add(elabel3);
eastpanel.add(elabel4);
eastpanel.add(elabel5);
add(eastpanel, BorderLayout.EAST);
centralpanel = new JPanel();
centralpanel.add(clabel1);
add(centralpanel, BorderLayout.CENTER);
add(southbutton, BorderLayout.SOUTH);
}
public static void main(String[] args) {
Test_1 window_start = new Test_1();
}
static class Action implements ActionListener{
#Override
public void actionPerformed (ActionEvent e){
clicks Numbers = new clicks();
Numbers.setclicks();
int test = Numbers.getclicks();
clabel1.setText("clicks: "+test);
}
}
}
And again, any comments/suggestions are welcome.
I am working on a little project and want to display the Name of the opened File.
The problem is, the JLabel who should display the File Name is not repainting, I had read that it should be repainted by itself..
here is my code for the FileChooser and to get the File Name ( I know that i get the path of the file, I will format it later..
/**
* Opens a window where the user can select a file.
*
* #return Scanner in
*/
public Scanner openFile() {
JFileChooser chooser = new JFileChooser();
Scanner in = null;
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedInFile = chooser.getSelectedFile();
try {
absolutePathOfFile = selectedInFile.getAbsolutePath();
FileReader fileReader = new FileReader(selectedInFile.getAbsolutePath());
in = new Scanner(fileReader);
} catch (FileNotFoundException ex) {
// File not found
System.out.println("File not found!!");
}
}
return in;
}
public List getList() {
return listOfEveryVariable;
}
#Override
public String getFileName() {
return absolutePathOfFile;
}
And here is the code for my Label
public Component createInfoPanel() {
infoPanel = new JPanel(new BorderLayout());
infoPanel.setBackground(Color.LIGHT_GRAY);
fileInfoPanel = new JPanel(new GridLayout(1,2));
fileInfoPanel.setBackground(Color.LIGHT_GRAY);
infoPanel.add(fileInfoPanel, BorderLayout.WEST);
JLabel fileInfo_1 = new JLabel();
fileInfo_1.setText("File: ");
fileInfoPanel.add(fileInfo_1);
JLabel fileInfo_2 = new JLabel();
FileName fn = new Datahandler();
fileInfo_2.setText(fn.getFileName());
fileInfoPanel.add(fileInfo_2);
return infoPanel;
}
The GuiInfoPanel is created and added in and to an Frame..
If I set a name to the getFileName() class and let it return it works and the name is displayed.
Greetings
The createInfoPanel is called here:
public class GuiFrame extends JFrame {
private static final int FRAME_WIDTH = 800;
private static final int FRAME_HIGHT = 600;
/**
* The variables for the panels
*/
private JPanel mainPanel, menuPanel, plotPanel, scatterplotPanel,
histogramPanel, histogram1, histogram2;
public GuiFrame() {
setSize(FRAME_WIDTH, FRAME_HIGHT);
/**
* Create Objects
*/
GuiMenuBar mb = new GuiMenuBar();
GuiInfoPanel ip = new GuiInfoPanel();
GuiOptionPanel op = new GuiOptionPanel();
JComponent sp = new Scatterplot();
/**
* Create Panels
*/
createMainPanel();
mb.createMenuBar();
ip.createInfoPanel();
op.createOptionPanel();
/**
* Add Panels
*/
this.add(mainPanel);
this.setJMenuBar(mb);
this.add(ip.infoPanel, BorderLayout.SOUTH);
menuPanel.add(op.optionPanel, BorderLayout.NORTH);
scatterplotPanel.add(sp, BorderLayout.CENTER);
}
private Component createMainPanel(){
mainPanel = new JPanel(new BorderLayout());
menuPanel = new JPanel(new BorderLayout());
mainPanel.add(menuPanel, BorderLayout.WEST);
plotPanel = new JPanel(new GridLayout(2,1));
plotPanel.setBorder(BorderFactory.createLineBorder(Color.black));
mainPanel.add(plotPanel, BorderLayout.CENTER);
scatterplotPanel = new JPanel(new BorderLayout());
scatterplotPanel.setBorder(BorderFactory.createLineBorder(Color.black));
plotPanel.add(scatterplotPanel);
histogramPanel = new JPanel(new GridLayout(1,2));
plotPanel.add(histogramPanel);
histogram1 = new JPanel(new BorderLayout());
histogram1.setBorder(BorderFactory.createLineBorder(Color.black));
histogramPanel.add(histogram1);
histogram2 = new JPanel(new BorderLayout());
histogram2.setBorder(BorderFactory.createLineBorder(Color.black));
histogramPanel.add(histogram2);
return mainPanel;
}
}
I think that the panel being called only once is be the problem.
It looks like the problem is that createInfoPanel() is only ever called once, at the point where you create the screen. At this point, setText() is doing what you'd expect it to, but the user hasn't chosen a file yet. I am basing this on the fact that if createInfoPanel() were called multiple times, you would end up adding more labels to the screen than desired.
When you select a file from your file chooser, createInfoPanel() doesn't magically get called again and so the text never gets updated on the JLabel. It would be useful to see the code that calls createInfoPanel() and the code that calls openFile() to verify this is the case.
Regarding your second question - you can't reference the JLabel outside of where it is declared. As you are declaring the JLabel within createInfoPanel() it is a local variable to this method only. If you want it to be accessed by other methods you need to make it a class variable, similar to the "absolutePathOfFile" variable. So you might do something like:
public class GuiInfoPanel {
private final JPanel infoPanel;
private final JLabel fileInfo = new JLabel();
public Component createInfoPanel() {
infoPanel = new JPanel(new BorderLayout());
infoPanel.setBackground(Color.LIGHT_GRAY);
fileInfo.setText("File: ");
infoPanel.add(fileInfo, BorderLayout.WEST);
return infoPanel;
}
/**
* Call this whenever the user picks a new file
*/
public void setFileInfoText(String filePath){
fileInfo.setText("File: " + filePath);
}
}
EDIT: Your latest code confirms my suspicions - createInfoPanel() is only called by the constructor, so will only be called once. Try something like my code snippet above to get the behaviour you're after. And a side-note: You should edit your original post to include more information rather than posting updates as 'answers'!
EDIT 2: See below for a self-contained 'toy' example that should help you to get the behaviour you're after.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class FileSelectionDemo extends JFrame
implements ActionListener
{
public static void main(String[] args)
{
FileSelectionDemo demoScreen = new FileSelectionDemo();
demoScreen.setSize(300, 300);
demoScreen.setVisible(true);
}
public FileSelectionDemo()
{
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
getContentPane().add(btnSelectFile);
getContentPane().add(lblFilePath);
btnSelectFile.addActionListener(this);
}
private final JLabel lblFilePath = new JLabel("");
private final JButton btnSelectFile = new JButton("Choose File");
public void selectFile()
{
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
{
File selectedInFile = chooser.getSelectedFile();
String absolutePathOfFile = selectedInFile.getAbsolutePath();
lblFilePath.setText(absolutePathOfFile);
}
}
#Override
public void actionPerformed(ActionEvent arg0)
{
Object source = arg0.getSource();
if (source == btnSelectFile)
{
selectFile();
}
}
}
my current program takes in text from some JTextFields and adds it to a file to keep track of medications. What i want to do, is add another button to the bottom of the program that will open a second jframe to display the medications that are already documented, but all attempts have been brutally unsuccessful. Below is the code that i am currently working with.
Much Thanks.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
#SuppressWarnings({ "serial" })
public class MedGUITest extends JFrame {
private JLabel medName;
private JLabel medTime;
private JLabel medDose;
private JLabel finished;
private JTextField textFieldMed;
private JTextField textFieldTime;
private JTextField textFieldDose;
private JButton submitButton;
private JButton meds;
public MedGUITest(){
setLayout(new FlowLayout());
medName = new JLabel("Type Medication Here:");
add(medName);
textFieldMed = new JTextField("",15);
add(textFieldMed);
medDose = new JLabel("Type Medication Dose:");
add(medDose);
textFieldDose = new JTextField("",15);
add(textFieldDose);
medTime = new JLabel("Type Medication Time:");
add(medTime);
textFieldTime = new JTextField("",15);
add(textFieldTime);
submitButton = new JButton("Click Here to Add");
event e = new event();
submitButton.addActionListener(e);
add(submitButton);
meds = new JButton("Click Here to see meds");
event2 r = new event2();
meds.addActionListener(r);
add(meds);
finished = new JLabel("");
add(finished);
}
public class event implements ActionListener {
public void actionPerformed(ActionEvent e){
String medName = textFieldMed.getText();
String medDose = textFieldDose.getText();
String medTime = textFieldTime.getText();
File med = new File("med.txt");
try(PrintWriter out= new PrintWriter(new FileWriter(med,true))) {
out.println("Medication: " + medName + " " +"Dosage: "+ medDose + " Mg"+ " " +"Time of day: "+ medTime);
finished.setText("Your Med has been added");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class event2 implements ActionListener{
public void actionPerformed(ActionEvent e){
}
}
public static void main(String args[]) throws IOException{
int winWidth = 300;
int winLength = 300;
MedGUITest gui = new MedGUITest();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(winWidth, winLength);
gui.setVisible(true);
gui.setTitle("Standard GUI");
}
}
You would probably want to use a JDialog instead of another JFrame. You just set it up the same way you set up any other JFrame or JDialog. You create the frame/dialog, add components and then call pack() then setvisible(true). You just want to make sure that you don't set JFrame.setDefaultCloseOperation() to close when the close your second JFrame.
I find it easier to set up my classes to sub-class JPanel instead of JFrame so then it is easier to reuse it in other places.
First, I would like to say I have searched these forums, as well as others for an answer to my question. I am very new to Java, and programing in general. After working on this for several hours, I would like to ask for some help.
I am trying to open up a window (that will have some graphics later), that has a menu bar. The options are 3 drop down menus that perform a task when selected. The file menu lets me save, load, and exit the program. For now the rest just print to the screen to let me know that much is working. Right now, I want to set it up so when I click the "Create Seller" option, it will open up a new dialog box with 3 fields. I would like to enter a string in one, and two doubles in the other two. I will then store those as variables and send them to another function. I have been stuck on this part for way too long. Keep in mind that, while this has probably been answered before, I think I am just not competent enough with Java yet to understand the answer. Try to dumb it down for me if that is not too much to ask. THANKS!
here is the class I am working on. Feel free to ask for less or more if you need.
package seller;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JFileChooser;
import javax.swing.JTextField;
import datastore.Meteorite;
import datastore.continents;
import datastore.customers;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class BaseFrame extends JFrame implements ActionListener
{
private static final long serialVersionUID = 1L;
JFileChooser myChooser = new JFileChooser(".");
JMenuItem menuItemSave;
JMenuItem menuItemLoad;
JMenuItem menuItemExit;
JMenuItem menuItemCreateSeller;
JMenuItem menuItemUpdateSeller;
JMenuItem menuItemRemoveSeller;
JMenuItem menuItemCreateMeteorite;
JMenuItem menuItemUpdateMeteorite;
JMenuItem menuItemRemoveMeteorite;
JMenuItem menuItemCreateOneLine;
continents worldMap = new continents();
boolean[][] mapArray = null;
int selection = 1;
String shopName = null;
Map myMap= new Map();
Scanner myScanner = new Scanner(System.in);
Menu myMenu = new Menu();
seller seller= new seller();
Meteorites myMeteorite = new Meteorites();
customers sellers= new customers(0,0,"test");
customers buyers= new customers(0, 0, "test");
ArrayList <Meteorite> myMeteorites = new ArrayList<Meteorite>();
ArrayList <customers> mySellers= new ArrayList<customers>();
ArrayList <customers> myBuyers= new ArrayList<customers>();
customers people= new customers(0,0,"test");
public void makeGui()
{
this.setTitle("Phase 3");
JMenuBar mb = new JMenuBar();
this.setJMenuBar(mb);
//Load and Save used from class example
JMenu fileMenu = new JMenu("File");
mb.add(fileMenu);
menuItemSave = new JMenuItem("Save");
menuItemSave.addActionListener(this);
menuItemLoad = new JMenuItem("Load");
menuItemLoad.addActionListener(this);
menuItemExit = new JMenuItem("Exit");
menuItemExit.addActionListener(this);
fileMenu.add(menuItemSave);
fileMenu.add(menuItemLoad);
fileMenu.add(menuItemExit);
//seller menu
JMenu sellerMenu = new JMenu("Seller");
mb.add(sellerMenu);
menuItemCreateSeller = new JMenuItem("Create Seller");
menuItemCreateSeller.addActionListener(this);
menuItemUpdateSeller = new JMenuItem("Update Seller");
menuItemUpdateSeller.addActionListener(this);
menuItemRemoveSeller = new JMenuItem("Remove Seller");
menuItemRemoveSeller.addActionListener(this);
sellerMenu.add(menuItemCreateSeller);
sellerMenu.add(menuItemUpdateSeller);
sellerMenu.add(menuItemRemoveSeller);
//handle meteorite menu
JMenu handleMeteoriteMenu = new JMenu("Handle Meteorite");
mb.add(handleMeteoriteMenu);
menuItemCreateMeteorite = new JMenuItem("Create Meteorite");
menuItemCreateMeteorite.addActionListener(this);
menuItemUpdateMeteorite = new JMenuItem("Update Meteorite");
menuItemUpdateMeteorite.addActionListener(this);
menuItemRemoveMeteorite = new JMenuItem("Remove Meteorite");
menuItemRemoveMeteorite.addActionListener(this);
menuItemCreateOneLine = new JMenuItem("Create Meteorite(1 line)");
menuItemCreateOneLine.addActionListener(this);
handleMeteoriteMenu.add(menuItemCreateMeteorite);
handleMeteoriteMenu.add(menuItemUpdateMeteorite);
handleMeteoriteMenu.add(menuItemRemoveMeteorite);
handleMeteoriteMenu.add(menuItemCreateOneLine);
JPanel tPanel = new JPanel();
this.add(tPanel);
this.pack();
this.setSize(new Dimension(640,480));
this.setVisible(true);
}
String myName;
double myLong;
double myLat;
#Override
public void actionPerformed(ActionEvent e)
{
Object source=null;
source=e.getSource();
if (source == menuItemLoad)
{
mapArray = worldMap.createMap();
myChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
int result = myChooser.showOpenDialog(this);
//if user clicked Cancel button, return
if (result == JFileChooser.CANCEL_OPTION)
System.exit(1);
File myFile = myChooser.getSelectedFile(); //get file
//display error if invalid
if ( ( myFile == null) || (myFile.getName().equals("")))
{
JOptionPane.showMessageDialog(this, "Invalid Name", "Invalid Name", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
myMeteorites= myMeteorite.loadMeteorite(myMeteorites, myFile);
sellers.loadSeller(mySellers);
buyers.loadBuyer(myBuyers);
}
if (source == menuItemSave)
{
mapArray = worldMap.createMap();
myChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
int result = myChooser.showOpenDialog(this);
//if user clicked Cancel button, return
if (result == JFileChooser.CANCEL_OPTION)
System.exit(1);
File myFile = myChooser.getSelectedFile(); //get file
//display error if invalid
if ( ( myFile == null) || (myFile.getName().equals("")))
{
JOptionPane.showMessageDialog(this, "Invalid Name", "Invalid Name", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
myMeteorites= myMeteorite.saveMeteorite(myMeteorites, myFile);
sellers.saveSeller(mySellers);
buyers.saveBuyer(myBuyers);
}
if (source == menuItemExit)
{
System.exit(1); //exit system
}
if (source == menuItemCreateSeller)
{
JFrame myFrame = new JFrame("Create a Seller");
JPanel myPanel = new JPanel();
JLabel myLabel1 = new JLabel();
JLabel myLabel2 = new JLabel();
JLabel myLabel3 = new JLabel();
final JTextField myText1 = new JTextField(30);
final JTextField myText2 = new JTextField(30);
final JTextField myText3 = new JTextField(30);
setDefaultCloseOperation(EXIT_ON_CLOSE);
myLabel1.setText("Enter Name");
myLabel2.setText("Enter Longitude");
myLabel3.setText("Enter Latitude");
myPanel.add(myLabel1);
myPanel.add(myText1);
myPanel.add(myLabel2);
myPanel.add(myText2);
myPanel.add(myLabel3);
myPanel.add(myText3);
myFrame.add(myPanel);
myFrame.setSize(350,200);
myFrame.setVisible(true);
myText1.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
myName = myText1.getText();
}
});
myName = myText1.getText();
//myLong = Double.parseDouble(myText2.getText());
//myLat = Double.parseDouble(myText3.getText());
System.out.println(myName);
//mySellers=people.createCust(mySellers, myLong, myLat, myName);
//mySellers=people.saveSeller(mySellers);
}
if (source == menuItemRemoveSeller)
{
System.out.println("remove seller");
}
if (source == menuItemUpdateSeller)
{
System.out.println("update seller");
}
if (source == menuItemCreateMeteorite)
{
System.out.println("create meteorite");
}
if (source == menuItemUpdateMeteorite)
{
System.out.println("updateMeteorite");
}
if (source == menuItemRemoveMeteorite)
{
System.out.println("remove meteorite");
}
if (source == menuItemCreateOneLine)
{
System.out.println("create one line");
}
}
}
See this example for what I am talking about. Though I'd advise against using multiple frames, this will work for what yo are trying to do. As #MadProgrammer suggested, look into creating JDialogs
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BaseFrame extends JFrame {
private String name;
private double value1;
private double value2;
private final JMenuBar jMenuBar = new JMenuBar();
private final JMenu jmOpen = new JMenu("Open");
JMenuItem menuItemCreateSeller = new JMenuItem("Create Seller");
InnerFrame innerFrame = new InnerFrame();
public BaseFrame() {
innerFrame.setResizable(false);
jmOpen.add(menuItemCreateSeller);
jMenuBar.add(jmOpen);
setJMenuBar(jMenuBar);
menuItemCreateSeller.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
innerFrame.setVisible(true);
}
});
setSize(300, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
Frame frame = new BaseFrame();
}
});
}
private class InnerFrame extends JFrame {
JPanel myPanel = new JPanel();
JLabel myLabel1 = new JLabel("Enter Name");
JLabel myLabel2 = new JLabel("Enter Longitude");
JLabel myLabel3 = new JLabel("Enter Latitude");
JLabel jlblStatus = new JLabel(" ");
JTextField myText1 = new JTextField(10);
JTextField myText2 = new JTextField(10);
JTextField myText3 = new JTextField(10);
JButton jbtPrint = new JButton("Print");
public InnerFrame() {
myPanel.add(myLabel1);
myPanel.add(myText1);
myPanel.add(myLabel2);
myPanel.add(myText2);
myPanel.add(myLabel3);
myPanel.add(myText3);
JPanel p1 = new JPanel(new GridLayout(1,2));
p1.add(jlblStatus);
p1.add(jbtPrint);
jlblStatus.setHorizontalAlignment(SwingConstants.LEFT);
jlblStatus.setForeground(Color.RED);
jbtPrint.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try {
name = myText1.getText();
value1 = Double.parseDouble(myText2.getText());
value2 = Double.parseDouble(myText3.getText());
System.out.println(name);
double total = value1 + value2;
System.out.println(total);
setVisible(false);
} catch (NumberFormatException ex) {
jlblStatus.setText("Invalid Input");
}
}
});
add(myPanel, BorderLayout.CENTER);
add(p1, BorderLayout.SOUTH);
setSize(180, 220);
setLocationRelativeTo(null);
setVisible(false);
}
}
}
You've gotten good advice in comments, and the other answer that has been posted looks reasonable at a glance. I'm going to throw in an explanation that you may or may not need; if you do need it, it would be the sort of thing it would be hard to explain that you need, because it is a concept that you may not have assimilated yet.
UI programming is "event-driven"; that means that, instead of having control in your code as you do for a non-interactive program, the control is passed to another system or part of the system, and when certain events happen, that other part calls your code. The 'other part' in this case is the Swing runtime. So your code is all about setting up the frames, panels, layouts, text fields, drop-downs, etc., AND setting listeners to those things that might cause events, and waiting for events to happen.
If your confusion is rooted in a lack of understanding of this, then the answer to your question might be that the listener for the button on the dialog is going to read the values from the drop-downs and/or text fields -- presumably the user has chosen and/or entered values as he/she was supposed to and then clicked the button. So the action routine that fires when the button (or the enter key) is clicked (pressed) goes and gets those values as they are at that time and puts them into variables (or writes them to a database or instantiates another object with them or whatever it is supposed to do.
This routine also might do validation -- if, for instance, one of the text fields holds a value that is required and the user didn't fill it out, then this listener routine could detect that and, instead of allowing the program to continue, could popup a message dialog for the user telling him/her what is wrong.
Again, I don't know that this is any part of your problem, but I thought it might be. It is a concept that inexperienced UI programmers sometimes have trouble with, and it is so basic to UI programming that a lot of the tutorials just assume you already know it.