Why is my JSlider not changing the value? - java

I am trying to make my program so that an integer value entered in a JTextfield can be stored into a variable. Then, when a JButton is clicked, this variable can tell a JSlider to move it's head to that of the integer value stored in the variable. My class name is Camera.Java
Code is showing no errors, however if I click my JButton, nothing happens, instead I see this error in the console:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:504)
at java.lang.Integer.parseInt(Integer.java:527)
at Camera.main(Camera.java:67)
My code:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;
import java.util.Scanner;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.*;
public class Camera {
static JButton addtolist;
static Scanner input = new Scanner(System.in);
static JSlider cam = new JSlider();
static JTextField enterval = new JTextField();
static int x ;
public static void main (String args[]){
JFrame myFrame = new JFrame ("Matthew Damon on Mars");
myFrame.setSize(300, 600);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JLabel userinp = new JLabel("Enter input: ");
cam = new JSlider(0, 15, 0);
cam.setPaintLabels(true);
enterval.setPreferredSize(new Dimension(100,80));
addtolist = new JButton("Enter");
addtolist.setPreferredSize(new Dimension(50,20));
JTextField enterval1 = new JTextField();
panel.add(addtolist);
Hashtable<Integer, JLabel> table = new Hashtable<Integer, JLabel>();
table.put(0, new JLabel("0"));
table.put(1, new JLabel("1"));
table.put(2, new JLabel("2"));
table.put(3, new JLabel("3"));
table.put(4, new JLabel("4"));
table.put(5, new JLabel("5"));
table.put(6, new JLabel("6"));
table.put(7, new JLabel("7"));
table.put(8, new JLabel("8"));
table.put(9, new JLabel("9"));
table.put(10, new JLabel("A"));
table.put(11, new JLabel("B"));
table.put(12, new JLabel("C"));
table.put(13, new JLabel("D"));
table.put(14, new JLabel("E"));
table.put(15, new JLabel("F"));
cam.setLabelTable(table);
myFrame.add(cam, BorderLayout.SOUTH);
myFrame.add(userinp, BorderLayout.NORTH);
myFrame.add(enterval1, BorderLayout.NORTH);
myFrame.add(panel, BorderLayout.CENTER);
myFrame.setVisible(true);
buttonAction();
}
public static void buttonAction() {
addtolist.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
int x = Integer.parseInt(enterval.getText());
cam.setValue(x);
} catch (NumberFormatException npe) {
// show a warning message
}
}
});
}
}

Your setting x on program creation before the user has had any chance to change its value. Get the text value from within the actionPerformed method which should be after the user has already selected a value, parse it into a number and set the slider with that value.
public void actionPerformed(ActionEvent e) {
try {
int x = Integer.parseInt(enterval.getText());
cam.setValue(x);
} catch (NumberFormatException npe) {
// show a warning message
}
}
Then get rid of all that static nonsense. The only method that should be static here is main, and it should do nothing but create an instance and set it visible.
Note that better than using a JTextField, use a JSpinner or a JFormattedTextField or if you're really stuck, a DocumentFilter to limit what the user can enter

