I am trying to send continuous screenshots to another PC on same network.
I googled it also but i didn't find things relevant to me.
Below is my code of sender and receiver. Problem is only first image is being received and then struck.
If i turn on JFrame then not a single image is updating in JPanel. Please help me :-(
imagesender.java
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
class imagesender
{
imagesender()throws Exception
{
Socket soc=new Socket("127.0.0.1",5555);
OutputStream os=soc.getOutputStream();
while(true)
{
try
{
Dimension dim=Toolkit.getDefaultToolkit().getScreenSize();
Rectangle rec=new Rectangle(dim);
Robot bot=new Robot();
BufferedImage image=bot.createScreenCapture(rec);
ImageIO.write(image,"jpeg",os);
System.out.println("Image Sent");
}
catch(Exception e)
{
System.out.println(e);
}
}
}
public static void main(String aerg[])throws Exception
{
new imagesender();
}
}
imagereciever.java
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import javax.imageio.*;
import java.io.*;
import javax.swing.*;
class imagereciever extends JPanel
{
static BufferedImage image;
imagereciever()throws Exception
{
ServerSocket ss=new ServerSocket(5555);
Socket soc=ss.accept();
JFrame frame=new JFrame();
frame.setSize(500,500);
frame.setContentPane(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setVisible(true);
InputStream is=soc.getInputStream();
while(true)
{
try
{
image=ImageIO.read(is);
//this.repaint();
ImageIO.write(image,"jpeg",new File("C:\\Users\\Arpit Jindal\\Desktop\\screenshot.jpeg"));
System.out.println("Image Recieved");
}
catch(Exception e)
{e.printStackTrace()}
}
}
public static void main(String aerg[])throws Exception
{
new imagereciever();
}
public void paint(Graphics g)
{
super.paint(g);
g.drawImage(image,0,0,null);
}
}
imagereciever.java recieves one image and then gives this error infinite times and imagesender.java keeps on sending images:-
java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
at javax.imageio.ImageIO.getWriter(ImageIO.java:1592)
at javax.imageio.ImageIO.write(ImageIO.java:1520)
at imagereciever.<init>(imagereciever.java:26)
at imagereciever.main(imagereciever.java:37)
Your GUI completely ignores Swing threading rules, so I'm not surprised that it might be getting stuck. Suggestions:
Use a SwingWorker to do long-running background tasks such as reading in images. In your case, perhaps a SwingWorker<Void, BufferedImage> is what you want so that you can pass the BufferedImage to the GUI via the publish/process method pair. The Concurrency in Swing tutorial will tell you the details on how to use this tool.
Don't draw with the paint method.
Instead draw in the paintComponent method of a JPanel that is displayed in JFrame. Be sure to call the super's paintComponent method within your override.
Stop to consider -- do you really need images transmitted in this way as you're passing in a lot of information, perhaps more than is needed? Better would be to pass a data model over the socket and then recreate a view with the data, if possible.
Never blatantly ignore exceptions as your code is doing. At least catch the exception's stacktrace.
The example #MadProgrammer gave to me solved my problem. This is my new Code:-
imagesender.java
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
class imagesender
{
imagesender()throws Exception
{
Socket soc=new Socket("127.0.0.1",5555);
OutputStream os=soc.getOutputStream();
while(true)
{
try
{
BufferedImage image=new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ImageIO.write(image,"png",baos);
baos.close();
ObjectOutputStream oos=new ObjectOutputStream(os);
oos.writeObject(baos.size()+"");
os.write(baos.toByteArray());
//System.out.println("Image Sent");
}
catch(Exception e)
{
System.exit(1);
}
}
}
public static void main(String aerg[])throws Exception
{
new imagesender();
}
}
imagereciever.java
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import javax.imageio.*;
import java.io.*;
import javax.swing.*;
class imagereciever extends JPanel
{
static BufferedImage image;
static Socket soc;
static InputStream is;
imagereciever()throws Exception
{
ServerSocket ss=new ServerSocket(5555);
soc=ss.accept();
is=soc.getInputStream();
JFrame frame=new JFrame();
frame.setSize(500,500);
frame.setContentPane(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
while(true)
{
try
{
ObjectInputStream ois=new ObjectInputStream(is);
int size=Integer.parseInt(ois.readObject().toString());
ByteArrayOutputStream baos=new ByteArrayOutputStream(size);
int sizeread=0,bytesin=0;
byte[] buffer=new byte[1024];
while(sizeread<size)
{
bytesin=is.read(buffer);
sizeread+=bytesin;
baos.write(buffer,0,bytesin);
}
baos.close();
ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
image=ImageIO.read(bais);
this.repaint();
}
catch(Exception e)
{
System.exit(1);
}
}
}
public static void main(String aerg[])throws Exception
{
new imagereciever();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image,0,0,null);
}
}
Related
I am not sure if this is a dumb question but I need help with this program I was creating. I wanted to make a login screen to this instant messenger app, which I already have created but I made it in javaFX. The problem is that since this instant messenger app is old, I created it with swing. Since there are no scenes in swing and there are in javafx, then when I hit login I would normally change the scene and that's it. That is why I am changing this program to javafx from swing but I am getting a couple of errors, if anyone is kind enough to tell me what I did wrong I would be grateful. Thanks and sorry for being so redundant, remember i'm just a beginner in 9th grade.
The exact error is in the line 56
The method ActionListener(new ActionListener(){}) is undefined for the type TextField
package messengerClient;
import java.io.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.*;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.*;
import javafx.stage.*;
import javafx.stage.Stage;
import javax.swing.JFrame;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.awt.*;
import java.awt.event.ActionEvent;
public class ClientFX extends Application {
private TextField userText;
private TextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private String serverIP;
private Socket connection;
Stage window;
Scene scene1,scene2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Client - Instant Messenger!");
ClientFX juan = new ClientFX("127.0.0.1");
juan.startRunning();
}
//CONSTRUCTOR
public ClientFX(String host){
serverIP = host;
ScrollPane sp = new ScrollPane();
sp.setContent(chatWindow);
userText = new TextField();
userText.setEditable(false);
userText.ActionListener(
new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
BorderPane layout1 = new BorderPane();
layout1.setTop(userText);
layout1.setCenter(chatWindow);
chatWindow = new TextArea();
scene2 = new Scene(layout1,500,300);
window.setScene(scene2);
window.show();
}
//CONNECT TO SERVER
public void startRunning(){
try{
connectToServer();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\n Client terminated connection");
}catch(IOException ioException){
ioException.printStackTrace();
}finally{
closeCrap();
}
}
//CONNECT TO SERVER
private void connectToServer() throws IOException{
showMessage("Attempting connection... \n");
connection = new Socket(InetAddress.getByName(serverIP), 6789);
showMessage("You have succesfully connected to: " + connection.getInetAddress().getHostName());
}
//SET UP STREAMS TO SEND AND RECIVE MESSAGES
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nYour streams are now ready to go! \n");
}
//WHILE CHATTING WITH THE SERVER
private void whileChatting() throws IOException{
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classnotfoundException){
showMessage("\nI do not know that object type");
}
}while(!message.equals("Server - END"));
}
//CLOSE THE STREAMS AND THE SOCKETS
private void closeCrap(){
showMessage("\nClosing streams and the sockets down...");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//SEND MESSAGES TO THE SERVER
private void sendMessage(String message){
try{
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
chatWindow.appendText("\nThat data type cannot be sent, sorry!");
}
}
//UPDATE CHAT WINDOW
private void showMessage(final String m){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.appendText(m);
}
}
);
}
//GIVES USER PERMISION TO TYPE INTO THE TEXT BOX
private void ableToType(final boolean tof){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
The problem is you are mixing swing and javafx. You are importing both:
import java.awt.event.*;
import javax.swing.*;
import javafx.application.Application;
...
import javafx.scene.Scene;
import javafx.scene.control.Button;
For example in the ClientFX constructor you are trying to add a javax.swing.JTextField (a swing component) to a javafx.scene.BorderPane (a javafx component). The JTextField does not extend javafx.scene.Node, therefore it cannot be given to BorderPane.setTop(Node).
Basically for any swing component (often start with J, JTextField, JTextArea etc.) find the javafx equivalent (for example javafx.scene.control.TextField, javafx.scene.control.TextArea) and learn how to use them (they will have a different api).
In the end you should not have an import statement for java.awt or javax.swing.
Update
As already said you need to learn how to use the new fx apis. Not only the package names, classes and methods change, but also maybe programming concepts.
To port your JTextField behaviour you use a TextField and call the setOnAction method with an EventHandler implementation (very similar to the swing concept):
userText.setOnAction(new EventHandler<javafx.event.ActionEvent>()
{
#Override
public void handle(javafx.event.ActionEvent event)
{
//
}
});
I am building a simple program with one button. I want to play the "zvuk.wav" file after I click on the button. It's not working though and I cant solve why. When I click the button, nothing happens. The zvuk.wav file is in the src file with the classes.
Here is my first class which imports java.applet:
package Music;
import java.net.MalformedURLException;
import java.net.URL;
import java.applet.*;
public class Music {
private URL soubor;
public Music(String cesta){
try {
soubor = new URL("file:"+cesta);
} catch (MalformedURLException vyjimka) {
System.err.println(vyjimka);
}
Applet.newAudioClip(soubor).play();
}
}
MainFram which extends JFrame and has one Button:
package Music;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MainFrame extends JFrame{
public static final int WIDTH = 480;
public static final int HEIGHT = 600;
private String file;
public MainFrame(){
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setTitle("Přehrávač");
setResizable(false);
JPanel jPanel = new JPanel();
JButton bPlay = new JButton("PLAY");
jPanel.setLayout(null);
add(jPanel);
jPanel.add(bPlay);
bPlay.setBounds(200, 250, 100, 50);
bPlay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Music music = new Music("zvuk.wav");
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MainFrame();
}
});
}
}
Please note that Applet.newAudioClip(url).play() does not throw an error if it fails for whatever reason (for example nothing will happen if the project cannot find the wav file).
Try this stand alone test app. Does it work?
import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;
public class MainClass {
public static void main(String[] args) {
try {
URL url = new URL("file:zvuk.wav" );
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
System.in.read();
ac.stop();
} catch (Exception e) {
System.out.println(e);
}
}
}
If this small sample works, then it should be a small matter to modify it for your purposes.
However if it doesn't work then we almost certainly know that you project is unable to find the wav file.
Try add this to the code above:
//existing line
URL url = new URL("file:zvuk.wav" );
//new lines to debug wav file location
File myMusicFile = new File(url.getPath());
if(myMusicFile.exists() && !myMusicFile.isDirectory()) {
System.out.println("File exists and is not a directory");
}
If the file does not exist then that's your problem, and you need to point your URL to the correct location.
However if the file does exist and it still doesn't work then we have another possible issue outside of code.
It is possible that .play() is completing too quickly, see below for an example of how to keep it alive.
It is possible that your wav file is not a type that can be played, or it requires an unsupported codec. This is a far bigger topic and needs a new question, and a little bit of research on your part.
Here is the example to keep it alive from the sample code:
//load and start audio
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
//keep thread alive until a key is pressed
System.in.read();
ac.stop();
Sources:
http://www.java2s.com/Code/JavaAPI/java.applet/AppletnewAudioClipURLaudioFileURL.htm
http://docs.oracle.com/javase/7/docs/api/java/applet/AudioClip.html#play%28%29
I do this using NetBeans. This is the code.
Music.java file
package sound.play;
import java.applet.Applet;
import java.net.MalformedURLException;
import java.net.URL;
public class Music {
private URL soubor;
public Music(String cesta) {
try {
soubor = new URL("file:" + cesta);
} catch (MalformedURLException vyjimka) {
System.err.println(vyjimka);
}
Applet.newAudioClip(soubor).play();
}
}
MainFram which extends JFrame and has one Button
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JPanel;
public class MainFrame extends javax.swing.JFrame {
public static final int WIDTH = 200;
public static final int HEIGHT = 200;
private String file;
public MainFrame() {
initComponents();
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setTitle("Přehrávač");
setResizable(false);
JPanel jPanel = new JPanel();
jPanel.setLayout(null);
add(jPanel);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Music music = new Music("zvuk.wav");
String filename = "zvuk.wav";
URL url = this.getClass().getResource(filename);
File myMusicFile = new File(url.getPath());
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame().setVisible(true);
}
});
}
I've written a program that has to open an image I've placed on the desktop. The problem is that the program runs but nothing happens in the console nor does it open the image. Do I've to implement a GUI to fix the problem or...?
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Image {
public JavaImage() {
try {
BufferedImage image = ImageIO.read(new File("C:/Users/Username/Desktop/index.jpg"));
}
catch (IOException e) {
System.out.println("There isn't a picture in the folder");
}
}
public static void main(String[] args) {
new Image();
}
}
I am porting part of my C++ OpenCV-based code to Java OpenCV. I am using the Java wrappers prepared by Willow Garage, i.e., the group behind c++ OpenCV. I am not using javacv (hosted at googlecode).
Part of this code accesses the video stream of the webcam and processes it. With C++ I am able to show the webcam video in 'real-time': if I wave my hand, the video on the screen shows me waving a hand. With Java if I wave my hand the video (taken from the webcam) is not able to keep my pace: the frame rate is incredibly slow.
What I do is:
I read the frame of the webcam video using OpenCV, it is a Mat object named frame;
I access the byte array of the frame and use it to build a BufferedImage;
The image is shown in a JPanel inside its paint method.
I am using java version 1.7 and OpenCV 2.4.8 on OS X 10.8.5.
Do you have any suggestion on how I might speed up the whole process?
Regards
Try this,,, it will give u better result
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
public class Robot extends JPanel implements Runnable {
static BufferedImage bufImagew = null;
public Robot() {
JFrame f=new JFrame();
f.setVisible(true);
f.add(this);
f.setSize(new Dimension(640,500));
}
#Override
public void run() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture camera = new VideoCapture(0);
// 1 for next camera
int i = 0;
try {
Mat frame = new Mat();
while (true) {
camera.read(frame);
Mat image_tmp = frame;
MatOfByte matOfByte = new MatOfByte();
BufferedImage bufImage = null;
if(image_tmp!=null)
Highgui.imencode(".jpg", image_tmp, matOfByte);
byte[] byteArray = matOfByte.toArray();
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
} catch (Exception e) {
e.printStackTrace();
}
bufImagew=bufImage;
this.repaint();
if(i==5)
i=0;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
DetectFaceDemo d=new DetectFaceDemo();
try {
super.paintComponent(g);
g.drawImage(bufImagew,0,0,null);
}
catch(Exception e){}
}
public static void main(String[] args) {
Robot gs = new Robot();
Thread th = new Thread(gs);
th.start();
}
}
In the following code, I call JOptionPane.showMessageDialog, inside a try/catch block. But when the error is caught, my JOptionPane is visible but without any message !!! Does someone knows why and how I can correct the problem ?
Regards
MyBoardJPannel.java
package experimentations.gui;
import java.awt.Graphics;
import java.awt.Image;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class MyBoardPannel extends JPanel {
#Override
public void paint(Graphics grahics) {
if (imageToShow == null)
imageToShow = loadImage("sampleImage");
}
/**
* In fact, there are not any image in project => will go to catch clause.
* #param imageName
*/
private void loadImage(String imageName) {
InputStream imageStream = getClass().getResourceAsStream("/"+imageName+".png");
try {
imageToShow = ImageIO.read(imageStream);
}
catch (Exception e) {
String errorMessage = "Failed to load image "+imageName;
System.err.println(errorMessage);
JOptionPane.showMessageDialog(this, errorMessage,
"Image loading error", JOptionPane.ERROR_MESSAGE);
imageToShow = null;
System.exit(1);
}
}
private Image imageToShow;
}
JOptionPaneErrorShowing.java
package experimentations.gui;
import javax.swing.JFrame;
public class JOptionPaneErrorShowing extends JFrame {
public JOptionPaneErrorShowing(){
setTitle("JOptionPane experimentation");
setSize(300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(new MyBoardPannel());
}
/**
* #param args
*/
public static void main(String[] args) {
new JOptionPaneErrorShowing().setVisible(true);
}
}
It's likely a Swing concurrency issue. But more importantly, you should never load an image from within a paint or paintComponent method, ever. Read it in the constructor or elsewhere but paint/paintComponent need to be lean and blazingly fast.
To solve your issue, consider reading in the image in SwingWorker object. If you call a JOptionPane from within the SwingWorker's doInBackground method though, be sure to call it on the Swing event thread, the EDT, using SwingUtilities.invokeLater(Runnable).
Also, you will hardly ever want to draw in a JPanel's paint method unless you are taking care of painting borders and children. Instead paint in a paintComponent method, and don't forget to call the super.paintComponent(g) method in that paintComponent override. You'll want to read the Swing graphics tutorials as this is all spelled out there.
For example:
import java.awt.Graphics;
import java.awt.Image;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class MyBoardPannel extends JPanel {
protected static final String SAMPLE_IMAGE = "sampleImage";
Image imageToShow = null;
public MyBoardPannel() {
SwingWorker<Image, Void> mySW = new SwingWorker<Image, Void>() {
#Override
protected Image doInBackground() throws Exception {
return loadImage(SAMPLE_IMAGE);
}
#Override
protected void done() {
try {
imageToShow = get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
mySW.execute();
}
#Override
public void paintComponent(Graphics grahics) {
super.paintComponent(grahics);
if (imageToShow != null) {
grahics.drawImage(imageToShow, 0, 0, null);
}
}
private Image loadImage(String imageName) {
InputStream imageStream = getClass().getResourceAsStream(
"/" + imageName + ".png");
try {
return ImageIO.read(imageStream);
} catch (Exception e) {
final String errorMessage = "Failed to load image " + imageName;
System.err.println(errorMessage);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(MyBoardPannel.this, errorMessage,
"Image loading error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
});
}
return null;
}
}
I don't really know, but maybe your panel you use as parent of the JOptionPane (by passing this) is invisible or there is something else wrong. Try adding pack(); at the end of your JOptionPaneErrorShowing constructor.
What I know is that I had this problem when I was using an old Ubuntu and old Nvidia driver for my GPU, when the desktop effects were turned on (the Compiz Fusion of today. I don't know if it was already called Compiz, that long ago).
Aha! I found it, you are displaying the error inside the repaint method. Never do that! Load your image inside the constructor of the MyBoardPanel class and show error messages over there.