carget carget - 6 days ago 6
Java Question

Java GUI Threading

I have a GUI program that, in this example, downloads an exe using

wget
. I have a thread set up that downloads the file. There is a static variable holding the file's size. Then I have a while loop that checks the actual file size and updates a
JLabel
until the download is 100% complete. The GUI obviously isn't updating and everything is halted until the thread completes, which to me is odd since I thought the point of making this thread would be to bypass this problem. Please let me know what I've done wrong and what about the thread needs to be changed. I want to try and keep this as simple as it is currently.

FYI: I have the
System.out.println()
in there so you can see that it does properly update the current file size. Also, the entire thing won't work if the file being downloaded already exists (since the while loop is instantly true).

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class downloaderProgram implements ActionListener {
JFrame frame;
JPanel p1, p2, p3;
JButton start;
JLabel status;

downloaderProgram() {
frame = new JFrame("Downloader");
frame.setSize(500, 400);

//p1
p1 = new JPanel();

//p2
p2 = new JPanel();

status = new JLabel("");
p2.add(status);

//p3
GridLayout p3Grid = new GridLayout(0, 1);
p3 = new JPanel();
p3.setLayout(p3Grid);

start = new JButton("Start");
start.setMargin(new Insets(10,0,10,0));

p3.add(start);

//frame
frame.add(p1, BorderLayout.NORTH);
frame.add(p2, BorderLayout.CENTER);
frame.add(p3, BorderLayout.SOUTH);

start.addActionListener(this);

//output.setEditable(false);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(start)) {
long fileSize = 1110476;

downloadThread dt = new downloadThread();
dt.start();

long length = 0;
File download = new File("7z920.exe");
while (length != fileSize) {
length = download.length();
status.setText(Long.toString(length));
System.out.println(Long.toString(length));
}

start.setEnabled(false);
}
}

public static void main(String[] args) {
new downloaderProgram();
}
}
class downloadThread extends Thread {
public void run() {
try {
String cmd = "wget http://downloads.sourceforge.net/sevenzip/7z920.exe";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
} catch(IOException io) {
System.out.println(io);
}
}
}


Sorry if the spacing is a bit messed up--it didn't copy over from my IDE very well. Thanks!

Answer

When will the label update? You're looping in the Event Dispatch Thread (EDT) - that's when Swing does its painting. Your while loop, not the download thread, is preventing the GUI from updating.

The answer is simple: javax.swing.SwingWorker. Here is a comprehensive SwingWorker tutorial from Oracle.

Also consider using a JProgressBar instead of or along with a JLabel. There's a tutorial for that too: How to Use Progress Bars

Comments