0

我有一个管理单独的串行协议线程的 Java GUI 应用程序。应用程序的性质是,当协议数据线程中的数据发生变化时,我需要刷新文本字段——想想实时数据监视器的一部分,它查看随时间变化的稳定数据帧。我目前处理动画视图的方式是通过自定义 SwingWorker(在下面的示例代码中显示为 ComponentAnimator,它动画实现了 AnimatableComponent 的 Swing 对象列表 - 基本上只是为了我的应用程序的目的的文本字段),它从事件线程绑定协议数据数据变化。SwingWorker 闪烁一个文本组件(在闪烁之间指定的持续时间反转前景和背景文本 N 次)。

我需要帮助解决的问题是当后台协议线程中的数据快速变化时,ComponentAnimator 启动(通过我限制为三个并发线程池的 Executor 服务)快速排队并且动画持续的时间比变化的时间长数据。我想知道在 GUI 线程中是否有某种方式(我在其中触发了 ComponentAnimator),我可以改为加入现有的活动线程,取消其动画动作并用新的动作替换它们,而不是在之后排队另一个定时动画当前一个。任何帮助或指导将不胜感激。

/**
 * Handles bound Frame Info property.  For this particular panel,
 * the frameInfo may be associated with this Simulator (Panel)
 * or from frames received from the Prosim737 translated TCP
 * strings.
 *
 * @param aNewFrameInfo
 *               new frame of 429 words
 * @param aOldFrameInfo
 *               old frame of 429 words - if this is null
 *               then this represents the first time
 *               callback of that frame.  This is particularly
 *               important when processing the first Prosim737
 *               Frame for the indicator bits as we must ensure
 *               that we update all indicator bits.  For
 *               subsequent frames we are only interested in
 *               deltas.
 */
private void handleNewFrameData(
    final ProsimLabelInfo aNewFrameInfo,
    final ProsimLabelInfo aOldFrameInfo) {
    // log the event to the log area (this is done in the EVT queue)
    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            // log changes, don't need a verbose date
            // SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss:SSS");
            java.util.Date lastLogTimeStamp = (aOldFrameInfo == null)?
                aNewFrameInfo.getTimeStamp() : aOldFrameInfo.getTimeStamp();
            // Code added to handle updating the widgets to default when
            // this is the first callback to handleNewFrameData (i.e
            // when aOldFrameInfo null)
            java.util.Date deltaT = new java.util.Date(
                aNewFrameInfo.getTimeStamp().getTime() -
                lastLogTimeStamp.getTime());
            StringBuilder sb = new StringBuilder(
                "DT" + gTimeFormat.format(deltaT));
            // make sure we behave like tail -f by setting the caretPosition
            // to the end of the stream of data
            StyledDocument doc = jEventLogTextPane.getStyledDocument();
            // only print changed label details
            boolean bFromPanel = aNewFrameInfo.isFromPanel();
            for (Base429Word newWord : aNewFrameInfo.getDataWords().values()) {
                List<AnimatableComponent> flashingText = new ArrayList<>();
                // get the corresponding label from
                // the previous frame update if any
                Base429Word oldWord = (aOldFrameInfo == null)? null :
                    aOldFrameInfo.get429Word(newWord.getUniqueKey());
                // update GUI elements - if first time word encountered
                if (oldWord == null || !oldWord.equals(newWord)) {
                    processUpdatedWord(bFromPanel, oldWord, newWord);
                    if ((oldWord == null) || !newWord.equals(oldWord)) {
                        JTextComponent textField = bFromPanel? 
                            gTXLabelCompInfo.get(newWord.getUniqueKey()):
                            gRXLabelCompInfo.get(newWord.getUniqueKey());
                        if (textField != null) {
                            flashingText.add(new TextFieldAnimator(
                                textField,
                                Color.BLACK, Color.WHITE,   // final colors
                                Color.YELLOW, Color.RED));  // animating colors
                        }
                    }                        
                    if (flashingText.size() > 0) {
                        // flash first time or changed received words
                        mExecutorService.execute(
                            new ComponentAnimator(flashingText, 1, 70));
                    }                        
                }                    
            }
            // red for changed areas, blue for timestamp prefix
            try {
                doc.insertString(doc.getLength(), sb.toString(), gBlueTextAttrs);
                jEventLogTextPane.setCaretPosition(doc.getLength());
                if ( !jSaveLogButton.isEnabled() ) {
                    jSaveLogButton.setEnabled(true);
                    jClearEventLogButton.setEnabled(true);
                }
            } catch (BadLocationException ex) {}
        }
4

1 回答 1

1

如何加入现有的 SwingWorker

  • SwingWorker不可共享,因为被指定为作为单个实例运行,没有 non_hacky 方式将值从一个实例传递到另一个实例(意思是 from publish(), process(), setProgress()),因为没有实现适用于的东西getProgress()

  • 这是标准线程的工作

  • 使用信号量进行线程化,但所有到已经可见的 Swing GUI 的输出都必须包装到invokeLater中,仅限于在 AWT、Swing 中实现的方法,而不是整个方法生成此输出

  • 您可以调用SwingWorkerfromExecutor并开始 2nd。(任意数量的实例)实例,从SwingWorkers 实例传递值,以done()

  • 例如

    1) 对于信号量,您需要命名 SwingWorkers 实例

    2)另一个参考代码

    3) 注意添加PropertyChangeListener , .... 没有实现任何 AWT, Swing Listener

于 2013-09-17T15:45:47.087 回答