Again, you should put most everything into the instance realm and out of the static realm. This means getting most of that code outside of the main method and into other methods and constructors, that means not trying to access fields or methods from the class, but rather from the instance. For instance, your main method should only create the main instances, hook them up and set them running and that's it. It should not be used to build the specific GUI components. For example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class CameraFoo extends JPanel {
// only static field here is a constant.
private static String TEXTS = "0123456789ABCDEF";
private JSpinner spinner = new JSpinner();
private JSlider slider = new JSlider(0, 15, 0);
public CameraFoo() {
List<Character> charList = new ArrayList<>();
Hashtable<Integer, JLabel> table = new Hashtable<>();
for (int i = 0; i < TEXTS.toCharArray().length; i++) {
char c = TEXTS.charAt(i);
String myText = String.valueOf(c);
JLabel label = new JLabel(myText);
table.put(i, label);
charList.add(c);
}
SpinnerListModel spinnerModel = new SpinnerListModel(charList);
spinner.setModel(spinnerModel);
slider.setLabelTable(table);
slider.setPaintLabels(true);
JPanel topPanel = new JPanel();
topPanel.add(spinner);
topPanel.add(new JButton(new ButtonAction("Press Me")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(slider);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
char ch = (char) spinner.getValue();
int value = TEXTS.indexOf(ch);
slider.setValue(value);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
private static void createAndShowGui() {
CameraFoo mainPanel = new CameraFoo();
JFrame frame = new JFrame("CameraFoo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}

Related

Resize JOptionPane Dialog and lines in a dialogs

My program is supposed to have the basic code examples in java and to do that I need help to have the dialogues where I can write have the code preloaded but I can't add spaces in the dialogues and resize them. Please help!
Main Class:
public class JavaHelperTester{
public static void main(String[] args){
JavaWindow display = new JavaWindow();
JavaHelper j = new JavaHelper();
display.addPanel(j);
display.showFrame();
}
}
Method Class:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class JavaHelper extends JPanel implements ActionListener{
JButton print = new JButton("Print Statements");
JButton classes = new JButton("Classes");
JButton varibles = new JButton("Assiging variables");
JButton signs = new JButton("Sign meanings");
JButton typesv = new JButton("Different Types of variables");
JButton scanners = new JButton("Scanner");
JButton loops = new JButton("Loops");
JButton ifstatements = new JButton("If statements");
JButton graphics = new JButton("Graphics");
JButton objects = new JButton("Making an oject");
JButton importstatments = new JButton("Import Statements");
JButton integers = new JButton("Different types of integers");
JButton methods = new JButton("Scanner methods");
JButton math = new JButton("Math in java");
JButton creation = new JButton("Method creation");
JButton arrays = new JButton("Arrays");
JButton jframe = new JButton("JFrame");
JButton stringtokenizer = new JButton("String Tokenizer");
JButton extending = new JButton("Class extending");
JButton fileio = new JButton("File I.O.");
JButton quit = new JButton("Quit");
public JavaHelper(){
setPreferredSize(new Dimension(500,350));
setBackground(Color.gray);
this.add(print);
print.addActionListener(this);
this.add(classes);
classes.addActionListener(this);
this.add(varibles);
varibles.addActionListener(this);
this.add(signs);
signs.addActionListener(this);
this.add(typesv);
typesv.addActionListener(this);
this.add(scanners);
scanners.addActionListener(this);
this.add(loops);
loops.addActionListener(this);
this.add(ifstatements);
ifstatements.addActionListener(this);
this.add(graphics);
graphics.addActionListener(this);
this.add(objects);
objects.addActionListener(this);
this.add(importstatments);
importstatments.addActionListener(this);
this.add(integers);
integers.addActionListener(this);
this.add(methods);
methods.addActionListener(this);
this.add(math);
math.addActionListener(this);
this.add(creation);
creation.addActionListener(this);
this.add(arrays);
arrays.addActionListener(this);
this.add(jframe);
jframe.addActionListener(this);
this.add(stringtokenizer);
stringtokenizer.addActionListener(this);
this.add(fileio);
fileio.addActionListener(this);
this.add(quit);
quit.addActionListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == print){
JOptionPane.showMessageDialog (null, "System.out.println(); and System.out.print();", "Print Statements", JOptionPane.INFORMATION_MESSAGE);
}
if(e.getSource() == classes){
JOptionPane.showMessageDialog (null, "Main class : public class ClassNameTester{ // public static void main(String[] args){, Other Classes : public class ClassName", "Classes", JOptionPane.INFORMATION_MESSAGE);
}
if(e.getSource() == quit){
System.exit(0);
}
}
private void dialogSize(){
}
}
JavaWindow:
import java.awt.*;
import javax.swing.*;
public class JavaWindow extends JFrame{
private Container c;
public JavaWindow(){
super("Java Helper");
c = this.getContentPane();
}
public void addPanel(JPanel p){
c.add(p);
}
public void showFrame(){
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I made changes to clean up the Java Helper GUI and to allow you to format the information on the JOptionPane dialogs.
Here's the Java Helper GUI.
And here's the Classes JOptionPane.
I modified your JavaHelperTester class to include a call to the SwingUtilities invokeLater method. This method puts the creation and use of your Swing components on the Event Dispatch thread (EDT). A Swing GUI must start with a call to the SwingUtilities invokeLater method.
I also formatted all of your code and resolved the imports.
package com.ggl.java.helper;
import javax.swing.SwingUtilities;
public class JavaHelperTester {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
JavaWindow display = new JavaWindow();
JavaHelper j = new JavaHelper();
display.addPanel(j);
display.showFrame();
}
};
SwingUtilities.invokeLater(runnable);
}
}
Here's your JavaWindow class.
package com.ggl.java.helper;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class JavaWindow extends JFrame {
private static final long serialVersionUID = 6535974227396542181L;
private Container c;
public JavaWindow() {
super("Java Helper");
c = this.getContentPane();
}
public void addPanel(JPanel p) {
c.add(p);
}
public void showFrame() {
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
And here's your JavaHelper class. I made the changes to your action listener to allow you to define the text as an HTML string. You may only use HTML 3.2 commands.
I also changed your button panel to use the GridLayout. The grid layout makes your buttons look neater and makes it easier for the user to select a JButton.
package com.ggl.java.helper;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class JavaHelper extends JPanel implements ActionListener {
private static final long serialVersionUID = -3150356430465932424L;
JButton print = new JButton("Print Statements");
JButton classes = new JButton("Classes");
JButton varibles = new JButton("Assiging variables");
JButton signs = new JButton("Sign meanings");
JButton typesv = new JButton("Different Types of variables");
JButton scanners = new JButton("Scanner");
JButton loops = new JButton("Loops");
JButton ifstatements = new JButton("If statements");
JButton graphics = new JButton("Graphics");
JButton objects = new JButton("Making an oject");
JButton importstatments = new JButton("Import Statements");
JButton integers = new JButton("Different types of integers");
JButton methods = new JButton("Scanner methods");
JButton math = new JButton("Math in java");
JButton creation = new JButton("Method creation");
JButton arrays = new JButton("Arrays");
JButton jframe = new JButton("JFrame");
JButton stringtokenizer = new JButton("String Tokenizer");
JButton extending = new JButton("Class extending");
JButton fileio = new JButton("File I.O.");
JButton quit = new JButton("Quit");
public JavaHelper() {
this.setLayout(new GridLayout(0, 2));
setBackground(Color.gray);
this.add(print);
print.addActionListener(this);
this.add(classes);
classes.addActionListener(this);
this.add(varibles);
varibles.addActionListener(this);
this.add(signs);
signs.addActionListener(this);
this.add(typesv);
typesv.addActionListener(this);
this.add(scanners);
scanners.addActionListener(this);
this.add(loops);
loops.addActionListener(this);
this.add(ifstatements);
ifstatements.addActionListener(this);
this.add(graphics);
graphics.addActionListener(this);
this.add(objects);
objects.addActionListener(this);
this.add(importstatments);
importstatments.addActionListener(this);
this.add(integers);
integers.addActionListener(this);
this.add(methods);
methods.addActionListener(this);
this.add(math);
math.addActionListener(this);
this.add(creation);
creation.addActionListener(this);
this.add(arrays);
arrays.addActionListener(this);
this.add(jframe);
jframe.addActionListener(this);
this.add(stringtokenizer);
stringtokenizer.addActionListener(this);
this.add(fileio);
fileio.addActionListener(this);
this.add(quit);
quit.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == print) {
String title = ((JButton) e.getSource()).getText();
JLabel label = new JLabel(createPrintText());
JOptionPane.showMessageDialog(this, label, title,
JOptionPane.INFORMATION_MESSAGE);
}
if (e.getSource() == classes) {
String title = ((JButton) e.getSource()).getText();
JLabel label = new JLabel(createClassesText());
JOptionPane.showMessageDialog(this, label, title,
JOptionPane.INFORMATION_MESSAGE);
}
if (e.getSource() == quit) {
System.exit(0);
}
}
private String createPrintText() {
StringBuilder builder = new StringBuilder();
builder.append("<html><pre><code>");
builder.append("System.out.print()");
builder.append("<br>");
builder.append("System.out.println()");
builder.append("</code></pre>");
return builder.toString();
}
private String createClassesText() {
StringBuilder builder = new StringBuilder();
builder.append("<html><pre><code>");
builder.append("Main class : public class ClassNameTester { <br>");
builder.append(" public static void main(String[] args) { <br>");
builder.append(" } <br>");
builder.append("} <br><br>");
builder.append("Other Classes : public class ClassName { <br>");
builder.append("}");
builder.append("</code></pre>");
return builder.toString();
}
}

Anonymous/Inner Class Dilemma in Java Swing [duplicate]

This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Closed 7 years ago.
I have a very simple GUI app. It only consists of a button and a label to display how many times that button has been clicked. I implemented it as follows:
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;
public class Scratch {
public static void main(String[] args) {
JFrame frame = new JFrame("Click Counter");
frame.setSize(400,250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JButton button = new JButton("Click Here");
final int count = 0;
final JLabel label = new JLabel("Click Count: 0");
panel.add(button);
panel.add(label);
frame.add(panel):
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
count++; // Error
String s = label.getText();
label.setText("Click Count: " + count);
}
});
frame.setVisible(true);
}
}
The problem is with the count variable. If I don't declare it as final, I cannot access it inside the anonymous class. If I do however, I cannot modify it. So what do I do? I really prefer creating actionlistener classes as anonymous classes as opposed to creating multiple classes in a single .java file.
declare variable outside function as a class variable
private static int count = 0;
public static void main(String[] args) {
JFrame frame = new JFrame("Click Counter");
frame.setSize(400,250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JButton button = new JButton("Click Here");
final JLabel label = new JLabel("Click Count: 0");
panel.add(button);
panel.add(label);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
count++;
String s = label.getText();
s = s.substring(0, s.length()-1);
label.setText(s + count);
}
});
frame.setVisible(true);
}

