繁体   English   中英

使用 Swing 工作线程更新 Swing 组件

[英]Update Swing Component using Swing Worker Thread

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

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

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

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

  1. 没有 Thread.sleep() function控制台结果UI 结果

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

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

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

使用 Thread.sleep() function 的程序将打印出控制台中的所有图标,但这取决于我们在 Thread.sleep() function 中使用的值。 该值越低,某些图标可能不会在控制台中打印。

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

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

我遇到的问题可能是由于我的程序中的逻辑错误,因为这是我第一次使用 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;
    }
}

提前致谢。

当“发布”方法被非常频繁地调用时,这些值可能会在 EDT 上调用“进程”之前累积。

这就是为什么“处理”方法会收到要发布的 object 列表的原因。 您的代码有责任遍历列表并使用列表中的所有数据更新您的 GUI。

因此,鉴于您的“doInBackground”逻辑使用 for 循环,我建议累积多个值,并且您的“处理”方法只是处理其中之一。

当您使用 Thread.sleep(...) 时,您会限制可能合并为单个“进程”事件的对象数量。

因此解决方案是确保您的“过程”方法遍历列表中的所有对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM