I can't get image to display - java

I have a chat client program I am working on and currently I can get the text pane, text input on the left. I can add buttons and change the background color to the right but I can not get an image to display on the right. There is more than one way to skin a cat on this from what I've read but I'm trying to stick with the setup I currently have so I don't have to rewrite everything. I understand the basics of Java (OOP) and how it works. I'm just lost as to how to format image icon and get this image to display. Here is the code: I am compiling with IntelliJ.
package edu.lmu.cs.networking;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.ImageIcon;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ChatClient {
private BufferedReader in;
private PrintWriter out;
private JFrame frame = new JFrame("Chatter");
private JTextField textField = new JTextField(20);
private JTextArea messageArea = new JTextArea(8, 40);
private JPanel panel;
private JButton button;
private JLabel label;
public ChatClient() {
textField.setEditable(false);
messageArea.setEditable(false);
// frame.setSize(500, 500);
// frame.setVisible(true);
frame.getContentPane().add(textField, "South");
frame.getContentPane().add(new JScrollPane(messageArea), "West");
panel = new JPanel();
panel.setBackground(Color.YELLOW);
button = new JButton("Button");
label = new JLabel(new ImageIcon("x.gif"));
panel.add(button);
panel.add(label, BorderLayout.EAST);
frame.add(panel);
frame.pack();
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
private String getServerAddress() {
return JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:",
"Welcome to the Chatter", JOptionPane.QUESTION_MESSAGE);
}
private String getName() {
return JOptionPane.showInputDialog(frame, "Choose a screen name:", "Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = getServerAddress();
Socket socket = new Socket(serverAddress, 5910);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
Thanks in advance,
-Brandon

You can just change your code as below and it will work. Just tested it on my own computer and it worked.
ImageIcon icon = new ImageIcon(getClass().getResource("x.gif"));
label = new JLabel(icon);
It seems your problem is that you didn't actually loaded the image in. Remember to use a ClassLoader to load the resource files.
You should place 'x.gif' under your project directory or your resource folder(preferred) in order to make this work.
For more details about loading resources, take a look at this link.

If the image is in your projects root directory,then you can access it the directly,similar to what you have done.
If it is inside some folder(say resources folder) in your project structure you need to use getClass().getResource("/resources/x.gif").
You can also create a scaled version of the image,specifying the height and width.It can be done using the sample code below:
ImageIcon icon = new ImageIcon("x.gif");
Image img = icon.getImage();
Image newimg = img.getScaledInstance(30, 20,
java.awt.Image.SCALE_SMOOTH);
icon = new ImageIcon(newimg);
label = new JLabel(icon);

Related

Is There a Way to Make a Java Method that Opens a .txt File as a pop-up? [duplicate]

This question already has answers here:
Loading a text file into a textarea
(4 answers)
Trying to read a text file into a JTextArea
(2 answers)
Open a text file in the default text editor... via Java?
(3 answers)
Closed 2 months ago.
I am currently making a java project that simulates a website for swimmers. It has multiple classes and incorporates the Jswing GUI. I have buttons that are used to display other classes GUI and data, but I was wondering if there was a way to have it so when I click a button, it would pull up a .txt file as a pop up externally, as opposed to just reading and writing the .txt files data into my console.
I had initially tried to display information from a .txt file into a JLabel or JTextField so it could be seen but I had abandoned that idea in order to pursue the easier and simplier idea of bringing up a entirely new window of a .txt file
package finalProject;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class FrontInterface extends JPanel {
private static JButton nSwimmer;
private static JButton cSwimmer;
private static JButton coach;
private JLabel heading;
private static JButton equipment;
public FrontInterface() {
//construct components
nSwimmer = new JButton ("New Swimmer");
cSwimmer = new JButton ("Current Swimmer");
coach = new JButton ("Coach");
heading = new JLabel ("Welcome to the Swimming Station");
equipment = new JButton ("Equipment");
//adjust size and set layout
setPreferredSize (new Dimension (752, 425));
setLayout (null);
//add components
add (nSwimmer);
add (cSwimmer);
add (coach);
add (heading);
add (equipment);
//set component bounds (only needed by Absolute Positioning)
nSwimmer.setBounds (280, 150, 200, 20);
cSwimmer.setBounds (280, 175, 200, 20);
coach.setBounds (280, 200, 200, 20);
heading.setBounds (280, 95, 195, 30);
equipment.setBounds (280, 225, 200, 25);
}
public static void showWindow(){
JFrame frame = new JFrame ("Front Interface");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FrontInterface());
frame.pack();
frame.setVisible(true);
nSwimmer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
frame.setVisible(false);
NewSwimmerForm w2 = new NewSwimmerForm();
w2.showWindow();
}
});
cSwimmer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
frame.setVisible(false);
CurrentSwimmer w2_1 = new CurrentSwimmer();
w2_1.showWindow();
}
});
coach.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
frame.setVisible(false);
NewSwimmerForm w2 = new NewSwimmerForm();
w2.showWindow();
}
});
equipment.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
frame.setVisible(false);
NewSwimmerForm w2 = new NewSwimmerForm();
w2.showWindow();
}
});
frame.setVisible(true);
}
public static void main (String[] args) {
showWindow();
}
}
And below is the code that the cSwimmer button will take you to upon clicking the cSwimmer button:
package finalProject;
import finalProject.FrontInterface;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class CurrentSwimmer extends JPanel {
private static JTextArea informationHeader;
public static void showWindow(){
try{
File file = new File("C:\\Users\\trent\\Desktop\\Intro to Computer Science\\Eclipse Codes\\FinalProject\\src\\finalProject\\history.txt");
System.out.println(file.getCanonicalPath());
FileInputStream ft = new FileInputStream(file);
DataInputStream in = new DataInputStream(ft);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strline;
while((strline = br.readLine()) != null){
System.out.println(strline);
}
in.close();
}catch(Exception e){
System.err.println("Error: " + e.getMessage());
}
}
public static void main(String [] args) {
showWindow();
}
}
Now, I am completely unsure of how to go about my situation, whether it be I display the information from the .txt file onto a jTextArea or if I should just create a method to make a .txt file open externally and replace the pop up window I would otherwise have with the writing to JTextArea.

