我有一个管理单独串行协议线程的Java GUI应用程序。应用程序的本质是,当协议数据线程中的数据发生变化时,我需要闪存文本字段 - 想想实时数据监视器的一部分,它会查看随时间变化的稳定数据帧。我当前处理动画视图的方式是通过自定义SwingWorker(在下面的示例代码中显示为ComponentAnimator,动画实现AnimatableComponent的Swing对象列表 - 实际上只是用于我的应用程序的文本字段),它是从事件线程绑定协议数据数据的变化。 SwingWorker闪烁一个Text组件(在闪烁之间以指定的持续时间将前景和背景文本反转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) {}
}
答案 0 :(得分:1)
如何加入现有的SwingWorker
SwingWorker
不可共享,因为被指定为单个实例运行,没有非错误的方式将值从一个实例传递到另一个实例(意味着来自publish()
,process()
,setProgress()
),因为getProgress()
不适用{/ 1>}
这是标准线程的工作
使用信号量进行线程处理,但是已经可见的Swing GUI的所有输出都必须包装到invokeLater
中,仅包含在AWT,Swing中实现的方法,而不是整个方法生成此输出
您可以从SwingWorker
调用Executor
并开始第二名。 (SwingWorker
done()
实例传递值的(任意数量的实例)实例
例如
1)对于信号量,你会need to naming SwingWorkers instances
3)注意添加PropertyChangeListener,....没有实现任何AWT,Swing Listener