I have a some class for downloading a big files from a web sites and displaying a process with jProgressBar.
I am using a SwingWorker class and the method doInBackground. It works fine, but when size of downloaded file > 20mb, i am getting a java.lang.IllegalArgumentException: the value should be from 0 to 100. What am i doing wrong? Please, help me! My piece of code:
#Override
protected Void doInBackground() throws Exception {
URL url = new URL(site);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int filesize = connection.getContentLength();
int totalDataRead = 0;
try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(
connection.getInputStream())) {
java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
try (java.io.BufferedOutputStream bout = new BufferedOutputStream(
fos, 1024)) {
byte[] data = new byte[1024];
int i;
while ((i = in.read(data, 0, 1024)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
int percent = (totalDataRead * 100) / filesize;
setProgress(percent);
}
}
}
return null;
}
}
Having played around with your calculations, this...
int percent = (totalDataRead * 100) / filesize;
Just looks wrong to me (it might just be my pathetic math brain), but out of 40mb at around 20.48mb (or 51%), it reverts to a negative number (-51%)
How ever, if I use
int percent = Math.round(((float)count / (float)range) * 100f);
It works just fine.
Also, I'd consider making filesize and totalDataRead long instead of int, but that's just me.
And a runnable example which I used to test it with...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pb;
public TestPane() {
pb = new JProgressBar();
setLayout(new GridBagLayout());
add(pb);
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
int range = 40 * (1024 * 1024);
for (int count = 0; count < range; count += 1024) {
int percent = Math.round(((float)count / (float)range) * 100f);
setProgress(percent);
Thread.sleep(1);
}
return null;
}
};
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (null != evt.getPropertyName()) {
switch (evt.getPropertyName()) {
case "progress":
pb.setValue(worker.getProgress());
break;
}
}
}
});
worker.execute();
}
}
}
Related
I'm using SwingWorker and
It perfectly updates JProgressBar WHEN the process is not too heavy (for example "Trames" list containing 62 elements)
It doesn't update JProgressBar when the process is heavy (I tested with 100k elements, it'll finally works with 2M+ elems)
Below my ProgressWorker class
#Override
protected Object doInBackground() throws Exception {
// TODO Auto-generated method stub
// here process i skipped
for (Trame t : trames) {
float progress = (float)FileRW.tramescounter/FileRW.maxtrames;
progress = progress*100;
int p = (int) progress;
setProgress(p);
System.out.println(getProgress()+"+p"+" ---- progress"+p+" ---- double"+progress);
Thread.sleep(25);
FileRW.tramescounter++;
// here process i skipped
}
// here process i skipped
return null;
}
Besides, my controller class:
ProgressWorker pw = new ProgressWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
Vue.bar.setValue(progress);
Vue.bar.repaint();
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
Vue.lastButton.setEnabled(true);
if (Vue.check.isSelected()) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.open(new File(Constants.FICHIER_LOG2));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Vue.filesInDirectory = null;
Vue.fileLabel.setText(Constants.PAN1_LABEL);
break;
default:
break;
}
}
}
});
pw.execute();
There's a runnable example (based on your out-of-context code) which works, so my guess is, it's not the SwingWorker which is at fault, but some part of the code you're not sharing.
Consider providing a Minimal, Complete, and Verifiable example which demonstrates your problem, until you do, this is about all the help we can possible give you
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import static javax.swing.SwingWorker.StateValue.DONE;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pb = new JProgressBar(0, 100);
public TestPane() {
setLayout(new GridBagLayout());
add(pb);
BadWorker pw = new BadWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
pb.setValue(progress);
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
System.out.println("All done where");
break;
}
}
}
});
pw.execute();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class BadWorker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
int count = 0;
int max = 10000;
do {
count++;
float progress = (float) count / max;
progress = progress * 100;
int p = (int) progress;
setProgress(p);
System.out.println(getProgress() + "+p" + " ---- progress" + p + " ---- double" + progress);
Thread.sleep(5);
// here process i skipped
} while (getProgress() < 100);
// here process i skipped
return null;
}
}
}
Ok nevermind the problem wasn't the one I expected
Just inside the first part of code I skipped I wrote
Vue.bar.setMaximum(trames.size());
Further,
float progress = (float)FileRW.tramescounter/FileRW.maxtrames;
progress = progress*100;
int p = (int) progress;
setProgress(p);
And in controller class
Vue.bar.setValue(progress);
But progress value set in ProgressWorker is from 0 to 100
My max ProgressBar value was 100K but the 0 < progression value <100,
It was normal that it didn't progress
I am using a BufferedImage to display two images on my JPanel. However, I want the images move in random directions when a button is clicked and should only stop when another button is pressed.
How do I make my images move randomly on the panel?
This is part of my code:
private void getImages() {
try {
frogImage = ImageIO.read(new File ("C:\\OOP\\CyberPet\\src\\img\\frog.gif"));
flyImage = ImageIO.read(new File ("C:\\OOP\\CyberPet\\src\\img\\fly.gif"));
g = panel.getGraphics();
g.drawImage(frogImage, 500, 25, 40, 40, null); //set position and size of the image
g.drawImage(flyImage, 40, 40, 10, 10, null); //set position and size of the image
} catch (IOException e) {
}
}
public void actionPerformed(ActionEvent event) {
getImages();
if (event.getSource() == makeButton){
responseArea.setText(enterField.getText());
}
else if(event.getSource() == hungryButton){
}
else if(event.getSource() == resetButton){
}
}
public void draw()
{
}
}
You can always check this example for inspiration.
Basically, it uses a javax.swing.Timer to pace the animation. Whenever an animal reaches an edge of the frame, it will reverse its direction to go in reverse. The directions and speed are randomly computed, adjust these to your needs:
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimationFlyAndFrog {
private static final int NB_OF_IMAGES_PER_SECOND = 50;
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private Random random = new Random();
private double dxFrog;
private double dyFrog;
private double xFrog = WIDTH / 2;
private double yFrog = HEIGHT / 2;
private double dxFly;
private double dyFly;
private double xFly = WIDTH / 2;
private double yFly = HEIGHT / 2;
protected void initUI() throws MalformedURLException {
final JFrame frame = new JFrame(TestAnimationFlyAndFrog.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
final JLabel frog = new JLabel(new ImageIcon(new URL("http://www.iconshock.com/img_jpg/SUPERVISTA/animals/jpg/128/frog_icon.jpg")));
frog.setSize(frog.getPreferredSize());
final JLabel fly = new JLabel(new ImageIcon(new URL("http://www.iconshock.com/img_jpg/SUPERVISTA/animals/jpg/128/fly_icon.jpg")));
fly.setSize(fly.getPreferredSize());
frame.setMinimumSize(new Rectangle(frog.getPreferredSize()).union(new Rectangle(fly.getPreferredSize())).getSize());
frame.add(frog);
frame.add(fly);
frame.setSize(WIDTH, HEIGHT);
dxFrog = getNextSpeed() * (random.nextBoolean() ? 1 : -1);
dyFrog = getNextSpeed() * (random.nextBoolean() ? 1 : -1);
dxFly = getNextSpeed() * (random.nextBoolean() ? 1 : -1);
dyFly = getNextSpeed() * (random.nextBoolean() ? 1 : -1);
Timer t = new Timer(1000 / NB_OF_IMAGES_PER_SECOND, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xFrog += dxFrog;
yFrog += dyFrog;
if (xFrog + frog.getWidth() > frame.getContentPane().getWidth()) {
xFrog = frame.getContentPane().getWidth() - frog.getWidth();
dxFrog = -getNextSpeed();
} else if (xFrog < 0) {
xFrog = 0;
dxFrog = getNextSpeed();
}
if (yFrog + frog.getHeight() > frame.getContentPane().getHeight()) {
yFrog = frame.getContentPane().getHeight() - frog.getHeight();
dyFrog = -getNextSpeed();
} else if (yFrog < 0) {
yFrog = 0;
dyFrog = getNextSpeed();
}
frog.setLocation((int) xFrog, (int) yFrog);
xFly += dxFly;
yFly += dyFly;
if (xFly + fly.getWidth() > frame.getContentPane().getWidth()) {
xFly = frame.getContentPane().getWidth() - fly.getWidth();
dxFly = -getNextSpeed();
} else if (xFly < 0) {
xFly = 0;
dxFly = getNextSpeed();
}
if (yFly + fly.getHeight() > frame.getContentPane().getHeight()) {
yFly = frame.getContentPane().getHeight() - fly.getHeight();
dyFly = -getNextSpeed();
} else if (yFly < 0) {
yFly = 0;
dyFly = getNextSpeed();
}
fly.setLocation((int) xFly, (int) yFly);
}
});
frame.setVisible(true);
t.start();
}
private double getNextSpeed() {
return 2 * Math.PI * (0.5 + random.nextDouble());
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new TestAnimationFlyAndFrog().initUI();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
First, everyone needs to know i'm relatively new to Java coding. To be more precise i'm completely new to Object Oriented Programming.
To the question.
I am trying to create a download class that updates a progress bar it was given to show its progress. And possibly anything else I decide to give it in the future to update.
The issue currently is that, in my head, this shouldn't work. I can do anything i want on the "main" method and the GUI is still responsive and quick. In my experience in past programming, this is not possible unless i thread the GUI. Why is this?
Since it works, is this ok to do it this way?
Class Main
package atomicElectronics;
import java.io.IOException;
import atomicElectronics.physical.AtomFrame;
import atomicElectronics.utility.Download;
public class Initial {
static AtomFrame atomLauncher;
public static void main(String[] args) {
atomLauncher = new AtomFrame();
atomLauncher.start();
System.out.println(Integer.MAX_VALUE);
Download theDownload = new Download();
theDownload.fileProgressBar(atomLauncher.progressBar);
try {
theDownload.exicute("http://download.videolan.org/pub/videolan/vlc/last/win64/vlc-2.1.3-win64.exe", "C:\\Users\\TrinaryAtom\\AppData\\Roaming");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Add Download Methods
// theDownload.updateBarTotal(JProgressBar);
// theDownload.updateLabelSpeed(String);
// theDownload.updateLabelTotal(String);
// theDownload.addFile(File);
// theDownload.addFiles(Files);
}
}
Class AtomFrame
package atomicElectronics.physical;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import javax.swing.JProgressBar;
public class AtomFrame extends JFrame{
public JProgressBar progressBar;
private static final long serialVersionUID = 4010489530693307355L;
public static void main(String[] args){
AtomFrame testFrame = new AtomFrame();
testFrame.start();
}
public AtomFrame(){
initializeComponents();
}
public void initializeComponents(){
this.setSize(400, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Atom Launcher");
this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
progressBar = new JProgressBar();
this.add(progressBar);
//this.pack();
}
public void start() {
this.setVisible(true);
}
public void close() {
this.dispose();
}
}
Class Download
package atomicElectronics.utility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JProgressBar;
public class Download {
private static final int BUFFER_SIZE = 4096;
private JProgressBar fileProgressBar;
public Download() {
}
public void fileProgressBar(JProgressBar fileBar) {
fileProgressBar = fileBar;
}
public void exicute(String fileURL, String saveDir) throws IOException {
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
double contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 9,
disposition.length());
}
} else {
// extracts file name from URL
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
fileURL.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
String saveFilePath = saveDir + File.separator + fileName;
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
double totalRead = 0;
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalRead += bytesRead;
System.out.println((totalRead / contentLength) * 100);
fileProgressBar.setValue((int)((totalRead / contentLength) * 100));
}
outputStream.close();
inputStream.close();
System.out.println("File downloaded");
} else {
System.out.println("No file to download. Server replied HTTP code: " + responseCode);
}
httpConn.disconnect();
}
}
Suggestions:
Use a SwingWorker to do your background thread work.
Inside your SwingWorker, set its progress "bound" property via setProgress(int progress). The value should be between 1 and 100.
Don't have your SwingWorker/file downloader hold the JProgressBar or any Swing components.
Add a PropertyChangeListener to your SwingWorker and monitor changes in the progress property.
Never make your Swing fields (or most and and all fields) public. Limit access, and instead change object state via methods.
Read the tutorial Concurrency in Swing for the necessary details.
For example, the code below is a gross simplification and downloads no files, but should give you the idea:
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.*;
public class Initial {
static AtomFrame atomLauncher;
public static void main(String[] args) {
atomLauncher = new AtomFrame();
atomLauncher.start();
System.out.println(Integer.MAX_VALUE);
final Download theDownload = new Download();
theDownload.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if ("progress".equals(pcEvt.getPropertyName())) {
int progress = theDownload.getProgress();
atomLauncher.setProgress(progress);
}
}
});
theDownload.execute();
}
}
class AtomFrame extends JFrame {
// ********* should be private!
private JProgressBar progressBar;
private static final long serialVersionUID = 4010489530693307355L;
public static void main(String[] args) {
AtomFrame testFrame = new AtomFrame();
testFrame.start();
}
public void setProgress(int progress) {
progressBar.setValue(progress);
}
public AtomFrame() {
initializeComponents();
}
public void initializeComponents() {
this.setSize(400, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Atom Launcher");
this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
progressBar = new JProgressBar();
this.add(progressBar);
// this.pack();
}
public void start() {
this.setVisible(true);
}
public void close() {
this.dispose();
}
}
class Download extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 300;
private Random random = new Random();
#Override
protected Void doInBackground() throws Exception {
int myProgress = 0;
while (myProgress < 100) {
myProgress += random.nextInt(10);
setProgress(myProgress);
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
return null;
}
}
This question already has answers here:
JProgressBar wont update
(3 answers)
Closed 9 years ago.
I currently have a class that should show me a simple form while downloading a file. It is working, but the progress bar is not updating, and I can only see it once the download is finished. Can someone help me?
import java.awt.FlowLayout;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JProgressBar;
public class Downloader {
public Downloader(String site, File file) {
JFrame frm = new JFrame();
JProgressBar current = new JProgressBar(0, 100);
current.setSize(50, 100);
current.setValue(0);
current.setStringPainted(true);
frm.add(current);
frm.setVisible(true);
frm.setLayout(new FlowLayout());
frm.setSize(50, 100);
frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
try {
URL url = new URL(site);
HttpURLConnection connection
= (HttpURLConnection) url.openConnection();
int filesize = connection.getContentLength();
float totalDataRead = 0;
try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(connection.getInputStream())) {
java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
try (java.io.BufferedOutputStream bout = new BufferedOutputStream(fos, 1024)) {
byte[] data = new byte[1024];
int i;
while ((i = in.read(data, 0, 1024)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
float Percent = (totalDataRead * 100) / filesize;
current.setValue((int) Percent);
}
}
}
} catch (IOException e) {
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component) null, e.getMessage(), "Error",
javax.swing.JOptionPane.DEFAULT_OPTION);
}
}
}
Yours is a classic Swing concurrency issue. The solution is as always -- do the long running code in a background thread such as can be found with a SwingWorker.
e.g.,
import java.awt.FlowLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JProgressBar;
public class Downloader {
public Downloader(String site, File file) {
JFrame frm = new JFrame();
final JProgressBar current = new JProgressBar(0, 100);
current.setSize(50, 100);
current.setValue(0);
current.setStringPainted(true);
frm.add(current);
frm.setVisible(true);
frm.setLayout(new FlowLayout());
frm.setSize(50, 100);
frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
final Worker worker = new Worker(site, file);
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if ("progress".equals(pcEvt.getPropertyName())) {
current.setValue((Integer) pcEvt.getNewValue());
} else if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
worker.get();
} catch (InterruptedException | ExecutionException e) {
// handle any errors here
e.printStackTrace();
}
}
}
});
worker.execute();
}
}
class Worker extends SwingWorker<Void, Void> {
private String site;
private File file;
public Worker(String site, File file) {
this.site = site;
this.file = file;
}
#Override
protected Void doInBackground() throws Exception {
URL url = new URL(site);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int filesize = connection.getContentLength();
int totalDataRead = 0;
try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(
connection.getInputStream())) {
java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
try (java.io.BufferedOutputStream bout = new BufferedOutputStream(
fos, 1024)) {
byte[] data = new byte[1024];
int i;
while ((i = in.read(data, 0, 1024)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
int percent = (totalDataRead * 100) / filesize;
setProgress(percent);
}
}
}
return null;
}
}
I am having a bit of problem with changing and Icon in a JLabel dynamically. First of all, what i am trying to do is basically simulating a screen sharing operation. On the client side, I am taking screenshots every second, sending them to the server. On the server side, I am trying to open these pictures in a simple GUI.
I am able to send the pictures without problem and I am also able to get them without problem as well. However, the GUI code I have written cannot open the pictures. More specifically, If there is a picture, it is able to open it, but it does not open another picture that has come.
What I am doing in the server side is, as soon as a picture gets to the server, I am saving it with a predetermined name. And then I am able to open the picture with Windows' own picture photo viewer. In fact, as soon as a new picture comes, photo viewer updates itself and shows the new screenshot.
However, I am having trouble opening the screenshots in a JFrame. I have written a program to take the screenshots in jpg format, send them to the server and then open them in a GUI. however i am having problems with the opening in the GUI part. From what I have understood, it does not open the files that are coming by from the client.
Below are my codes, any help will be much appreciated.
Server side,
package ScreenCap;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import FileServer.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import test.TsgIcons;
/**
*
* #author busra
*/
public class ScreenCapServer extends Thread{
String filePath;
int portNumber;
FileServer screenCapServer;
ServerSocket getFileServer;
Socket getFile;
InputStream in;
FileOutputStream fileOutputStream;
TsgIcons screenShotIcons;
public ScreenCapServer(String path, int port) {
this.filePath = path;
this.portNumber = port;
this.screenShotIcons = new TsgIcons();
}
public static void waitTime(long millisecond){
long max = millisecond;
for(long i = 0; i < max; i++){
for(long j = 0; j < max; j++){
}
}
}
public void run() {
while(true) {
try {
for(int i = 0; i < 10; i++) {
getFileServer = new ServerSocket(portNumber);
getFile = getFileServer.accept();
in = getFile.getInputStream();
fileOutputStream = new FileOutputStream(filePath + "\\" + i + ".jpg");
byte [] buffer = new byte[64*1024];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
in.close();
fileOutputStream.close();
getFileServer.close();
screenShotIcons.update();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
GUI,
package test;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TsgIcons extends JFrame implements ActionListener {
protected Timer timer;
protected JLabel viewIcon;
private String[] SMILEY = {"orig_screen"};
private String BUTTON = "Button";
private int timeCount;
private int iconNumber;
private String image;
public TsgIcons() {
this(1, 100);
}
public TsgIcons(int initialTime, int delay) {
super("TSG Smileys");
this.timeCount = initialTime;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon = new JLabel();
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
this.timer = new Timer(delay, this);
this.init();
}
protected void init() {
JButton button = new JButton("Start / Stop");
button.setActionCommand(BUTTON);
button.addActionListener(this);
this.viewIcon.setHorizontalAlignment(JLabel.CENTER);
this.getContentPane().add(button, BorderLayout.SOUTH);
this.getContentPane().add(this.viewIcon, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(250, 250);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if ( BUTTON.equals(e.getActionCommand()) ) { // test if the button clicked
if ( this.timer.isRunning() ) {
this.timer.stop();
} else {
this.timer.start();
}
} else
{ this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
}
public void update() {
this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
public static void main(String argv []) {
new TsgIcons();
}
}