JAVA: Save user input as a string in a Jframe GUI

Noob here. I have been browsing for hours, and I still cannot figure out the proper way to get user input to be saved as a string from a text field in my Jframe. Any help would be appreciated. I want to save the user's text into the variable userWords.
package cipher;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
public class cipherApp extends JFrame {
private static final int WIDTH = 700;
private static final int HEIGHT = 700;
private String userWords; // stores user input into a string
public cipherApp(){
setTitle("Camo Cipher");
setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args){
cipherApp newInstance = new cipherApp();
}
}
You have to use a JTextField and a JButton to submit the use input:
public class Test extends JFrame {
String userWord = "";
JTextField userInput = new JTextField(10);
JButton submit = new JButton("Submit");
public Test() {
super("Camo Cipher");
JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 15));
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null); // This center the window on the screen
submit.addActionListener( (e)-> {
submitAction();
});
centerPanel.add(userInput);
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 15));
southPanel.add(submit);
Box theBox = Box.createVerticalBox();
theBox.add(Box.createVerticalStrut(100));
theBox.add(centerPanel);
theBox.add(Box.createVerticalStrut(200));
theBox.add(southPanel);
add(theBox);
}
private void submitAction() {
// You can do some validation here before assign the text to the variable
userWord = userInput.getText();
}
public static void main(String[] args) {
new Test().setVisible(true);
}
}
This is a variation of BilaDja's code (I mainly changed the graphics). This will make the window size at around half the screen, in the middle of the screen. If you would like to change the size, change the field 'jf.setSize(x, y);'.
package test;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test extends JFrame {
private static final long serialVersionUID = -5624404136485946868L;
String userWord = "";
JTextField userInput;
public Test() {
JFrame jf = new JFrame();
JPanel panel = new JPanel();
JLabel jl = new JLabel("Test");
JButton jButton = new JButton("Click");
userInput = new JTextField("", 30);
jButton.addActionListener( (e) -> {
submitAction();
});
jf.setSize(500, 500);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(panel);
panel.add(jl);
panel.add(userInput);
panel.add(jButton);
}
private void submitAction() {
userWord = userInput.getText();
//do something with the variabe userWord here (print it to the console, etc.)
}
public static void main(String[] args) {
new Test();
}

Java: Why doesn't my image show up?

I have created 2 classes that are working together to show pictures by clicking different buttons. In my EventEvent class I tried to make it so that when you press the "Picture 1" button, the variable ImageIcon xpic gets the value of ImageIcon vpic (which holds an image), after xpic has the same value as vpic my frame is supposed to somehow refresh so that xpic's new value applies and gets then shows the picture.
Why doesn't my image show up even though the button press repaints the JPanel the image is in?
Main class:
import java.awt.*;
import javax.swing.*;
public class EventMain extends JFrame{
EventEvent obje = new EventEvent(this);
// Build Buttons
JButton picB1;
JButton picB2;
JButton picB3;
JButton picB4;
JButton picB5;
//Build Panels
JPanel row0;
//Build Pictures
ImageIcon xpic;
ImageIcon vpic;
public EventMain(){
super("Buttons");
setLookAndFeel();
setSize(470, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout layout1 = new GridLayout(3,4);
setLayout(layout1);
picB1 = new JButton("Picture 1");
picB2 = new JButton("Picture 2");
picB3 = new JButton("Picture 3");
picB4 = new JButton("Picture 4");
picB5 = new JButton("Picture 5");
vpic = new ImageIcon(getClass().getResource("Images/vanessa.png"));
// Set up Row 0
row0 = new JPanel();
JLabel statement = new JLabel("Choose a picture: ", JLabel.LEFT);
JLabel picture = new JLabel(xpic);
// Set up Row 1
JPanel row1 = new JPanel();
// Set up Row 2
JPanel row2 = new JPanel();
//Listeners
picB1.addActionListener(obje);
FlowLayout grid0 = new FlowLayout (FlowLayout.CENTER);
row0.setLayout(grid0);
row0.add(statement);
row0.add(picture);
add(row0);
FlowLayout grid1 = new FlowLayout(FlowLayout.CENTER);
row1.setLayout(grid1);
row1.add(picB1);
row1.add(picB2);
add(row1);
FlowLayout grid2 = new FlowLayout(FlowLayout.CENTER);
row2.setLayout(grid2);
row2.add(picB3);
row2.add(picB4);
row2.add(picB5);
add(row2);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.NimbusLookAndFeel");
} catch (Exception exc) {
}
}
public static void main(String[] args) {
EventMain con = new EventMain();
}
}
Class containing events:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventEvent implements ActionListener {
EventMain gui;
public EventEvent(EventMain in){
gui = in;
}
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("Picture 1")){
gui.xpic = gui.vpic;
gui.row0.repaint();
}
}
}
You're confusing variables with objects. Just because you change the object associated with the xpic variable, don't assume that this will change the object (the Icon) held by the JLabel. There is no magic in Java, and changing the object that a variable refers to will have no effect on the prior object.
In other words, this:
gui.xpic = gui.vpic;
gui.row0.repaint();
will have no effect on the icon that the picture JLabel is displaying
To swap icons, you must call setIcon(...) on the JLabel. Period. You will need to make the picture JLabel a field, not a local variable, and give your GUI class a public method that allows outside classes to change the state of the JLabel's icon.
Also, you should not manipulate object fields directly. Instead give your gui public methods that your event object can call.
Edit
For example:
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyGui extends JPanel {
public static final String IMAGE_PATH = "https://duke.kenai.com/cards/.Midsize/CardFaces.png.png";
private static final int ROWS = 4;
private static final int COLS = 13;
private BufferedImage largeImg;
private List<ImageIcon> iconList = new ArrayList<>();
private JLabel pictureLabel = new JLabel();
private JButton swapPictureBtn = new JButton(new SwapPictureAction(this, "Swap Picture"));
private int iconIndex = 0;
public MyGui() throws IOException {
add(pictureLabel);
add(swapPictureBtn);
URL imgUrl = new URL(IMAGE_PATH);
largeImg = ImageIO.read(imgUrl);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int x = (j * largeImg.getWidth()) / COLS;
int y = (i * largeImg.getHeight()) / ROWS;
int w = largeImg.getWidth() / COLS;
int h = largeImg.getHeight() / ROWS;
iconList.add(new ImageIcon(largeImg.getSubimage(x, y, w, h)));
}
}
pictureLabel.setIcon(iconList.get(iconIndex));
}
public void swapPicture() {
iconIndex++;
iconIndex %= iconList.size();
pictureLabel.setIcon(iconList.get(iconIndex));
}
private static void createAndShowGui() {
MyGui mainPanel;
try {
mainPanel = new MyGui();
JFrame frame = new JFrame("MyGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class SwapPictureAction extends AbstractAction {
private MyGui myGui;
public SwapPictureAction(MyGui myGui, String name) {
super(name);
this.myGui = myGui;
}
#Override
public void actionPerformed(ActionEvent e) {
myGui.swapPicture();
}
}
See the createAction() method below and how it creates an AbstractAction. See also the tutorial related to using actions with buttons. http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html
import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import java.awt.*;
import java.awt.event.ActionEvent;
public class EventMain {
private static final ImageIcon PICTURE_1 = new ImageIcon(EventMain.class.getResource("images/v1.png"));
private static final ImageIcon PICTURE_2 = new ImageIcon(EventMain.class.getResource("images/v2.png"));
private JFrame frame;
EventMain create() {
setLookAndFeel();
frame = createFrame();
frame.getContentPane().add(createContent());
return this;
}
void show() {
frame.setSize(470, 300);
frame.setVisible(true);
}
private JFrame createFrame() {
JFrame frame = new JFrame("Buttons");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
private Component createContent() {
final JLabel picture = new JLabel();
JButton picB1 = new JButton(createAction("Picture 1", picture, PICTURE_1));
JButton picB2 = new JButton(createAction("Picture 2", picture, PICTURE_2));
JButton picB3 = new JButton(createAction("Picture 3", picture, PICTURE_1));
JButton picB4 = new JButton(createAction("Picture 4", picture, PICTURE_2));
JButton picB5 = new JButton(createAction("Picture 5", picture, PICTURE_1));
JLabel statement = new JLabel("Choose a picture: ", JLabel.LEFT);
// Create rows 1, 2, 3
JPanel panel = new JPanel(new GridLayout(3, 4));
panel.add(createRow(statement, picture));
panel.add(createRow(picB1, picB2));
panel.add(createRow(picB3, picB4, picB5));
return panel;
}
/**
* Create an action for the button. http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html
*/
private Action createAction(String label, final JLabel picture, final Icon icon) {
AbstractAction action = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
picture.setIcon(icon);
}
};
action.putValue(Action.NAME, label);
return action;
}
private Component createRow(Component... componentsToAdd) {
JPanel row = new JPanel(new FlowLayout(FlowLayout.CENTER));
for (Component component : componentsToAdd) {
row.add(component);
}
return row;
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new EventMain().create().show();
}
});
}
}

