我在unix服务器上编写了一些监控进程的程序。我的代码的主要部分看起来像这样:
Class FeedMonitor {
//.............
private volatile boolean monitor = true;
private volatile String feedShRez;
private volatile DefaultMutableTreeNode envNode;
//.............
public void prepareGUI() {
//..............
//
SwingWorker worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
sh = new Shell(env);
System.out.println("Swing worker for check feed statuses started...");
while (monitor) {
// get running feeds
feedShRez = sh.getFeedsStatus(rez);
System.out.println(feedShRez);
Thread.sleep(15000);
System.out.println("Swing worker for check feed statuses is waking up...");
}
return null;
}
@Override
protected void done() {
System.out.println("Swing worker completed.");
super.done();
System.out.println("Set monitor object to false");
feedShRez = "";
}
};
worker.execute();
//......
// This action I would like to execute in thread periodically
envTree.setCellRenderer(new DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree pTree,
Object pValue, boolean pIsSelected, boolean pIsExpanded,
boolean pIsLeaf, int pRow, boolean pHasFocus) {
System.out.println("Node is " + pValue.toString());
super.getTreeCellRendererComponent(
pTree, pValue, pIsSelected,
pIsExpanded, pIsLeaf, pRow,
hasFocus);
// we are under environment tree
if ( envNode !=null && ((DefaultMutableTreeNode)pValue).getParent() == envNode
&& feedShRez != null && !feedShRez.isEmpty()){
if (feedShRez.contains(pValue.toString())) {
System.out.println("Found feed " + pValue.toString() + " in strings");
setForeground(Color.GREEN);
} else {
setForeground(Color.RED);
}
}
return (this);
}
});
// In this thread I would like to execute action above
// but it works only one or two times
SwingWorker worker2 = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
while (monitor) {
//System.out.println("enter to second swing worker");
//envTree.repaint();
//mainFrame.repaint();
// should fire DefaultTreeCellRenderer action
envTree.setSelectionRow(0);
//envTree.setFont(null);
Thread.sleep(3000);
}
return null;
}
@Override
protected void done() {
super.done();
monitor = false;
System.out.println("Done in second swing worker");
//progressBar.setVisible(false);
}
};
worker2.execute();
正如您从上面的代码中看到的,我使用了两个SwingWorkers。在其中一个中,我向服务器发出请求,以检查另一个工作程序中正在运行的进程
我尝试通过调用envTree.setCellRenderer(new DefaultTreeCellRenderer()
来模拟envTree.setSelectionRow(0)
动作,以通过JTree中的GREEN和RED颜色标记运行和向下过程。这个动作对我来说不能正常工作的主要问题是,它只能触发一两次,但是当我手动点击JTree时它总是被执行。可以请有人就此提出建议。提前谢谢。
答案 0 :(得分:1)
如果我正确理解了您的问题,您可以使用shell获取某种进程列表。此列表存储在字段中,用于创建TreeModel
。您希望使用新提供的信息定期将JTree
重新标记为TreeModel
。
JTree
与所有Swing组件一样,具有内置机制,可在底层数据发生更改时触发重绘。您更改模型后,模型将触发更改事件,并且视图将拾取此事件。然后视图知道它必须重新绘制。
所以,我会提出这样的解决方案:
SwingWorker
(当前更新循环中的字段)不再使用该字段。相反,它使用SwingWorker#publish
方法发布中间结果。然后,您可以覆盖SwingWorker#process
方法来处理这些结果。在EDT上调用此方法,并可以使用新信息更新TreeModel
。更改TreeModel
。TreeModel
应包含与正确呈现数据相关的所有信息TreeModel
和相应事件所做的更改,JTree
将安排重新绘制。不需要第二个SwingWorker
。由于模型包含渲染器所需的所有信息,因此渲染器可以返回正确状态的Component
。