How to keep a GUI running after a program is run in Java

I am a high school student working on a project that will convert the video from a YouTube link into an MP3 and download it. This program opens a GUI and has a button that converts the video from the link into an MP3 and downloads it. However, after the link gets converted I want it to open up another GUI, but the program just ends. Is there any way to have the program to continue to run after the downloading process?
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class GUI extends JFrame {
private static JTextField userLink;
private static JFrame frameOne;
private static JPanel panelOne;
private static JButton convertB;
private static JLabel titleOne;
private static JLabel name;
public String youtubeLink;
public static JLabel titleTwo;
public static JLabel info;
public GUI() {
panelOne = new JPanel();
frameOne = new JFrame();
frameOne.setSize(500, 300);
frameOne.setBackground(Color.CYAN);
frameOne.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frameOne.setVisible(true);
frameOne.add(panelOne);
panelOne.setLayout(null);
titleOne = new JLabel("Welcome to the Youtube"); //Title for first panel
titleOne.setBounds(55, 10, 500, 30);
titleOne.setFont(new Font("Courier", Font.BOLD, 30));
panelOne.add(titleOne);
titleTwo = new JLabel("to MP3 Converter!"); //Title for first panel
titleTwo.setBounds(100, 40, 500, 30);
titleTwo.setFont(new Font("Courier", Font.BOLD, 30));
panelOne.add(titleTwo);
name = new JLabel("By Zeid Akel");
name.setBounds(220, 80, 80, 25);
panelOne.add(name);
convertB = new JButton("Convert and Download"); //Convert and
convertB.setBounds(170, 220, 175, 50);
convertB.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
youtubeLink = userLink.getText();
System.out.println(youtubeLink);
String s;
String l = "youtube-dl -x --audio-format mp3 ";
String rl = l + youtubeLink;
File f = new File("/Users/zeidakel/YoutubeVideos"); //Location where
if (!f.exists()) {
System.out.println("Download Location does not exist"); //Check if
} else {
try {
Process p = Runtime.getRuntime().exec(rl); //Code put int terminal
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
System.out.println("Output:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("Errors:\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
frameOne.setVisible(false);
new GUI2();
System.exit(0);
} catch (IOException e1) {
}
}
}
});
panelOne.add(convertB);
userLink = new JTextField(); //Input area for youtube link
userLink.setBounds(135, 190, 250, 25);
panelOne.add(userLink);
info = new JLabel("Paste your link here:");
info.setBounds(140, 170, 250, 25);
panelOne.add(info);
frameOne.setVisible(true);
}
}
The GUI should always be running you should never close it or try to create a new JFrame.
Instead, the task to convert the video should be run in a separate Thread, so you don't prevent the GUI from responding to events.
An easy way to do this is to use a SwingWorker. Read the section from the Swing tutorail on Concurrency for more information and examples.
Other comments:
Swing components should NOT be defined as static variables. That is not what the static keyword is used for.
Don't use a null layout and setBounds(). Swing was designed to be used with layout managers.

I cannot load Images in .JAR [duplicate]

