【发布时间】:2017-03-05 12:34:36
【问题描述】:
我正在尝试实现一个进度条,用于确定 Java 中另一个线程的(近似)完成百分比。现在我有两个线程同时运行,但我不确定如何链接到另一个线程。我需要它从 0 开始,当另一个朋友完成时,我希望进度条显示 100。这就是我到目前为止所拥有的。我几乎整天都在寻找解决方案,但似乎找不到任何东西。有什么建议吗?
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileSystemView;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.*;
import java.io.File;
public class ProgressBarTest extends JFrame {
JButton browse, search;
JTextField directory;
JProgressBar progressBar;
File file;
JList<File> results;
JScrollPane scrollPane;
// Launch the app
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new ProgressBarTest();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// Create the app
private ProgressBarTest() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("We are testing the JProgressBar");
browse = new JButton("Browse");
browse.setActionCommand("browse");
browse.addActionListener(new ButtonListener());
search = new JButton("Search");
search.setActionCommand("search");
search.addActionListener(new ButtonListener());
directory = new JTextField(20);
directory.setEnabled(false);
file = new File(System.getProperty("user.home"));
results = new JList<File>(file.listFiles());
results.setCellRenderer(new MyCellRenderer());
results.setLayoutOrientation(JList.HORIZONTAL_WRAP);
results.setVisibleRowCount(-1);
scrollPane = new JScrollPane(results, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setPreferredSize(new Dimension(408, 100));
progressBar = new JProgressBar(0,100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
JPanel panel1 = new JPanel();
panel1.add(browse);
panel1.add(directory);
panel1.add(search);
JPanel panel2 = new JPanel();
panel2.add(scrollPane);
JPanel panel3 = new JPanel();
panel3.add(progressBar);
this.add(panel1, BorderLayout.PAGE_START);
this.add(panel2, BorderLayout.CENTER);
this.add(panel3, BorderLayout.PAGE_END);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private class MyCellRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
JLabel l = (JLabel)c;
File f = (File)value;
l.setText(f.getName());
l.setPreferredSize(new Dimension(130, 20));
l.setIcon(FileSystemView.getFileSystemView().getSystemIcon(f));
l.setBorder(new EmptyBorder(3,3,3,3));
return l;
}
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
if(event.getActionCommand().equals("browse")) {
JFileChooser chooser = new JFileChooser(System.getProperty("user.home"));
chooser.setDialogTitle("Search what?");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.showOpenDialog(null);
directory.setText(chooser.getSelectedFile().getPath());
} else if (event.getActionCommand().equals("search")) {
FileThread ft = new FileThread();
ft.start();
ProgressBarThread pbt = new ProgressBarThread();
pbt.start();
}
}
}
private class FileThread extends Thread {
public void run() {
file = new File(directory.getText().trim());
results.setListData(file.listFiles());
}
}
private class ProgressBarThread extends Thread {
public void run() {
for (int i = 0; i <= 100; i++) {
progressBar.setValue(i);
progressBar.setString(Integer.toString(i));
try {
Thread.sleep(50);
} catch(InterruptedException err) {
err.printStackTrace();
}
}
}
}
}
我知道我必须用决定第一个线程花费的百分比/时间的东西来取出 for 循环。只是不确定这是如何完成的。
【问题讨论】:
-
链接线程?我认为你对你需要做什么感到困惑。您不想链接线程,而是简单地将进程从在后台线程上运行的一段代码传递到在 Swing 事件线程上运行的另一段代码。
-
您的代码还从后台线程进行 Swing 突变更改,这是您永远不应该做的事情。请阅读 Swing 线程教程以了解如何正确处理此问题:Lesson: Concurrency in Swing。
-
@HovercraftFullOfEels 我是 Java 语言和线程的新手。我只是说一下我在 youtube 视频和一些示例上看到的内容。
-
如果您的目标是在搜索目录时使进度条不断前进,那么您可能不走运。为此,在后台运行的任务必须能够发送您的程序通知并量化其进度,我看不到您的文件搜索能够做到这一点。这种情况通常需要显示一个不确定的 JProgressBar。
-
@HovercraftFullOfEels 那是我的目标。在我的真实项目(非测试应用程序)中,我让它返回所有子文件夹和文件,它们可能有数百个文件并且需要一段时间才能显示它们。
标签: java multithreading jprogressbar