How to read text file before GUI program runs

I've searched through the forums but keep coming up empty for a solution.
I'm making a sort of library with a GUI program. What I want is for it to save entries via a text file. I can create objects fine with the methods I have, and can save them to a file easily. The problem comes from starting up the program again and populating a Vector with values in the text file. The objects I'm adding have a String value, followed by 7 booleans. When I try to load up from file, the String value is empty ("") and all booleans are false.
How do I get it to read the text before starting the rest of the GUI and filling the Vector right?
EDIT: Sorry for being very vague about it all. I'll post the code, but it's about 337 lines long..
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Scanner;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
#SuppressWarnings("serial")
public class SteamLibraryGUI extends JFrame implements ActionListener
{
//For main window
private JButton exitButton, addEntry, editEntry, removeEntry;
private JLabel selectGame, gameCount;
private JComboBox<String> gameCombo;
private Vector<Game> gamesList = new Vector<Game>();
private Vector<String> titleList = new Vector<String>();
private int numGames = gamesList.size();
private int selectedGame;
//For add window
private JFrame addFrame;
private JLabel gameTitle = new JLabel("Title:");
private JTextField titleText = new JTextField(60);
private JCheckBox singleBox, coopBox, multiBox, cloudBox, controllerBox, achieveBox, pcBox;
private JButton addGame, addCancel;
//For edit window
private JFrame editFrame;
private JButton editGame, editCancel;
public SteamLibraryGUI()
{
setTitle("Steam Library Organizer");
addEntry = new JButton("Add a game");
editEntry = new JButton("Edit a game");
removeEntry = new JButton("Remove a game");
exitButton = new JButton("Exit");
selectGame = new JLabel("Select a game:");
gameCount = new JLabel("Number of games:"+numGames);
gameCombo = new JComboBox<String>(titleList);
JPanel selectPanel = new JPanel();
selectPanel.setLayout(new GridLayout(1,2));
selectPanel.add(selectGame);
selectPanel.add(gameCombo);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1,3));
buttonPanel.add(addEntry);
buttonPanel.add(editEntry);
buttonPanel.add(removeEntry);
JPanel exitPanel = new JPanel();
exitPanel.setLayout(new GridLayout(1,2));
exitPanel.add(gameCount);
exitPanel.add(exitButton);
Container pane = getContentPane();
pane.setLayout(new GridLayout(3,1));
pane.add(selectPanel);
pane.add(buttonPanel);
pane.add(exitPanel);
addEntry.addActionListener(this);
editEntry.addActionListener(this);
removeEntry.addActionListener(this);
exitButton.addActionListener(this);
gameCombo.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==addEntry)
addEntry();
if(e.getSource()==editEntry)
editEntry(gamesList.get(selectedGame));
if(e.getSource()==removeEntry)
{
removeEntry(selectedGame);
update();
}
if(e.getSource()==exitButton)
exitProg();
if(e.getSource()==gameCombo)
{
selectedGame = gameCombo.getSelectedIndex();
}
if(e.getSource()==singleBox)
singleBox.isSelected();
if(e.getSource()==coopBox)
coopBox.isSelected();
if(e.getSource()==multiBox)
multiBox.isSelected();
if(e.getSource()==cloudBox)
cloudBox.isSelected();
if(e.getSource()==controllerBox)
controllerBox.isSelected();
if(e.getSource()==achieveBox)
achieveBox.isSelected();
if(e.getSource()==pcBox)
pcBox.isSelected();
if(e.getSource()==addGame)
{
gamesList.add(new Game(titleText.getText(), singleBox.isSelected(), coopBox.isSelected(),
multiBox.isSelected(), cloudBox.isSelected(), controllerBox.isSelected(),
achieveBox.isSelected(), pcBox.isSelected()));
titleList.add(titleText.getText());
addFrame.dispose();
update();
}
if(e.getSource()==addCancel)
addFrame.dispose();
if(e.getSource()==editCancel)
editFrame.dispose();
if(e.getSource()==editGame)
{
gamesList.get(selectedGame).name = titleText.getText();
gamesList.get(selectedGame).single = singleBox.isSelected();
gamesList.get(selectedGame).coop = coopBox.isSelected();
gamesList.get(selectedGame).multi = multiBox.isSelected();
gamesList.get(selectedGame).cloud = cloudBox.isSelected();
gamesList.get(selectedGame).controller = controllerBox.isSelected();
gamesList.get(selectedGame).achieve = achieveBox.isSelected();
gamesList.get(selectedGame).pc = pcBox.isSelected();
titleList.remove(selectedGame);
titleList.add(titleText.getText());
editFrame.dispose();
update();
}
}
public void update()
{
Collections.sort(titleList);
Collections.sort(gamesList);
gameCombo.updateUI();
titleText.setText("");
gameCombo.setSelectedIndex(-1);
numGames = gamesList.size();
gameCount.setText("Number of games:"+numGames);
}
public void addEntry()
{
addFrame = new JFrame("Add Entry");
addFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
addFrame.getContentPane();
addFrame.setLayout(new GridLayout(3,1));
singleBox = new JCheckBox("Single-Player");
singleBox.setSelected(false);
coopBox = new JCheckBox("Coop");
coopBox.setSelected(false);
multiBox = new JCheckBox("MultiPlayer");
multiBox.setSelected(false);
cloudBox = new JCheckBox("Steam Cloud");
cloudBox.setSelected(false);
controllerBox = new JCheckBox("Controller Support");
controllerBox.setSelected(false);
achieveBox = new JCheckBox("Achievements");
achieveBox.setSelected(false);
pcBox = new JCheckBox("For New PC");
pcBox.setSelected(false);
addGame = new JButton("Add game");
addCancel = new JButton("Cancel");
JPanel titlePanel = new JPanel();
titlePanel.setLayout(new FlowLayout());
titlePanel.add(gameTitle);
titlePanel.add(titleText);
JPanel checkPanel = new JPanel();
checkPanel.setLayout(new FlowLayout());
checkPanel.add(singleBox);
checkPanel.add(coopBox);
checkPanel.add(multiBox);
checkPanel.add(cloudBox);
checkPanel.add(controllerBox);
checkPanel.add(achieveBox);
checkPanel.add(pcBox);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(addGame);
buttonPanel.add(addCancel);
addFrame.add(titlePanel);
addFrame.add(checkPanel);
addFrame.add(buttonPanel);
singleBox.addActionListener(this);
coopBox.addActionListener(this);
multiBox.addActionListener(this);
cloudBox.addActionListener(this);
controllerBox.addActionListener(this);
achieveBox.addActionListener(this);
pcBox.addActionListener(this);
addGame.addActionListener(this);
addCancel.addActionListener(this);
addFrame.pack();
addFrame.setVisible(true);
}
public void editEntry(Game g)
{
editFrame = new JFrame("Edit Entry");
editFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
editFrame.getContentPane();
editFrame.setLayout(new GridLayout(3,1));
singleBox = new JCheckBox("Single-Player");
singleBox.setSelected(g.single);
coopBox = new JCheckBox("Coop");
coopBox.setSelected(g.coop);
multiBox = new JCheckBox("MultiPlayer");
multiBox.setSelected(g.multi);
cloudBox = new JCheckBox("Steam Cloud");
cloudBox.setSelected(g.cloud);
controllerBox = new JCheckBox("Controller Support");
controllerBox.setSelected(g.controller);
achieveBox = new JCheckBox("Achievements");
achieveBox.setSelected(g.achieve);
pcBox = new JCheckBox("For New PC");
pcBox.setSelected(g.pc);
editGame = new JButton("Edit game");
editCancel = new JButton("Cancel");
titleText.setText(g.name);
JPanel titlePanel = new JPanel();
titlePanel.setLayout(new FlowLayout());
titlePanel.add(gameTitle);
titlePanel.add(titleText);
JPanel checkPanel = new JPanel();
checkPanel.setLayout(new FlowLayout());
checkPanel.add(singleBox);
checkPanel.add(coopBox);
checkPanel.add(multiBox);
checkPanel.add(cloudBox);
checkPanel.add(controllerBox);
checkPanel.add(achieveBox);
checkPanel.add(pcBox);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(editGame);
buttonPanel.add(editCancel);
editFrame.add(titlePanel);
editFrame.add(checkPanel);
editFrame.add(buttonPanel);
singleBox.addActionListener(this);
coopBox.addActionListener(this);
multiBox.addActionListener(this);
cloudBox.addActionListener(this);
controllerBox.addActionListener(this);
achieveBox.addActionListener(this);
pcBox.addActionListener(this);
editGame.addActionListener(this);
editCancel.addActionListener(this);
editFrame.pack();
editFrame.setVisible(true);
}
public void removeEntry(int g)
{
Object[] options = {"Yes, remove the game", "No, keep the game"};
int n = JOptionPane.showOptionDialog(null, "Are you sure you want to remove this game from the list?",
"Remove game?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]);
if (n==0)
{
gamesList.remove(g);
titleList.remove(g);
}
}
public void exitProg()
{
try
{
PrintWriter out = new PrintWriter("games.txt");
out.flush();
for(int i=0;i<gamesList.size();i++)
{
out.print(gamesList.get(i).toString());
}
out.close();
}
catch (FileNotFoundException e) {}
System.exit(0);
}
public static void main(String[] args)
{
SteamLibraryGUI frame = new SteamLibraryGUI();
frame.pack();
frame.setSize(600,200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Scanner in = new Scanner("games.txt");
while(in.hasNextLine())
{
String line = in.nextLine();
String[] options = line.split("|");
Game g = new Game(options[0],Boolean.getBoolean(options[1]),
Boolean.getBoolean(options[2]),Boolean.getBoolean(options[3]),
Boolean.getBoolean(options[4]),Boolean.getBoolean(options[5]),
Boolean.getBoolean(options[6]),Boolean.getBoolean(options[7]));
frame.gamesList.add(g);
frame.titleList.add(options[0]);
System.out.println(g.toString());
}
in.close();
}
}
There's also a Game class, but it's simply 1 String, and then 7 booleans.
There were two significant bugs in the code. First, Scanner was constructed with a string parameter (which means that the Scanner scanned the string, not the file named by the string). Second, the pipe character "|" is a regular expression metacharacter. That is important because line.split() splits on regular expressions. Thus, the "|" has to be escaped. The main() function works fine if it is written as follows (with debugging output code included to show that each step is working correctly):
public static void main(String[] args)
{
SteamLibraryGUI frame = new SteamLibraryGUI();
frame.pack();
frame.setSize(600,200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try
{
Scanner in = new Scanner(new File("games.txt"));
while(in.hasNextLine())
{
System.out.println("line = ");
String line = in.nextLine();
System.out.println(line);
String[] options = line.split("\\|");
System.out.println("Options = ");
for (String s : options)
{
System.out.println(s);
}
Game g = new Game(options[0],Boolean.getBoolean(options[1]),
Boolean.getBoolean(options[2]),Boolean.getBoolean(options[3]),
Boolean.getBoolean(options[4]),Boolean.getBoolean(options[5]),
Boolean.getBoolean(options[6]),Boolean.getBoolean(options[7]));
frame.gamesList.add(g);
frame.titleList.add(options[0]);
System.out.println(g.toString());
}
in.close();
} catch (IOException x)
{
System.err.println(x);
}
}
There is one other important Gotcha: The method exitProg() writes the "games.txt" file out again before the program finishes. This creates a problem if the file was read incorrectly in the first place because the wrong data will be written back to the file. During testing, this means that even when the reading code has been corrected, it will still read the erroneous data that was written from a previous test run.
My preference in this situation is would be to isolate all the reading and writing code for "game.txt" inside the Game class (which makes it easier to verify that the reading and writing formats are identical) and only write the code to write the data back out once I'd written and tested the reading code, which would avoid this Gotcha.

Categories