This question already has answers here:
Once exported, java cannot find/draw images
(2 answers)
Closed 6 years ago.
I'm a student currently studying Java Programming and using Netbeans to create the application. The program is already done and loads nicely in the IDE (with images). I have to build it into JAR for a presentation to my lecturer and has done it but the images are not present in the JAR.
First of all, I've checked all the available answers for allowing images to be present in the JAR but I couldn't get it right with the program as it doesn't load even in IDE and shows error. Which most have pointed out that I have to input (getClass().getClassLoader().getResource("image.jpg")). I tried inputting it but it shows errors, mostly because my codes for placing the ImageIcon are different.
Below is my full code of the JFrame presenting the program:
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;
import javax.swing.ImageIcon;
import java.util.logging.Level;
import java.util.logging.Logger;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class A2{
public void GUI () throws IOException {
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setTitle("Minus");
frame.setSize(700,500);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
//Set the layout
JPanel panel;
panel = new JPanel();
panel.setLayout(null);
frame.setContentPane(panel);
// Create all components
JLabel ctgy = new JLabel("Minus");
JLabel minus2 = new JLabel("What is 6 squares minus 3 squares?");
JButton ans_a = new JButton("9");
JButton ans_b = new JButton("3");
JButton ans_c = new JButton("7");
JButton back = new JButton("Back");
JLabel min2 = new JLabel();
//Add objects to layout
panel.add(ctgy);
panel.add(minus2);
panel.add(min2);
panel.add(ans_a);
panel.add(ans_b);
panel.add(ans_c);
panel.add(back);
// Set position of objects in content pane
min2.setLocation(100,100);
minus2.setLocation(20,50);
ctgy.setLocation(10,3);
ans_a.setLocation(500,100);
ans_b.setLocation(500,150);
ans_c.setLocation(500,200);
back.setLocation(500, 400);
//Set size of object
min2.setSize(300,300);
ctgy.setSize(200,50);
minus2.setSize(350,50);
ans_a.setSize(100,30);
ans_b.setSize(100,30);
ans_c.setSize(100,30);
back.setSize(100, 30);
//Set the fonts and colors
Font font1 = new Font("Cooper Black", Font.BOLD, 26);
Font font2 = new Font("Calisto MT", Font.BOLD, 20);
ctgy.setFont(font1);
ctgy.setBackground(Color.white);
minus2.setFont(font2);
minus2.setBackground(Color.red);
panel.setBackground (Color.RED);
ans_a.setBackground(Color.white);
ans_b.setBackground(Color.white);
ans_c.setBackground(Color.white);
min2.setIcon(new ImageIcon("src/images/6-3.png"));
ans_b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Correct!");
try {
A3.main(null);
} catch (IOException ex) {
Logger.getLogger(A1.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
ans_a.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Incorrect! Please try again.");
}
});
ans_c.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Incorrect! Please try again.");
}
});
frame.repaint();
back.addActionListener(new ActionListener () {
public void actionPerformed(ActionEvent f){
Categories.main(null);
}
});
}
public static void main (String [] args) throws IOException {
A2 gd = new A2();
gd.GUI();
}
}
This is the part of my code where I state the JLabel to put my image in which I named as min2:
JLabel ctgy = new JLabel("Minus");
JLabel minus2 = new JLabel("What is 6 squares minus 3 squares?");
JButton ans_a = new JButton("9");
JButton ans_b = new JButton("3");
JButton ans_c = new JButton("7");
JButton back = new JButton("Back");
JLabel min2 = new JLabel();
This is adding the panel for the JLabel:
panel.add(min2);
The size and location:
min2.setLocation(100,100);
min2.setSize(300,300);
Lastly the image itself and location:
min2.setIcon(new ImageIcon("src/images/6-3.png"));
This part will show error because I set this to open a new Class when a user click the JButton so that would happen since you don't have the A3 Class:
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Correct!");
try {
A3.main(null);
} catch (IOException ex) {
Logger.getLogger(A1.class.getName()).log(Level.SEVERE, null, ex);
}
I've checked the JAR file with WinRAR and confirmed that images folder and the images are inside. I wanted to post the screenshots but Imgur isn't working for me.
The pathfile for all images are inside src/images.
Please suggest what changes I need to make. Thank you and sorry if it has been asked too much.
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/img.png")));
this is how you should actually load the image file.your given file path is wrong try it with this approach.

Java: Swing component(s) not repainting

