java - 添加其他项目时无法从另一个线程更新 JProgressBar 的值

标签 java swing user-interface jprogressbar edt

在向 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();

最佳答案

我写这篇文章是为了证明我认为你正在尝试做的事情。它创建两个主面板。最上面的一个是进度条。下一层承载着线程中创建的较小面板。 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);
          }

       }
    }

关于java - 添加其他项目时无法从另一个线程更新 JProgressBar 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58070712/

相关文章:

java - Spring MVC 映射方法未使用 POST 调用

java - 如何使 JFrame 具有特定大小,不包括边框?

java - 使用paintComponent(g)在同一类中生成两个图

java - 每次做出错误的猜测时,我都需要让我的程序向 GUI 添加一个 .jpg。

user-interface - Blackberry - 如何使菜单项变灰?

java - 为不同的时间字符串接收相同的 ZonedDateTime

java - Java HashMap 是否要求值不可变?

javascript - 执行脚本Webview JavaFx

algorithm - 如何优化qt tablewidget刷新?

java - 从支持 bean 中关闭 JSP 弹出窗口?