添加其他项目时无法从另一个线程更新 JProgressBar 的值
Can't update value of JProgressBar from another thread when adding another items
我在向 JPanel 添加其他组件时显示当前状态(在 JProgressBar 中)时遇到问题。
这个操作很繁重,需要大约 2 秒,迭代 20 次(添加 20 个项目)。
但它可以是 100 个项目。
所以我需要实现在JProgressBar中显示每次迭代的当前状态,但我不知道该怎么做。 (在我的代码中它是值 perc)
您能解释一下 EDT 的工作原理吗?是否将事件添加到队列中?谢谢!
我的 JProgressBar 对象:categoryStatus。
这是我的代码:
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();
我写这篇文章是为了展示我认为您正在尝试做的事情。它创建了两个主面板。最上面的一个托管 ProgressBar。下面的面板承载在线程中创建的较小面板。添加较小的面板时,使用 Swing 计时器来模拟 activity。
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);
}
}
}
我在向 JPanel 添加其他组件时显示当前状态(在 JProgressBar 中)时遇到问题。
这个操作很繁重,需要大约 2 秒,迭代 20 次(添加 20 个项目)。 但它可以是 100 个项目。
所以我需要实现在JProgressBar中显示每次迭代的当前状态,但我不知道该怎么做。 (在我的代码中它是值 perc)
您能解释一下 EDT 的工作原理吗?是否将事件添加到队列中?谢谢!
我的 JProgressBar 对象:categoryStatus。
这是我的代码:
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();
我写这篇文章是为了展示我认为您正在尝试做的事情。它创建了两个主面板。最上面的一个托管 ProgressBar。下面的面板承载在线程中创建的较小面板。添加较小的面板时,使用 Swing 计时器来模拟 activity。
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);
}
}
}