I'm using some sample code from the Java website, and the file selector seems to get the file I want, but when I try to update the jframe and other components in the gui I used to call the file selector, nothing changes. I've tried quite a few of the suggested fixes to get things to update, but nothing seems to work. Most of my components are static by the way...
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.awt.event.*;
public class GuiTester extends JFrame {
private static String fileName = "Input File: Please select a file";
//Create a file chooser
private static final JFileChooser fc = new JFileChooser();
private static JButton inputSelectorButton;
private static JButton outputSelectorButton;
private static JFrame frame = new JFrame( "Gui Tester" );
private static JPanel panel = new JPanel();
private static JLabel inputFile = new JLabel( fileName );
public static void main(String[] args) {
go();
}
private static void go() {
inputSelectorButton = new JButton ( "Select Input File" );
outputSelectorButton = new JButton ( "Select Output File" );
Font bigFont = new Font( "sans", Font.BOLD, 22 );
Font smallFont = new Font( "sans", Font.PLAIN, 9 );
panel.setLayout(new BoxLayout( panel, BoxLayout.Y_AXIS ) );
JLabel description0 = new JLabel(" ");
JLabel description6 = new JLabel(" ");
JLabel inputFile = new JLabel( fileName );
inputFile.setFont( smallFont );
inputSelectorButton.addActionListener( new inputSelectorListener() );
JButton startButton = new JButton ( "GO!" );
panel.add(description0);
panel.add(description6);
panel.add( inputFile );
panel.add( inputSelectorButton );
panel.add( outputSelectorButton );
panel.add( startButton );
frame.getContentPane().add( BorderLayout.CENTER, panel );
inputFile.setAlignmentX(JComponent.CENTER_ALIGNMENT);
inputSelectorButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
outputSelectorButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
startButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
frame.setSize(370,400);
panel.setSize(370,400);
frame.setVisible(true);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public static class inputSelectorListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == inputSelectorButton) {
int returnVal = fc.showOpenDialog( panel );
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
if ( file.exists() )
fileName = file.getPath();
else
fileName = "File not found, please select a file";
System.out.println(fileName);
inputFile.setText( fileName );
inputFile.validate();
inputFile.repaint();
panel.validate();
panel.repaint();
frame.validate();
frame.repaint();
} else {
System.out.println("Open command cancelled by user.");
}
}
}
}
}
I do not see anywhere you add
inputFile
panel
To anything that is displayable.
You are also shadowing inputFile.
You create an static reference...
private static JLabel inputFile = new JLabel(fileName);
Then in go, you create a local reference...
JLabel inputFile = new JLabel(fileName);
This means that the reference you using in the actionPerformed method is not the same reference that is on the screen.
Do not rely on static to solve reference issues, this will bite you more quickly then you can realise...
You might like to take a look at:
Initial Threads
Code Conventions for the Java Programming Language
You should try to use classes and organize your code better. Below I have redesigned your existing code. I did not add anything, but I did move some stuff around and remove a couple unnecessary variables for this example.
I changed your ActionListener to an AbstractAction, just to let you know. :-p
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class GuiTester extends JPanel {
// Create a file chooser
private static final JFileChooser fc = new JFileChooser();
private JLabel inputFile;
public GuiTester(int width, int height) {
Font smallFont = new Font("sans", Font.PLAIN, 9);
JLabel description0 = new JLabel(" ");
JLabel description6 = new JLabel(" ");
JButton startButton = new JButton("Enter");
JButton inputSelectorButton = new JButton(new FileChooserAction(
"Select Input File"));
JButton outputSelectorButton = new JButton("Select Output File");
inputFile = new JLabel("Input File: Please select a file");
inputFile.setFont(smallFont);
inputFile.setAlignmentX(JComponent.CENTER_ALIGNMENT);
inputSelectorButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
outputSelectorButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
startButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
add(description0);
add(description6);
add(inputFile);
add(inputSelectorButton);
add(outputSelectorButton);
add(startButton);
setSize(width, height);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
public JLabel getInputFileLabel() {
return inputFile;
}
#Override
public void invalidate() {
super.invalidate();
// Invalidate the label, you really don't need this, but you should
// reference children in here if you want to explicitly invalidate them
// when the parent gets invalidated. The parent is responsible for
// telling its children what to do and when to do it.
inputFile.invalidate();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// This gets called when you repaint, since you are adding children
// to this panel, painting is pointless. You can however fill the
// background if you wish.
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Gui Test");
f.setContentPane(new GuiTester(370, 400));
f.setSize(370, 400);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
}
});
}
public class FileChooserAction extends AbstractAction {
public FileChooserAction(String name) {
super(name);
}
public void actionPerformed(ActionEvent e) {
Container c = ((JButton) e.getSource()).getParent();
GuiTester g = null;
if (c instanceof GuiTester) {
g = (GuiTester) c;
}
int returnVal = fc.showOpenDialog(c);
if (g != null && returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
String fileName = "Input File: Please select a file";
if (file.exists())
fileName = file.getPath();
else
fileName = "File not found, please select a file";
System.out.println(fileName);
g.getInputFileLabel().setText(fileName);
g.validate();
g.repaint();
} else {
System.out.println("Open command cancelled by user.");
}
}
}
}

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