Following method call prevents JLabel from getting visible [duplicate] - java

I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}

Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}

You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();

Related

How to load time saved of a countdown when open a Jframe

I'm development a countdown for a program, the time is saved successfully, but when i restart the program the label load the time but not resume. What do i need to make for resume the timer?
This is for a program that needs a software licence activation
private Timer t;
private int M = 5, S = 60;
File Save = new File("C:\\Users\\User\\Downloads\\Countdown.txt");
private ActionListener accion = new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
S--;
if( S == -1){
M = M - 1;
S = 60;
}if( M == -1){
M = 5;
S = S - 0;
}if( M == 1 && S == 1){
Lbl_Warning.setText("Your'e Software Licence Soon Expire");
}if( M == 0 && S == 1){
Lbl_Warning.setText("Your'e Software Licence Expired");
M = 0; S = 0;
t.stop();
}
Update();
}
};
public Crono() {
initComponents();
this.setLocationRelativeTo(null);
t = new Timer(1000, acciones);
t.start();
}
public void Save(){
try{
if(!Save.exists()){
Save.createNewFile();
}{
BufferedWriter BW = new BufferedWriter(new FileWriter(Save.getAbsolutePath()));
BW.write(Lbl_Cronometro.getText());
BW.close();
}
} catch (IOException ex) {
ex.getMessage();
}
}
public void Charge(){
try {
if (Save.exists()){
Scanner sc = new Scanner(Save);
Lbl_Crono.setText(sc.nextLine());
sc.close();
}
} catch (FileNotFoundException ex) {
ex.getMessage();
}
}
private void Update() {
String time = (M+" : "+S);
Lbl_Crono.setText(time);
}
private void Lbl_ExitMouseClicked(java.awt.event.MouseEvent evt) {
if(t.isRunning())
{
t.stop();
Save();
System.exit(0);
}
Update();
}
I expect when I open again the JFrame, charge the saved time of the countdown and start.

JFrame freezes when button is pressed and operations from the other Class are ran [duplicate]

I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}
You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();

How to make phases in thread cycle?

I've got thread class which increments lable value from 0 to n. Thread code:
public class
SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
Thread must work until stop value isn't true. Also I've got 2 thread objects st1 and st2 with different arguments:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
So first thread should increment timeLabel1 from 0 to 10 and st2 - from 0 to 5. And now the question. How can I make my programm wait until threads has passed the stage in the cycle? I mean something like this:
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
//stage
}
}
And then:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
//wait until both stages aren't done
System.out.println("yep");
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Администратор
* Date: 22.11.13
* Time: 21:17
* To change this template use File | Settings | File Templates.
*/
public class StackOverflow implements ActionListener {
JButton button = new JButton("Button");
SimpleThread st1 = new SimpleThread("1st"), st2 = new SimpleThread("2nd");
JLabel timeLabel1 = new JLabel("0"), timeLabel2 = new JLabel("0");
StackOverflow() {
JFrame jfrm = new JFrame("Strategy fighting");
jfrm.setLayout(new FlowLayout());
jfrm.setSize(300, 150);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(this);
jfrm.add(button);
jfrm.add(timeLabel1);
jfrm.add(timeLabel2);
jfrm.setVisible(true);
}
public class SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
public void actionPerformed(ActionEvent e) {
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
System.out.println("yep");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new StackOverflow();
}
});
}
}
Your question already has the answer: the Phaser class. ;)
Something like this should do the trick:
static final Phaser phaser = new Phaser(NUM_THREADS + 1); // +1 for the main thread
In your threads:
run() {
// do stage 1
phaser.arriveAndAwaitAdvance(); // wait until everyone is done with stage 1
// do stage 2
}
And in your main:
startThreads(NUM_THREADS);
phaser.arriveAndAwaitAdvance(); // wait until stage 1 is done
// ... do something else

SwingWorker (not working), loop ends after 1st iteration

