问题
I have a problem with displaying current status(in JProgressBar) while adding another components to JPanel.
This operation is heavy and takes at about 2 seconds with 20 iterations (adding 20 items). But it can be 100 items.
So I need to achieve displaying current status of every iteration in JProgressBar, but I can't realize how to do it. (In my code it is value perc)
And can you explain how EDT works? Is it adding events into queue to the end? Thank you!
My JProgressBar object: categoryStatus.
Here is my code:
categoryStatus = new LayoutProgressBar(150, 200, 800, 20, Color.decode("#F7F7F7"), 3, 0);
workPanel.add(categoryStatus);
LayoutPanel modsPanel = new LayoutPanel( 5, 64, 1090, 448, new Color(0,0,0,0));
modsPanel.setLayout(new BorderLayout());
LayoutPanel subModPanel = new LayoutPanel(8, 50, modsPanel.getWidth()-16, 300, new Color(0,0,0,0));
subModPanel.setPreferredSize(new Dimension(modsPanel.getWidth()-16, mods.size()*172 ));
Thread thrd1 = new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
long startTime = System.nanoTime();
for(int i = 0; i<mods.size(); i++){
String mod_url = mods.get("mod_"+i).get("mod_url").toString();
String title = mods.get("mod_"+i).get("name").toString();
String mod_type = mods.get("mod_"+i).get("type").toString();
LayoutPanel curModPanel = new LayoutPanel(10, i*172+5, 1060, 156, new Color(0,0,0,55));
LayoutLabel last_upd = new LayoutLabel(185, 112, 17, 17, true, false, Color.black, new ImageIcon(LoadingComp.class.getResource("/images/upd.png")), "", 12, "MullerBold.otf");
LayoutLabel vers_icon = new LayoutLabel(355, 112, 19, 19, true, false, Color.black, new ImageIcon(LoadingComp.class.getResource("/images/cube.png")), "", 12, "MullerBold.otf");
LayoutLabel vers = new LayoutLabel(385, 115, 130, 14, false, false, Color.decode("#00B9FF"), null, mods.get("mod_"+i).get("version").toString(), 12, "MullerMedium.otf");
LayoutLabel last_date = new LayoutLabel(215, 115, 130, 14, false, false, Color.decode("#00B9FF"), null, mods.get("mod_"+i).get("date").toString(), 12, "MullerMedium.otf");
LayoutLabel titleLabel = new LayoutLabel(185, 15, 130, 14, false, false, Color.white, null, title, 14, "MullerBold.otf");
LayoutLabel author1 = new LayoutLabel(185, 40, 130, 14, false, false, Color.decode("#8790a6"), null, "Автор:", 12, "MullerMedium.otf");
LayoutLabel author2 = new LayoutLabel(228, 40, 130, 14, false, false, Color.decode("#00B9FF"), null, mods.get("mod_"+i).get("author").toString(), 12, "MullerMedium.otf");
LayoutTextPane descr = new LayoutTextPane(185, 65, curModPanel.getWidth()-200, 40, "Roboto-Regular.ttf", mods.get("mod_"+i).get("descr").toString(), 12, Color.decode("#D3D4E4"), null, false, StyleConstants.ALIGN_LEFT);
String mod_action = "Установить";
String mod_btn = "install_btn";
if(lut.checkFileExistence( lut.setModDestination(mod_type, title) )) {
mod_action = "Удалить";
mod_btn = "delete_btn";
}
LayoutButton mod_btn_status = new LayoutButton(18, 103, 135, 34, false, mod_action, Color.WHITE, mod_btn, 14, "MullerBold.otf");
mod_btn_status.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
workWithMod(mod_btn_status, curModPanel, title, mod_url, mod_type);
workPanel.revalidate();
workPanel.repaint();
}
});
LayoutLabel img = new LayoutLabel(18, 15, 136, 72, true, false, Color.black, new ImageIcon(DefaultUtils.getWebImage(mods.get("mod_"+i).get("img_url").toString())), "", 12, "MullerBold.otf");
curModPanel.add(mod_btn_status);
curModPanel.add(last_upd);
curModPanel.add(vers_icon);
curModPanel.add(last_date);
curModPanel.add(img);
curModPanel.add(vers);
curModPanel.add(titleLabel);
curModPanel.add(author1);
curModPanel.add(author2);
curModPanel.add(descr);
subModPanel.add(curModPanel);
int perc = i * 100 / mods.size();
//new Worker(perc, categoryStatus).execute();
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
};
thrd1.start();
categoryStatus.setValue(50);
Thread thrd2 = new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
scrollPane = new JScrollPane(subModPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setOpaque(false);
scrollPane.setViewportView(subModPanel);
scrollPane.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE);
scrollPane.getViewport().setOpaque(false);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.getVerticalScrollBar().setOpaque(false);
scrollPane.getVerticalScrollBar().setUnitIncrement(5);
scrollPane.getVerticalScrollBar().setUI(new LayoutScrollPane(Color.white));
scrollPane.getVerticalScrollBar().setPreferredSize(
new Dimension(7, Integer.MAX_VALUE));
modsPanel.add(scrollPane);
workPanel.remove(categoryStatus);
workPanel.repaint();
workPanel.revalidate();
workPanel.add(modsPanel);
}
});
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
scrollPane.getVerticalScrollBar().setValue(0);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
};
thrd2.start();
回答1:
I wrote this to demonstrate what I think you are trying to do. It creates two main panels. The top one hosts the ProgressBar. The lower one hosts the smaller panels created in the thread. A Swing timer is used to simulate activity while the smaller panels are added.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ProgressDemo extends JPanel {
JProgressBar bar = new JProgressBar();
JFrame frame = new JFrame();
int n = 0;
int panelCount = 0;
JPanel subPanel = new JPanel();
public ProgressDemo() {
setPreferredSize(new Dimension(500, 500));
subPanel.setPreferredSize(new Dimension(500, 450));
frame.add(this);
add(bar);
add(subPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(0, new MyActionListener());
timer.setDelay(200);
bar.setMaximum(200);
timer.start();
}
public static void main(String[] args) {
new ProgressDemo().start();
}
public void start() {
for (int i = 0; i < 200; i++) {
try {
SwingUtilities.invokeAndWait(() ->
{
subPanel.add(new MyPanel());
revalidate();
frame.repaint();
});
sleep(500);
}
catch (InvocationTargetException | InterruptedException ite) {
ite.printStackTrace();
}
}
}
public static void sleep(int milli) {
try {
Thread.sleep(milli);
}
catch (InterruptedException ie) {
}
}
private class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
n++;
if (n > 200) {
n = 0;
}
bar.setValue(n);
}
}
Color[] colors = {
Color.red, Color.blue, Color.green, Color.yellow, Color.cyan,
Color.magenta
};
class MyPanel extends JPanel {
public MyPanel() {
setBackground(colors[panelCount % colors.length]);
int w = 25;
int h = 25;
setPreferredSize(new Dimension(w, h));
panelCount++;
setVisible(true);
}
}
}
来源:https://stackoverflow.com/questions/58070712/cant-update-value-of-jprogressbar-from-another-thread-when-adding-another-items