当前位置: 首页 > 知识库问答 >
问题:

使用Swing Worker线程更新Swing组件

栾英资
2023-03-14

目前,我正在尝试使用SwingWorker构建Swing应用程序,以不断更新面板。

我想在这里完成的是从数据库加载数据,每个数据都将作为面板中的图标发布。图标的颜色基于严重程度字段的值。例如:

示例数据在这张图片中,我有12个对象_id A001的数据。doInBackground()方法中的函数将循环12次,并调用publish()函数在面板中显示图标。图标的颜色基于每个对象id的严重性字段的最高值。

在doInbackground()方法中,我使用了两种结果不同的方法:

>

  • 没有线。sleep()函数控制台结果用户界面结果

    使用Thread.sleep()函数10毫秒控制台结果UI结果

    使用Thread.sleep()函数20毫秒控制台结果UI结果

    不使用线程的程序。sleep()函数将只打印控制台中的最后一个图标,就像publish()函数只执行一次一样。

    使用线程的程序。sleep()函数将打印出控制台中的所有图标,但这取决于我们在线程中使用的值。sleep()函数。值越低,一些图标可能无法在控制台中打印。

    数据库中的所有图标都完全显示在用户界面面板中,但基于使用的Thread.sleep()函数和延迟使用的时间,颜色不一致。

    就我个人而言,我不想使用Thread.sleep()函数,因为当数据较大时,延迟可能会更高。

    我遇到的问题可能是由于程序中的逻辑错误,因为这是我第一次使用SwingWorker。

    如果有人想试试的话,我也会把我的全部代码放在这个问题上。https://drive.google.com/file/d/1Fs1r72HWEzOMwVY2FF9ujtl3eUd-4oIS/view?usp=sharing

    处理数据在doInBackground()方法中完成,然后将值传递给process()方法以更新面板。

    以下是SwingWorker线程的代码:

    package com.akbar.thread;
    
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.Insets;
    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.TreeMap;
    
    import javax.persistence.TypedQuery;
    import javax.swing.AbstractButton;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.SwingWorker;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.query.Query;
    
    import com.akbar.datastructure.TerminalData;
    import com.akbar.sources.RoundImageButton;
    
    public class MonitorThread extends SwingWorker<Void, LinkedHashMap<String, String>> {
        private static final String GREEN = "/com/akbar/resources/green48.png";
        private static final String YELLOW = "/com/akbar/resources/yellow48.png";
        private static final String RED = "/com/akbar/resources/red48.png";
        private static final String BLACK = "/com/akbar/resources/black48.png";
        private static final int SEVERITY_LEVEL = 0;
        
        private boolean print = false;
        
        private int newCount = 0;
        private int updCount = 0;
        private int terminalSev;
        private int terminalCount = 0;
        
        private String lastTerminal;
        private String terminalId;
        private String termDetail;
        private String terminalStatus;
        
        private JPanel terminalPanel;
        private JScrollPane terminalScroll;
        
        private TerminalData terminalData;
        
        private TreeMap<String, JButton> updatedTerminal;
        
        private LinkedHashMap<String, LinkedHashMap<String, TerminalData>> terminalList;
        private LinkedHashMap<String, TerminalData> terminalDetail;
        private LinkedHashMap<String, String> zCommand;
        
        private SessionFactory factory = generateSessionFactory();
        private Session session;
        private Transaction tx;
        private TypedQuery<TerminalData> query;
        
        public MonitorThread(JPanel terminalPanel, JScrollPane terminalScroll) {
            this.terminalPanel = terminalPanel;
            this.terminalScroll = terminalScroll;
            
            updatedTerminal = new TreeMap<String, JButton>();
            terminalDetail = new LinkedHashMap<String, TerminalData>();
            terminalList = new LinkedHashMap<String, LinkedHashMap<String, TerminalData>>();
            zCommand = new LinkedHashMap<String, String>();
        }
    
        @SuppressWarnings("unchecked")
        @Override
        protected Void doInBackground() throws Exception {
            try {
                session = factory.openSession();
                tx = (Transaction) session.beginTransaction();
                query = session.createQuery("FROM TerminalData", TerminalData.class);
                List<TerminalData> result = query.getResultList();
                
                if (result.size() > 0) {
                    for (int i = 0; i < result.size(); i++) {
                        terminalData = (TerminalData)result.get(i);
                        terminalSev = 0;
                        termDetail = terminalData.getObjectDetail();
                        terminalId = terminalData.getObjectId();
                        if (terminalList.get(terminalId) != null) {
                            terminalDetail.put(termDetail, terminalData);
                            terminalList.put(terminalId, (LinkedHashMap<String, TerminalData>)terminalDetail.clone());
                            zCommand.put("UPD", terminalId);
                            publish(zCommand);
    //                      if (!(terminalId).equals(lastTerminal)) {
    //                          lastTerminal = terminalId;
    //                          updCount++;
    //                      }
                        } else {
    //                      if("125006".equals(terminalId)) {
    //                          System.out.println("test");
    //                      }
                            terminalDetail = new LinkedHashMap<String, TerminalData>();
                            terminalDetail.put(termDetail, terminalData);
                            terminalList.put(terminalId, (LinkedHashMap<String, TerminalData>)terminalDetail.clone());
                            zCommand.put("NEW", terminalId);
                            publish(zCommand);
    //                      newCount++;
                        }
                        Thread.sleep(20);
                    }
    //              System.out.println(String.format("New count: [%s], Update count: [%s]", newCount, updCount));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (session != null) {
                    session.close();
                }
            }
            return null;
        }
        
        @Override
        protected void process(List<LinkedHashMap<String, String>> chunks) {
            LinkedHashMap<String, String> test = chunks.get(chunks.size() - 1);
            List<String> commandKey = new ArrayList<String>(test.keySet());
            LinkedHashMap<String, TerminalData> tempDetail;
            List<String> terminalKey;
            List<String> detailKeys;
    
            TerminalData tempData = new TerminalData();
            
            int sev = 0;
            
            String color;
            String command = commandKey.get(0);
            String terminal = test.get(command);
            zCommand.remove(command);
    
    //      if (!(terminal.equals(lastTerminal))) {
    //          lastTerminal = terminal;
    //          System.out.println(String.format("Terminal [%s], count [%s]", terminal, ++terminalCount));
    //      }
            
            switch (command) {
            case "NEW":
                System.out.println(String.format("Newly Terminal [%s], count [%s]", terminal, ++terminalCount));
                lastTerminal = terminal;
                updatedTerminal = new TreeMap<String, JButton>();
                terminalKey = new ArrayList<String>(terminalList.keySet());
                tempDetail = new LinkedHashMap<String, TerminalData>();
                for (int i = 0; i < terminalKey.size(); i++) {
                    tempDetail = terminalList.get(terminalKey.get(i));
                    detailKeys = new ArrayList<String>(tempDetail.keySet());
                    sev = 0;
                    for (int j = 0; j < detailKeys.size(); j++) {
                        tempData = tempDetail.get(detailKeys.get(j));
                        int tempSev = Integer.parseInt(tempData.getSeverity());
                        if (tempSev > sev) {
                            sev = tempSev;
                        }
                    }
                    color = terminalKey.get(i).equals(terminal) ? BLACK : getIconColor(sev);
                    updatedTerminal.put(tempData.getObjectId(), new RoundImageButton(tempData.getObjectId(), color, tempData.getObjectId(), new Dimension(130, 48)));
                }
                updatePanel(updatedTerminal);
                break;
                
            case "UPD":
    //          System.out.println(String.format("Updated Terminal [%s], count [%s]", terminal, terminalCount++));
    //          if (!(terminal.equals(lastTerminal))) {
    //              lastTerminal = terminal;
    //              System.out.println(String.format("Terminal [%s], count [%s]", terminal, terminalCount++));
    //          }
                sev = 0;
                tempDetail = new LinkedHashMap<String, TerminalData>();
                Component[] comps = terminalPanel.getComponents();
                if (comps.length > 0) {
                    for (Component comp : comps) {
                        if (comp instanceof JButton) {
                            if (terminal.equals(comp.getName())) {
                                tempDetail = new LinkedHashMap<String, TerminalData>();
                                tempDetail = terminalList.get(terminal);
                                detailKeys = new ArrayList<String>(tempDetail.keySet());
                                for (int j = 0; j < detailKeys.size(); j++) {
                                    tempData = tempDetail.get(detailKeys.get(j));
                                    int tempSev = Integer.parseInt(tempData.getSeverity());
                                    if (tempSev > sev) {
                                        sev = tempSev;
                                    }
    //                              if ("125006".equals(terminal)) {
    //                                  System.out.println(String.format("Terminal [%s], object detail [%s], severity [%s]", terminal, tempData.getObjectDetail(), sev));
    //                              }
                                }
    //                          System.out.println(String.format("Terminal [%s], object detail [%s], severity [%s]", terminal, tempData.getObjectDetail(), sev));
                                color = getIconColor(sev);
                                ((AbstractButton) comp).setIcon(new ImageIcon(getClass().getResource(color)));
                                break;
                            }
                        }
                    }
                }
                break;
                
            case "RMV":
                break;
            
            default:
                break;
            }
        }
        
        @Override
        protected void done() {
            super.done();
        }
        
        private void updateComponent(String terminal) {
            LinkedHashMap<String, TerminalData> temp = terminalList.get(terminal);
            List<String> key = new ArrayList<String>(temp.keySet());
            TerminalData data;
            int highestSeverity = 0;
            int severity = 0;
            for (int i = 0; i < key.size(); i++) {
                data = temp.get(key.get(i));
                severity = Integer.parseInt(data.getSeverity());
                if (severity > highestSeverity) {
                    highestSeverity = severity;
                }
            }
            
            if (highestSeverity > SEVERITY_LEVEL) {
                
            }
        }
        
        private String getIconColor(int severity) {
            if (severity >= 0 && severity <= 10) {
                return GREEN;
            } else if (severity > 10 && severity <= 30) {
                return YELLOW;
            } else if (severity > 30 && severity <= 40) {
                return RED;
            }
            return BLACK;
        }
        
        private TreeMap<String, JButton> retrieveDisplayedTerminal() {
            TreeMap<String, JButton> temp = new TreeMap<String, JButton>();
            Component[] comps = terminalPanel.getComponents();
            if (comps.length > 0) {
                for (Component comp : comps) {
                    if (comp instanceof JButton) {
                        temp.put(comp.getName(), (JButton) comp);
                    }
                }
            }
            return temp;
        }
        
        private boolean checkCurrentTerminal(String terminal) {
            Component[] comps = terminalPanel.getComponents();
            if (comps.length > 0) {
                for (Component comp : comps) {
                    if (comp instanceof JButton) {
                        if ((comp.getName()).equals(terminal)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        
        private void updatePanel(TreeMap<String, JButton> terminals) {
            final int MAX_COLUMN = 14;
            JButton button;
            Component[] components = terminalPanel.getComponents();
            if (components.length > 0) {
                for (Component comp : components) {
                    if (comp instanceof JButton) {
                        terminalPanel.remove(comp);
                        terminalPanel.validate();
                        terminalPanel.repaint();
                        terminalScroll.validate();
                        terminalScroll.repaint();
                    }
                }
            }
            
            GridBagConstraints gc = new GridBagConstraints();
            gc.insets = new Insets(0, 5, 5, 0);
            
            int currentLine = 1;
            int size = terminals.size();
            int totalLine = size / MAX_COLUMN;
            if (totalLine == 0) {
                totalLine += 1;
            } else {
                int temp = size % MAX_COLUMN;
                if (temp > 0) {
                    totalLine += 1;
                }
            }
            
            int xCount = -1;
            int yCount = 0;
            
            List<String> keyList = new ArrayList<String>(terminals.keySet());
            for (int i = 0; i < size; i++) {
                if (terminals.get(keyList.get(i)) instanceof JButton) {
                    button = terminals.get(keyList.get(i));
                    if (xCount == MAX_COLUMN - 1) {
                        currentLine++;
                        yCount++;
                        xCount = 0;
                        gc.gridx = xCount;
                        gc.gridy = yCount;
                        gc.weightx = 0.0;
                        gc.weighty = (currentLine == totalLine ? 50.0 : 0.1);
                        gc.anchor = GridBagConstraints.NORTHWEST;
                        gc.fill = GridBagConstraints.HORIZONTAL;
                    } else {
                        xCount++;
                        gc.gridx = xCount;
                        gc.gridy = yCount;
                        gc.weightx = 0.0;
                        gc.weighty = 0.1;
                        gc.anchor = GridBagConstraints.NORTH;
                        gc.fill = GridBagConstraints.NONE;
                    }
                    terminalPanel.add(button, gc);
                }
            }
            terminalPanel.validate();
            terminalPanel.repaint();
            terminalScroll.validate();
            terminalScroll.repaint();
        }
        
        private SessionFactory generateSessionFactory() {
            try {
                return new Configuration().configure().buildSessionFactory();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    先谢谢你。

  • 共有1个答案

    艾昊明
    2023-03-14

    如果频繁调用“publish”方法,则在EDT上调用“process”之前,可能会累积值。

    这就是“process”方法接收要发布的对象列表的原因。代码负责遍历列表,并使用列表中的所有数据更新GUI。

    因此,考虑到您的"doInbackground"逻辑使用for循环,我建议累积多个值,而您的"处理"方法只是处理众多值中的一个。

    当你用线的时候。睡眠(…)您可以限制可能合并为单个“流程”事件的对象数量。

    因此,解决方案是确保“process”方法迭代列表中的所有对象。

     类似资料:
    • 问题内容: 您好,我想知道从swingworkerthread向jtextarea添加文本的最佳方法是什么,我创建了另一个类,Threadsclass()。execute()调用了jbutton。并且线程与此代码并行运行 现在id要做的是将x的值添加到主gui上的文本区域,任何想法都值得赞赏。 问题答案: JavaDocs有一个很好的例子 看一下发布和处理 潜在的意图是,您仅需要从事件调度线程中更

    • 问题内容: 我对SwingWorker和Java GUI有疑问。 我有几类,其处理的信息,我们可以给他们打电话,和。此处理可能需要很长时间。 这些都是的子类,但是本身并不是直接调用的(这些类使用继承自的方法。为了使EDT自由绘制进度条,在保持对象层次结构时最好的使用方法是什么?是否具有包装器类,并且有其调用?即使不扩展,它仍然可以按我期望的那样工作吗? 编辑:澄清我的问题,即使他们已经是子类,我如

    • 问题内容: 我有一个 JAVA6 GUI处理数据导入到我们的数据库。我已经实现了工作的JProgressBar。我知道对GUI所做的更改必须通过事件分发线程完成- 我认为我做不到(正确/完全)。 通过传入在主程序中创建的JProgressBar构造后台Worker线程UploadWorker,并在完成后直接设置更改进度条的值: 这可以正常工作,但有时(并非总是)在标准输出中抛出多个NPE,并且用户

    • 我现在正在使用SwingWorker,我遇到了一点问题,我意识到不可能从http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html.多次执行SwingWorker线程 我的问题是,是否可以创建同一SwingWorker线程的新实例?在这里的代码中,我将工作线程称为“worker” 是否可以创建此线程的多个实例,以便我

    • 问题内容: 我在这段代码上遇到了麻烦。 我正在使用一个随机数启动一个计时器,并且我想每秒倒数一次更新JLabel。但是我还没有弄清楚该怎么做,因为计时器触发的唯一侦听器位于它的末尾(我知道)。 这是代码: 问题答案: 我不太了解您为什么使用随机数的问题,但以下是一些观察结果: 我想每秒钟更新一次带有倒计时的JLabel。 然后,您需要将计时器设置为每秒触发一次。因此,计时器的参数是1000,而不是

    • 问题内容: 我在某处有几千行代码,并且我注意到当我对其进行过多更新时,我的JTextPane会闪烁。我在这里写了一个简化版: 这是针对终端(cmd)样式的GUI组件- 我想我已经在这里进行了所有优化,包括将其作为最终变量,这样它就不会被构造数百次。仍然,闪烁是明显的和不可接受的。几分钟后,组件完全冻结。我必须非常快速地更新组件,并且更新时必须将窗格滚动到底部。 我一直在考虑从头开始制作我自己的JT