I expected to see close to 200,000 lines (196,608) of output from the loop in this code. It only prints one line. Can anyone spot the blunder?
import java.awt.*;
import java.util.*;
import javax.swing.*;
class SwingWorkerUnicodeTest {
private String[] fontNameArray;
private JLabel output = new JLabel("Processing..");
private JProgressBar progressBar = new JProgressBar();
class CodePointDetailWorker extends SwingWorker<Object, Object> {
private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
private ArrayList<Character.UnicodeScript> unicodeScripts;
private int[] glyphCount = new int[fontNameArray.length];
public CodePointDetailWorker() {
progressBar.setVisible(true);
Arrays.fill(glyphCount, 0);
}
#Override
protected Void doInBackground() throws Exception {
// Check for for the first 3 planes. The next 11 are unassigned
int pS = 3*65536;
for (int kk = 0; kk < pS; kk++) {
System.out.println("doInBackground " + kk + " " + pS);
doForEveryCodePoint(kk);
}
return null;
}
#Override
public void done() {
output.setText("Done!");
}
private final void doForEveryCodePoint(final int codePoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
if (block != null && !unicodeBlockNames.contains(block)) {
unicodeBlockNames.add(block);
}
Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
if (us == null || us.toString() == null) {
} else {
if (!unicodeScripts.contains(us)) {
unicodeScripts.add(us);
}
}
// fonts - test for points in all 6 defined blocks.
for (int ii = 0; ii < fontNameArray.length; ii++) {
Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
if (f.canDisplay(codePoint)) {
glyphCount[ii]++;
}
}
}
}
public SwingWorkerUnicodeTest() {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
fontNameArray = ge.getAvailableFontFamilyNames();
JPanel gui = new JPanel(new BorderLayout());
gui.add(progressBar, BorderLayout.CENTER);
gui.add(output, BorderLayout.PAGE_END);
CodePointDetailWorker cpdw = new CodePointDetailWorker();
cpdw.execute();
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new SwingWorkerUnicodeTest();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
Edit
Fixed code, based on the advice of the first 2 answers.
It now both implements the overridden method that reports errors, but initializes the arrays for ..much output and shows progress in the progress bar.
import java.awt.*;
import java.util.*;
import javax.swing.*;
class SwingWorkerUnicodeTest {
private JLabel output = new JLabel("Processing..");
// Check for for the first 3 planes. The next 11 are unassigned
int pS = 3 * 65536;
private JProgressBar progressBar = new JProgressBar(0, pS);
class CodePointDetailWorker extends SwingWorker<Object, Object> {
private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
private ArrayList<Character.UnicodeScript> unicodeScripts;
private int[] glyphCount;
private String[] fontNameArray;
public CodePointDetailWorker(String[] fontNameArray) {
this.fontNameArray = fontNameArray;
progressBar.setVisible(true);
glyphCount = new int[fontNameArray.length];
Arrays.fill(glyphCount, 0);
unicodeBlockNames = new ArrayList<Character.UnicodeBlock>();
unicodeScripts = new ArrayList<Character.UnicodeScript>();
}
#Override
protected Void doInBackground() throws Exception {
for (int kk = 0; kk < pS; kk++) {
if (kk % 500 == 0) {
progressBar.setValue(kk);
}
doForEveryCodePoint(kk);
}
progressBar.setValue(0);
return null;
}
#Override
public void done() {
try {
get();
output.setText("Done!");
} catch (Exception ex) {
ex.printStackTrace();
output.setText("Bad: " + ex.getMessage());
}
}
private final void doForEveryCodePoint(final int codePoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
if (block != null && !unicodeBlockNames.contains(block)) {
unicodeBlockNames.add(block);
}
Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
if (us == null || us.toString() == null) {
} else {
if (!unicodeScripts.contains(us)) {
unicodeScripts.add(us);
}
}
// fonts - test for points in all 6 defined blocks.
for (int ii = 0; ii < fontNameArray.length; ii++) {
Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
if (f.canDisplay(codePoint)) {
glyphCount[ii]++;
}
}
}
}
public SwingWorkerUnicodeTest(String[] names) {
JPanel gui = new JPanel(new BorderLayout());
gui.add(progressBar, BorderLayout.CENTER);
gui.add(output, BorderLayout.PAGE_END);
CodePointDetailWorker cpdw = new CodePointDetailWorker(names);
cpdw.execute();
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
new SwingWorkerUnicodeTest(fontNames);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
There is, likely, an Exception being thrown within the doInBackground method, which is, obviously, causing it to exit.
In your done method, even if it returns nothing, you should call get to ensure that nothing went wrong during the execution of the doInBackground method
#Override
public void done() {
try {
get();
output.setText("Done!");
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
output.setText("Bad: " + ex.getMessage());
}
}
You're not initializing your ArrayLists
public CodePointDetailWorker() {
unicodeBlockNames = new ArrayList<>();
unicodeScripts = new ArrayList<>();
...
}
so a NPE is silently being thrown in the SwingWorker once this statement is encountered
if (block != null && !unicodeBlockNames.contains(block)) {
^---null

Make threads usage efficient in Java

I have coded a simple application in Java that downloads particular images from a list of html links provided. Everything was working fine until I added the feature of having to download from a list of html links rather than just one. I had to implement the wait() and notify() methods which forced me to change the approach a little. Now, the downloads work fine, but the GUI does not update while the download is in progress.
I make the 1st thread wait from HTML.java and notify it at the end of DownloadImages.java. For this I had to invoke buttonPressed class as an object rather than a thread, which is why I think my GUI won't update.
Is there a way to simplify or make thread-usage more efficient in my code? Thanks in advance.
Here is skeleton of my code:
/*Test.java*/
package my;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Test extends javax.swing.JFrame {
public static buttonPressed bp;
public static boolean alldone;
/** Creates new form Test */
public Test() {
initComponents();
}
public static class buttonPressed implements Runnable {
Thread t1, t2;
buttonPressed() {
t1 = new Thread(this, "downloadAction");
t1.start();
}
public void suspendThread() {
System.out.println("suspended");
alldone = false;
}
public synchronized void resumeThread() {
System.out.println("resumed");
alldone = true;
notify();
}
public void run() {
String[] len = new String[]{/*list of urls*/};
for (int i = 0; i &lt len.length; i++) {
System.out.println("going times: " + i);
t2 = new Thread(new HTML(), "HTMLthread");
t2.start();
synchronized (this) {
while (!alldone) {
try {
wait();
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
}
private void downloadActionPerformed(java.awt.event.ActionEvent evt) {
bp = new buttonPressed();
try {
bp.t1.join();
} catch (InterruptedException e) {
System.out.println("Main Thread: interrupted");
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Test().setVisible(true);
}
});
}
private javax.swing.JButton download;
public static javax.swing.JProgressBar progress;
}
/*HTML.java*/
package my;
import java.util.ArrayList;
class HTML implements Runnable {
private Thread t3;
public HTML() {
Test.bp.suspendThread();
}
public void run() {
downloadHTML();
ArrayList xyz = parseHTML();
t3 = new Thread(new DownloadImages(xyz), "DownDecrypt");
t3.start();
}
private void downloadHTML() {
// Downloads the HTML file
}
private ArrayList parseHTML() {
// Parses the HTML file and gets links to images
return new ArrayList();
}
}
/*DownloadImages.java*/
package my;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
class DownloadImages implements Runnable {
static int current = 0, previous = 0;
static boolean speedFlag;
ArrayList<String> links = new ArrayList<String>();
private Thread t4;
public DownloadImages(ArrayList param1) {
this.links = param1;
speedFlag = true;
}
public void run() {
t4 = new Thread(new getSpeed(), "getSpeed");
t4.start();
download(links);
}
private void download(ArrayList<String> param1) {
String[] imgurl = new String[param1.size()];
URLConnection conn = null;
InputStream is = null;
ByteArrayOutputStream bais = null;
int prog;
for (int i = 0; i < param1.size(); i++) {
current = 0;
imgurl[i] = param1.get(i);
try {
conn = new URL(imgurl[i]).openConnection();
int fsize = conn.getContentLength();
is = new BufferedInputStream(conn.getInputStream());
bais = new ByteArrayOutputStream();
byte[] byteChunk = new byte[1024];
int n;
while ((n = is.read(byteChunk)) > 0) {
bais.write(byteChunk, 0, n);
current = current + 1024;
prog = (int) (current * 100.0 / fsize);
Test.progress.setValue(prog);
}
} catch (MalformedURLException ex) {
Logger.getLogger(DownloadImages.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Logger.getLogger(DownloadImages.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
byte[] imgBytes = bais.toByteArray();
try {
FileOutputStream fos = new FileOutputStream(i + ".jpg");
fos.write(imgBytes);
fos.flush();
fos.close();
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException : " + ex);
} catch (IOException e) {
e.printStackTrace();
}
}
speedFlag = false;
// Resume the thread to start downloading the next link
Test.bp.resumeThread();
}
private static class getSpeed implements Runnable {
int kbytesPerSecond;
private final int fireTime;
public getSpeed() {
fireTime = 1000;
}
public void run() {
while (speedFlag) {
try {
Thread.sleep(fireTime);
} catch (InterruptedException ex) {
Logger.getLogger(getSpeed.class.getName()).log(Level.SEVERE, null, ex);
}
kbytesPerSecond = (((current - previous) / 1024) / (fireTime / 1000));
System.out.println(kbytesPerSecond);
previous = current;
}
}
}
}
As far as the GUI is concerned you need to read about Swing concurrency. In short, use SwingWorker.
Mind that you use old AWT stuff (java.awt.EventQueue).
I suggest you have an ExecutorService like Executors.newCachedThreadPool and submit() the tasks to it. Collect the Future objects so you know when they are done. This will be more efficient and manageable than creating Threads all over the place.
You can have just one pool like
static final ExecutorService POOL = Executors.newCachedThreadPool();
to submit a task
POOL.submit(new Callable<Void>() {
public Void call() throws InterruptedException {
while (speedFlag) {
Thread.sleep(1000);
kbytesPerSecond = (current - previous) / 1024;
System.out.println(kbytesPerSecond);
previous = current;
}
}
});
Even better for repeating tasks is to use a scheduled executor service.
static final ScheduledExecutorService POOL = Executors.newScheduledThreadPool(4);
Future task = POOL.scheduleAtFixedRate(new Runnable() {
public void run() {
kbytesPerSecond = (current - previous) / 1024;
System.out.println(kbytesPerSecond);
previous = current;
}
}, 1, 1, TimeUnit.SECONDS);
// to end the task
task.cancel(false);

Categories