我正在编写一个swing应用程序。这里的任务是从给定的URL下载文件,然后获取它们的计数。该程序无任何问题/错误。
问题是我的框架中有一个测试区,下载file 1
时我希望文本区域显示downloaded file 1
,文件2显示downloaded file 1
等等。 ..
目前在我的程序中,消息会一次显示。我的意思是,如果我有10个文件,它会显示。
downloaded file 1
downloaded file 2
.
.
.
.
.
downloaded file 10
但只有在下载了所有10个文件后才会显示。要查看是否存在任何其他问题,我已在sysout
代码下方添加了textarea
。令我惊讶的是,sysout
被打印10次,我的意思是每次处理文件时都会触发,但textarea
一次附加所有数据。
以下是我的代码。
GuiForPDFs
import java.awt.BorderLayout;
public class GuiForPDFs extends JFrame {
private JPanel contentPane;
private JTextField srcTextField;
private JTextArea textArea;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GuiForPDFs frame = new GuiForPDFs();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
FileDownloadTest downloadTest = new FileDownloadTest();
public GuiForPDFs() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 552, 358);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
srcTextField = new JTextField();
srcTextField.setBounds(10, 26, 399, 20);
contentPane.add(srcTextField);
srcTextField.setColumns(10);
JButton srcBtn = new JButton("Source Excel");
srcBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fChoose = new JFileChooser();
if (fChoose.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
srcTextField.setText(fChoose.getSelectedFile().getAbsolutePath());
} else {
System.out.println("No Selection");
}
}
});
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setBounds(10, 106, 516, 203);
contentPane.add(textArea);
srcBtn.setBounds(419, 25, 107, 23);
contentPane.add(srcBtn);
JButton dNcButton = new JButton("Process");
dNcButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
downloadTest.fileDownloadTest(srcTextField.getText(), textArea);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
dNcButton.setBounds(212, 70, 89, 23);
contentPane.add(dNcButton);
}
}
FileDownloadTest
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JTextArea;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class FileDownloadTest {
public void fileDownloadTest(String src, JTextArea textArea) throws IOException, InterruptedException {
String path = src;
FileInputStream fin = new FileInputStream(new File(path));
XSSFWorkbook workbook = new XSSFWorkbook(fin);
XSSFSheet sheet = workbook.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
System.out.println("rows are " + rows);
XSSFCell cell;
// Make sure that this directory exists
String dirName = src.substring(0, src.lastIndexOf("\\"));
File f = new File(dirName);
if (!f.exists()) {
f.mkdir();
}
System.out.println(f.getAbsolutePath() + " is Directory Name " + src + " is the file");
for (int i = 1; i < rows; i++) {
XSSFCell url = sheet.getRow(i).getCell(0);
String URLString = url.toString();
cell = sheet.getRow(i).getCell(7);
String fileName = URLString.substring(URLString.lastIndexOf("/") + 1);
int pageNumbers = downloadFiles(dirName, url.toString().replace("http", "https"));
if (cell == null) {
cell = sheet.getRow(i).createCell(1);
}
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
cell.setCellValue(pageNumbers);
FileOutputStream fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
textArea.append("downloaded " + fileName + "\n");
System.out.println("Done");
}
workbook.close();
fin.close();
}
public static int downloadFiles(String dirName, String urlString) {
System.out.println("Downloading \'" + urlString + "\' PDF document...");
String fileName = urlString.substring(urlString.lastIndexOf("/") + 1);
System.out.println(fileName + " is file name");
try {
saveFileFromUrlWithJavaIO(dirName + "\\" + fileName, urlString);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Downloaded \'" + urlString + "\' PDF document...");
int pageNumber = 0;
try {
pageNumber = getNoOfPages(dirName + "\\" + fileName);
} catch (IOException e) {
e.printStackTrace();
}
return pageNumber;
}
public static int getNoOfPages(String fileName) throws IOException {
PDDocument document = PDDocument.load(new File(fileName));
int numberOfPages = document.getNumberOfPages();
return numberOfPages;
}
public static void saveFileFromUrlWithJavaIO(String fileName, String fileUrl)
throws MalformedURLException, IOException {
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
in = new BufferedInputStream(new URL(fileUrl).openStream());
fout = new FileOutputStream(fileName);
byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null)
in.close();
if (fout != null)
fout.close();
}
}
public static void saveFileFromUrlWithCommonsIO(String fileName, String fileUrl)
throws MalformedURLException, IOException {
FileUtils.copyURLToFile(new URL(fileUrl), new File(fileName));
}
}
请告诉我如何解决这个问题。
由于
答案 0 :(得分:1)
以上评论是正确的,您在向文本区域添加文本时在EDT上。这是因为您从 dNcButton ActionListener 实现中调用 downloadTest.fileDownloadTest 。
离开EDT的好习惯是你有一个长时间运行的操作,并且下载文件通常是作为你不想做的事情的一个例子。美国东部时间。
网上有很多关于如何离开EDT的资源,包括很多这个伟大的网站;
On Event Dispatch Thread---want to get off of it
Make thread run on non EDT (event dispatch thread) thread from EDT
答案 1 :(得分:0)
与其他评论一样,您需要在EDT上仅保留与UI相关的任务。否则,如果您的用户正在下载100个文件,则UI将锁定,直到下载任务完成。 SwingWorker是为Swing应用程序执行此操作的完美类。这是一个简单的例子:
// Run your FileDownloadTest inside a SwingWorker
// or have the class extend SwingWorker
new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
//Perform downloading here (done off the EDT)
//Call publish(downloadedFileName) to be sent to the process method()
return null;
}
@Override
protected void process(List<String> chunks) {
// Modify textArea (done on the EDT)
StringBuilder downloadedFiles = new StringBuilder();
for (String fileName : chunks) {
downloadedFiles.append("downloaded" + fileName + "\n");
}
textArea.setText(downloadedFiles);
}
@Override
protected void done() {
//Anything you want to happen after doInBackground() finishes
}
}.execute();