I can't figure out how to call this class and make it execute. I am calling methods from other classes to make a menu to take it to different related tasks as lesson on Mexico, but I can't figure out how to make it display this class. in the different cases each call a method that executes it. i want to do this for the second program i posted. I want to make it execute th program so it can play its song
Main Class:
import javax.swing.JOptionPane;
public class MexicoProject
{
public static void main(String[] args)
{
String[] choice = {"History", "Trivia", "Intro", "Anthem", "Quit"};
String Menu;
do
{
Menu = (String)JOptionPane.showInputDialog(null, "Welcome, this program will teach you about the history of Mexico.\nPick one of the options below.",
"Mexico History", JOptionPane.QUESTION_MESSAGE, null, choice, choice[0]);
if (Menu == null)
JOptionPane.showMessageDialog(null, "Pick something!");
else
{
switch (Menu)
{
case "History":
MexicoHistory.History();
break;
case "Trivia":
Quiz();
break;
case "Intro":
FrenchIntro.Intro();
break;
case "Anthem":
{
break;
}
break;
case "Quit":
JOptionPane.showMessageDialog(null, "Goodbye!");
break;
default:
JOptionPane.showMessageDialog(null, "Something went wrong! Try again!");
}
}
} while (Menu != "Quit");
}
Class Being Called:
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class Song extends JFrame
{
AudioFormat audioFormat;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
boolean stopPlayback = false;
final JButton stopBtn = new JButton("Stop");
final JButton playBtn = new JButton("Play");
final JTextField textField = new JTextField("MexicanNationalAnthem.wav");
public static void main(String args[])
{
new Song();
}//end main
//-------------------------------------------//
public Song() //constructor
{
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
//Instantiate and register action listeners
// on the Play and Stop buttons.
playBtn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
playAudio();//Play the file
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
stopBtn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//Terminate playback before EOF
stopPlayback = true;
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(playBtn,"West");
getContentPane().add(stopBtn,"East");
getContentPane().add(textField,"North");
setTitle("Himno Nacional Mexicano");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(250,70);
setVisible(true);
}//end constructor
//-------------------------------------------//
//This method plays back audio data from an
// audio file whose name is specified in the
// text field.
public void playAudio()
{
try
{
File soundFile = new File(textField.getText());
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
audioFormat = audioInputStream.getFormat();
System.out.println(audioFormat);
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat);
sourceDataLine =(SourceDataLine)AudioSystem.getLine(dataLineInfo);
//Create a thread to play back the data and
// start it running. It will run until the
// end of file, or the Stop button is
// clicked, whichever occurs first.
// Because of the data buffers involved,
// there will normally be a delay between
// the click on the Stop button and the
// actual termination of playback.
new PlayThread().start();//call the PlayThread class
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}//end catch
}//end playAudio
//=============================================//
//Inner class to play back the data from the
// audio file.
class PlayThread extends Thread
{
byte tempBuffer[] = new byte[10000];
public void run()
{
try
{
sourceDataLine.open(audioFormat);
sourceDataLine.start();
int cnt;
//Keep looping until the input read method
// returns -1 for empty stream or the
// user clicks the Stop button causing
// stopPlayback to switch from false to
// true.
while((cnt = audioInputStream.read(tempBuffer,0,tempBuffer.length)) != -1&& stopPlayback == false)
{
if(cnt > 0)
{
//Write data to the internal buffer of
// the data line where it will be
// delivered to the speaker.
sourceDataLine.write(tempBuffer, 0, cnt);
}//end if
}//end while
//Block and wait for internal buffer of the
// data line to empty.
sourceDataLine.drain();
sourceDataLine.close();
//Prepare to playback another file
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
stopPlayback = false;
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}//end catch
}//end run
}//end inner class PlayThread
}//===================================//
Make sure that all the classes remain in same package.
You can call the method of other classes by creating a object for class being called ..
then use the object to call the method name..
classbeingcalled obj= new classbeingcalled();
obj.methodname();
or declare your method as a static method so you can call the method by using the class name
public static returntype methodname(){
...
}
from any class in the package
classname.methodname();
PS: If you are not satisfied with this answer or dint expect this answer please be clear with your question.
Related
So I have been making a stop button recently and have been wondering how can I stop a button sound instantly when already playing.
The problem : When you click the stop sound button, it only stops the next button you press.
What Im Trying to Achieve : When you click the stop sound button, it stops all playing sounds.
Here is the main button class sound :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
//JButtons Class
public class Buttons extends JButton implements ActionListener{
private int locX = 0;
private int locY = 0;
//Sets the basic features of the buttons and adds an action listener
public Buttons(String title){
super(title);
setBounds(locX,locY,100,100);
setOpaque(true);
setBorderPainted(false);
setBorder(BorderFactory.createLineBorder(Color.WHITE));
addActionListener(this);
}
//Sets the dimentions of the buttons
public void setDimentions(int x, int y){
this.locX = x;
this.locY = y;
setBounds(locX,locY,100,100);
}
//Maps button colors to sting values
static Map<String, Color> colorMap = Map.ofEntries(Map.entry("WHITE", Color.WHITE), Map.entry("GRAY", Color.GRAY), Map.entry( "BLACK", Color.BLACK), Map.entry( "RED", Color.RED), Map.entry( "ORANGE", new Color(255,121,0)), Map.entry( "YELLOW", Color.YELLOW), Map.entry( "GREEN", Color.GREEN), Map.entry( "BLUE", Color.BLUE), Map.entry( "MAGENTA", Color.MAGENTA), Map.entry( "PINK", Color.PINK), Map.entry( "CYAN", Color.CYAN));
//Gets the color from the map and returns it
static Color getColor(String col){
return colorMap.get(col.toUpperCase());
}
//Sets the color of the button and repaints it
public void setColors(String colorBack, String colorFront){
setBackground(getColor(colorBack));
setForeground(getColor(colorFront));
repaint();
}
public String[] listFilesForFolder(final File folder) {
String[] f = new String[25];
int count = 0;
for(int i = 0; i < 25; i++){
f[i] = "";
}
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
if(fileEntry.getName().equals(".DS_Store")){
}else{
f[count] = fileEntry.getName();
count++;
}
}
}
return f;
}
public void playSound(String url, boolean loop, boolean stop){
try{
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Launchpad.class.getResource("soundFiles/" + url));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
if(loop == true){
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
if(stop == true){
stopSound(clip);
}
}
catch(Exception e){
System.out.println("Error");
}
}
public void stopSound(Clip clip){
if(clip.isActive()){
clip.stop();
clip.flush();
clip.close();
}
}
//Event Handler / Action Listener
#Override
public void actionPerformed(ActionEvent e){
if(e.getSource() == this){
String sNum = this.getText();
int num = Integer.parseInt(sNum);
final File folder = new File("/Users/ethanbowles/Desktop/idk/programing/java/Launchpad/soundFiles");
String[] names =listFilesForFolder(folder);
System.out.println(names[num - 1]);
System.out.println(num);
boolean fullStop = StopButton.stop;
playSound(names[num - 1], LoopButton.loop, fullStop);
StopButton.stop = false;
LoopButton.loop = false;
}
}
}
Here is the main sound stop button :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class StopButton extends JButton implements ActionListener{
public static boolean stop = false;
public StopButton(){
super("Stop");
setBounds(10,10,100,50);
addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e){
if(e.getSource() == this){
if(stop == true){
stop = false;
}else{
stop = true;
}
super.repaint();
}
}
}
The problem is due to the logic with the .stop field in one JButton modified by the other JButton. Also reusing playSound() to play or stop is not a good design.
Here is a solution with a much cleaner design with 2 buttons, one for play one for stop.
The MusicController is independent from the UI:
class MusicController
{
// A property for the state of the controller
public final static String PROP_STATE = "StateProperty";
enum State
{
NOT_READY, STOPPED, PLAYING
};
State state = State.NOT_READY;
boolean loop;
// Manage property change listeners
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void loadSound()
{
// Initialize music data, load clip from file etc.
...
State oldState = state;
state = State.STOPPED; // We can actually play a sound only from the STOPPED state
pcs.firePropertyChange(PROP_STATE, oldState, state);
}
public State getState()
{
return state;
}
public void play()
{
switch (state)
{
case NOT_READY:
// Error "Not ready"
...
break;
case STOPPED:
// Start playback (looped if loop is true)
...
State oldState = state;
state = State.PLAYING;
pcs.firePropertyChange(PROP_STATE, oldState, state); // Notify listeners
break;
case PLAYING:
// Already playing, do nothing
break;
default:
throw new AssertionError(state.name());
}
}
public void stop()
{
// Same code structure than play(), but adapted to stop playback if current state is PLAYING.
...
}
public void addPropertyChangeListener(PropertyChangeListener listener)
{
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener)
{
pcs.removePropertyChangeListener(listener);
}
}
The View manages the UI and just listens to the MusicController state.
class View implements PropertyChangeListener
{
JButton playButton, stopButton;
MusicController controller = new MusicController();
public View()
{
// Listen to music controller state changes
controller.addPropertyChangeListener(this);
// Create UI
Action playAction = new AbstractAction("Play")
{
public void actionPerformed(ActionEvent ae)
{
controller.play();
}
};
playButton = new JButton(playAction);
// Same for stopButton with controller.stop();
...
// Add buttons to UI etc.
...
updateUI(controller.getState());
}
/**
* Update the user interface depending on the music controller state.
*
* #param state
*/
private void updateUI(State state)
{
switch (state)
{
case NOT_READY:
playButton.setEnabled(false);
stopButton.setEnabled(false);
break;
case STOPPED:
playButton.setEnabled(true);
stopButton.setEnabled(false);
break;
case PLAYING:
playButton.setEnabled(false);
stopButton.setEnabled(true);
break;
default:
throw new AssertionError(state.name());
}
}
/**
* Called when a MusicController property has changed.
*/
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getSource() == controller && MusicController.PROP_STATE.equals(evt.getPropertyName()))
{
// State has changed, update UI accordingly
State state = (State) evt.getNewValue();
updateUI(state);
}
}
}
I think you need to change the scope of your Clips. Currently they are local variables. They need to be instance variables. Then, place all Clips that are eligible for "stopping" into a collection. When you want to stop them all at once, you can iterate through that collection.
Having a collection of Clips will require a bit more overhead. You'll have to make sure you remove a Clip from the collection when you are finished with it, for example. Also, because iterating through the collection and adding/removing could potentially happen concurrently, a thread-safe collection such as CopyOnWriteArrayList would likely be a better choice than an ArrayList.
I want to play music when my getoutput method is invoked and stop the music when the invoking is finished. I'm able to do the former but not the latter. How do I stop the music after I've finished invoking the getoutput method?
import java.io.InputStream;
import javax.sound.sampled.AudioSystem;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class Student {
public void music() {
try {
// open the sound file as a Java input stream
String gongFile = "C:\\Users\\wei liang\\Documents\\Programming fundamentals\\T7-Arrays\\Assignment\\TT.wav";
InputStream in = new FileInputStream(gongFile);
// create an audiostream from the inputstream
AudioStream audioStream = new AudioStream(in);
// play the audio clip with the audioplayer class
AudioPlayer.player.start(audioStream);
} catch (Exception ex) {
System.out.println("Error! Can't find file.");
ex.printStackTrace();
}
}
}
This is my main method which calls the music method and another method not shown in the Student class.
public class StudentUser {
//Main method
public static void main(String args[]) {
//creating a new Student object
Student stud = new Student();
//Calling the music method
stud.music();
//Calling the getoutput method
stud.getoutput();
}
}
I would suggest using Thread, the Thread will be kept live until the music file is played and it will be ended automatically.
Since you did not provided getoutput method, you just call music method and it will play the music and ends.
Your Student class would be like:
import javax.sound.sampled.*;
import java.io.File;
class Student {
public synchronized void music(final String fileName, final SoundOptions mode) {
Thread music = new Thread(new Runnable() {
#Override
public void run() {
try {
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
new File(fileName));
final Clip audioLineClip = (Clip) AudioSystem.getLine(
new Line.Info(Clip.class));
audioLineClip.open(inputStream);
audioLineClip.setFramePosition(0);
audioLineClip.addLineListener(new LineListener() {
#Override
public void update(LineEvent event) {
LineEvent.Type type = event.getType();
if (type == LineEvent.Type.OPEN) {
} else if (type == LineEvent.Type.CLOSE) {
System.exit(0);
} else if (type == LineEvent.Type.START) {
} else if (type == LineEvent.Type.STOP) {
audioLineClip.close();
}
}
});
switch (mode) {
case Stop:
audioLineClip.stop();
break;
case Play:
audioLineClip.start();
break;
case Loop:
audioLineClip.loop(Clip.LOOP_CONTINUOUSLY);
break;
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
});
if (mode != SoundOptions.Stop) {
music.start();
synchronized (music) {
while (true) {
try {
music.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} else {
music.interrupt();
}
}
}
enum SoundOptions {
Play, Loop, Stop
}
and StudentUser class:
public class StudentUser {
private static String gongFile = "C:\\Users\\wei liang\\Documents\\Programming fundamentals\\T7-Arrays\\Assignment\\TT.wav";
//Main method
public static void main(String args[]) {
//Creating a new Student object
Student stud = new Student();
//Calling the music method and it is stops when music ends
stud.music(gongFile, SoundOptions.Play);
}
}
I want to calculate the max, min and average time for which the beep was high from mic input.
Following is the code to capture an playbak it from mic. But I want to sense the beep sound coming and calculate time of each beep.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class AudioCapture01 extends JFrame{
boolean stopCapture = false;
ByteArrayOutputStream
byteArrayOutputStream;
AudioFormat audioFormat;
TargetDataLine targetDataLine;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
public static void main(String args[]){
new AudioCapture01();
}//end main
public AudioCapture01(){ //constructor
final JButton captureBtn = new JButton("Capture");
final JButton stopBtn = new JButton("Stop");
final JButton playBtn = new JButton("Playback");
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(false);
setResizable(false);
setLocationRelativeTo(null);
//Register anonymous listeners
captureBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
//Capture input data from the microphone until the Stop button is clicked.
captureAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(captureBtn);
stopBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
//Terminate the capturing of input data from the microphone.
stopCapture = true;
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(stopBtn);
playBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//Play back all of the data that was saved during capture.
playAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(playBtn);
getContentPane().setLayout(new FlowLayout());
setTitle("Capture/Playback Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300,70);
setVisible(true);
}//end constructor
//This method captures audio input from a microphone and saves it in a ByteArrayOutputStream object.
private void captureAudio(){
try{
//Get everything set up for capture
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo =new DataLine.Info(TargetDataLine.class,audioFormat);
targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
targetDataLine.open(audioFormat);
targetDataLine.start();
//Create a thread to capture the microphone data and start it
// running. It will run until the Stop button is clicked.
Thread captureThread =new Thread(new CaptureThread());
captureThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end captureAudio method
//This method plays back the audio
// data that has been saved in the
// ByteArrayOutputStream
private void playAudio() {
try{
//Get everything set up for
// playback.
//Get the previously-saved data
// into a byte array object.
byte audioData[] =byteArrayOutputStream.toByteArray();
//Get an input stream on the
// byte array containing the data
InputStream byteArrayInputStream= new ByteArrayInputStream(audioData);
AudioFormat audioFormat =getAudioFormat();
audioInputStream =new AudioInputStream(byteArrayInputStream,audioFormat,audioData.length/audioFormat.getFrameSize());
DataLine.Info dataLineInfo =new DataLine.Info(SourceDataLine.class,audioFormat);
sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
//Create a thread to play back
// the data and start it
// running. It will run until
// all the data has been played
// back.
Thread playThread =new Thread(new PlayThread());
playThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end playAudio
//This method creates and returns an
// AudioFormat object for a given set
// of format parameters. If these
// parameters don't work well for
// you, try some of the other
// allowable parameter values, which
// are shown in comments following
// the declarations.
private AudioFormat getAudioFormat(){
float sampleRate = 8000.0F; //8000,11025,16000,22050,44100
int sampleSizeInBits = 16; //8,16
int channels = 1; //1,2
boolean signed = true; //true,false
boolean bigEndian = false; //true,false
return new AudioFormat(sampleRate,sampleSizeInBits,channels,signed,bigEndian);
}//end getAudioFormat
//===================================//
Inner class to capture data from microphone
class CaptureThread extends Thread {
//An arbitrary-size temporary holding buffer
byte tempBuffer[] = new byte[10000];
public void run(){
byteArrayOutputStream =new ByteArrayOutputStream();
stopCapture = false;
try{//Loop until stopCapture is set
// by another thread that
// services the Stop button.
while(!stopCapture){
//Read data from the internal
// buffer of the data line.
int cnt = targetDataLine.read(tempBuffer,0,tempBuffer.length);
if(cnt > 0){
//Save data in output stream object.
byteArrayOutputStream.write(tempBuffer, 0, cnt);
}//end if
}//end while
byteArrayOutputStream.close();
}catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end run
}//end inner class CaptureThread
//===================================//
//Inner class to play back the data that was saved.
class PlayThread extends Thread{
byte tempBuffer[] = new byte[10000];
public void run(){
try{
int cnt;
//Keep looping until the input read method returns -1 for empty stream.
while((cnt = audioInputStream.
read(tempBuffer, 0,
tempBuffer.length)) != -1){
if(cnt > 0){
//Write data to the internal buffer of the data line
// where it will be delivered to the speaker.
sourceDataLine.write(tempBuffer, 0, cnt);
}//end if
}//end while
//Block and wait for internal buffer of the data line to empty.
sourceDataLine.drain();
sourceDataLine.close();
}catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end run
}//end inner class PlayThread
}//end outer class AudioCapture01.java
I am able to capture and playback the audio but I can't sense the audio. Any help will be appreciated.
can anybody tell me why the following code doesn't work properly?
I want to play and stop an audio file.
I can do the playback but whenever I click the stop button nothing happens.
Here's the code :
Thank you.
..................
import java.io.*;
import javax.sound.sampled.*;
import javax.swing.*;
import java.awt.event.*;
public class SoundClipTest extends JFrame {
final JButton button1 = new JButton("Play");
final JButton button2 = new JButton("Stop");
int stopPlayback = 0;
// Constructor
public SoundClipTest() {
button1.setEnabled(true);
button2.setEnabled(false);
// button play
button1.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
button1.setEnabled(false);
button2.setEnabled(true);
play();
}// end actionPerformed
}// end ActionListener
);// end addActionListener()
// button stop
button2.addActionListener(
new ActionListener() {
public void actionPerformed(
ActionEvent e) {
//Terminate playback before EOF
stopPlayback = 1;
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
JToolBar bar = new JToolBar();
bar.add(button1);
bar.add(button2);
bar.setOrientation(JToolBar.VERTICAL);
add("North", bar);
add("West", bar);
setVisible(true);
}
void play() {
try {
final File inputAudio = new File("first.wav");
// First, we get the format of the input file
final AudioFileFormat.Type fileType =
AudioSystem.getAudioFileFormat(inputAudio).getType();
// Then, we get a clip for playing the audio.
final Clip c = AudioSystem.getClip();
// We get a stream for playing the input file.
AudioInputStream ais = AudioSystem.getAudioInputStream(inputAudio);
// We use the clip to open (but not start) the input stream
c.open(ais);
// We get the format of the audio codec
// (not the file format we got above)
final AudioFormat audioFormat = ais.getFormat();
c.start();
if (stopPlayback == 1) {
c.stop();
}
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}// end play
public static void main(String[] args) {
//new SoundClipTest().play();
new SoundClipTest();
}
}
your if (stopPlayback == 1 ) will only be run once -- you'll have to enclose it in a while(true) loop to make sure it keeps being evaluated, make sure you add a pause as well otherwise you will burn a lot of unnecessary cycles.
Update: I was assuming you ran a second thread to watch on the stopPlayback value - I now see this is not the case. Why don't you just call the c.stop() from your ActionListener?
Are there any examples of a server and a client that use sockets, but that have send and get methods? I'm doing this networked battleship program, almost finished, but can't get the server and clients to work. I have made a chat program that only sends strings, but this time I need to send objects. I'm already frustrated, so is there any source code that already has this.
Here's the code for the client... how would you modify it to allow to send objects? Also I need to be listening for incoming objects and process them right away.
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SimpleChat extends JFrame {
private Socket communicationSocket = null;
private PrintWriter outStream = null;
private BufferedReader inStream = null;
private Boolean communicationContinue = true;
private String disconnectString = "disconnect764*#$1";
private JMenuItem disconnectItem;
private JTextField displayLabel;
private final Color colorValues[] = { Color.black, Color.blue, Color.red, Color.green };
// set up GUI
public SimpleChat() {
super("Simple Chat");
// set up File menu and its menu items
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('F');
// set up Activate Server menu item
JMenuItem serverItem = new JMenuItem("Activate Server");
serverItem.setMnemonic('S');
fileMenu.add(serverItem);
serverItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpServer();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
JMenuItem clientItem = new JMenuItem("Activate Client");
clientItem.setMnemonic('C');
fileMenu.add(clientItem);
clientItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpClient();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
disconnectItem = new JMenuItem("Disconnect Client/Server");
disconnectItem.setMnemonic('D');
disconnectItem.setEnabled(false);
fileMenu.add(disconnectItem);
disconnectItem.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
}
} // end anonymous inner class
); // end call to addActionListener
// set up About... menu item
JMenuItem aboutItem = new JMenuItem("About...");
aboutItem.setMnemonic('A');
fileMenu.add(aboutItem);
aboutItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(SimpleChat.this, "This is an example\nof using menus", "About",
JOptionPane.PLAIN_MESSAGE);
}
} // end anonymous inner class
); // end call to addActionListener
// set up Exit menu item
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
fileMenu.add(exitItem);
exitItem.addActionListener(new ActionListener() { // anonymous inner class
// terminate application when user clicks exitItem
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
System.exit(0);
}
} // end anonymous inner class
); // end call to addActionListener
// create menu bar and attach it to MenuTest window
JMenuBar bar = new JMenuBar();
setJMenuBar(bar);
bar.add(fileMenu);
// set up label to display text
displayLabel = new JTextField("Sample Text", SwingConstants.CENTER);
displayLabel.setForeground(colorValues[0]);
displayLabel.setFont(new Font("Serif", Font.PLAIN, 72));
displayLabel.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
sendData();
}
} // end anonymous inner class
); // end call to addActionListener
getContentPane().setBackground(Color.CYAN);
getContentPane().add(displayLabel, BorderLayout.CENTER);
setSize(500, 200);
setVisible(true);
} // end constructor
public static void main(String args[]) {
final SimpleChat application = new SimpleChat();
application.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
application.disconnectClientServer(true);
System.exit(0);
}
});
// application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void setCommunicationSocket(Socket sock) {
communicationSocket = sock;
communicationContinue = true;
disconnectItem.setEnabled(true);
}
public void setOutStream(PrintWriter out) {
outStream = out;
}
public void setInStream(BufferedReader in) {
inStream = in;
}
public void setUpServer() {
ServerThread st = new ServerThread(this);
st.start();
}
public void setUpClient() {
ClientThread st = new ClientThread(this);
st.start();
}
public void disconnectClientServer(Boolean sendMessage) {
if (communicationSocket == null)
return;
try {
// shut down socket read loop
communicationContinue = false;
disconnectItem.setEnabled(false);
// send notification to other end of socket
if (sendMessage == true)
outStream.println(disconnectString);
// sleep to let read loop shut down
Thread t = Thread.currentThread();
try {
t.sleep(500);
} catch (InterruptedException ie) {
return;
}
outStream.close();
inStream.close();
communicationSocket.close();
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Disconnection Failed", "SimpleChat", JOptionPane.PLAIN_MESSAGE);
return;
} finally {
communicationSocket = null;
}
}
public void sendData() {
if (communicationSocket != null) {
String data = displayLabel.getText();
outStream.println(data);
}
}
public void getData() {
String inputLine;
try {
while (communicationContinue == true) {
communicationSocket.setSoTimeout(100);
// System.out.println ("Waiting for Connection");
try {
while (((inputLine = inStream.readLine()) != null)) {
System.out.println("From socket: " + inputLine);
if (inputLine.equals(disconnectString)) {
disconnectClientServer(false);
return;
}
displayLabel.setText(inputLine);
}
} catch (SocketTimeoutException ste) {
// System.out.println ("Timeout Occurred");
}
} // end of while loop
System.out.println("communication is false");
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Input Stream read failed", "SimpleChat",
JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ServerThread extends Thread {
private SimpleChat sc;
private JTextField display;
public ServerThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
ServerSocket connectionSocket = null;
try {
connectionSocket = new ServerSocket(10007);
} catch (IOException e) {
System.err.println("Could not listen on port: 10007.");
JOptionPane.showMessageDialog(sc, "Could not listen on port: 10007", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Server Socket is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
Socket communicationSocket = null;
try {
communicationSocket = connectionSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Accept failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
try {
PrintWriter out = new PrintWriter(communicationSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(communicationSocket.getInputStream()));
sc.setCommunicationSocket(communicationSocket);
sc.setOutStream(out);
sc.setInStream(in);
connectionSocket.close();
sc.getData();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Creation of Input//Output Streams failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ClientThread extends Thread {
private SimpleChat sc;
public ClientThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
String ipAddress = "127.0.0.1";
try {
echoSocket = new Socket(ipAddress, 10007);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Don't know about host: " + ipAddress, "Client", JOptionPane.PLAIN_MESSAGE);
return;
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Couldn't get I/O for the connection to: " + ipAddress, "Client",
JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Client", JOptionPane.PLAIN_MESSAGE);
sc.setCommunicationSocket(echoSocket);
sc.setOutStream(out);
sc.setInStream(in);
sc.getData();
}
}
I suggest you read up on java serialization. There is an example here. Basically, there is built in serialization support. Your class needs to implement Serializable. Then you use ObjectOutputStream and ObjectInputStream to write object.
You would be well advised to use libraries that shield you from the error prone low level socket programming.
For C++ look to Boost (http://www.boost.com) or ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)
For Java I only found a document that talks about the acceptor pattern http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF
But I am sure there's an implementation out somewhere
Your on the right track. A chat program is a good place to start learning about sockets.
What you want is to use the ObjectOutputStream and ObjectInputStream classes. You simply have to wrap your input stream / output stream with these filters. ObjectOutputStream has a method writeObject(), and the ObjectInputStream has a corresponding readObject() method.
Most serialization examples show reading and writing objects to a file, but the same can be done using a socket stream. See http://www.acm.org/crossroads/xrds4-2/serial.html
I didn't bother to read through your piles and piles of code, but in general you can't directly send objects over the network. Network communication is just bits and bytes. If you want to send objects, you'll need to serialize them on the sending side, and de-serialize them on the receiving side. There are tons of methods of serializing, eg JSON, XML, or even Java's built-in serialization support (only recommended if both the client and server will always be Java).
You may find this code to be a decent starting point for making your own class. These are two classes I made to somewhat abstract the work needed for TCP and UDP socket protocols:
http://code.google.com/p/hivewars/source/browse/trunk/SocketData.java
http://code.google.com/p/hivewars/source/browse/trunk/UDPSocket.java
Quick dislaimer: These are kind of versions of a feature full class, I just added functionality as I needed it. However, it could help you start.