2013-08-26 44 views
5

在(嵌入式)Ubuntu 12.04系统上,我们有一个简单的Java程序,它在窗口上显示一些图形模式,每秒更新一次。我们用它来监视系统上运行的一些进程。问题在于,当它处于活动状态而不是最小化时,它会在窗口更新时窃取焦点。这使得无法使用开放的终端窗口进行工作。如何在更新窗口时防止Java图形程序窃取焦点?

运行应用程序窗体命令行或从Eclipse IDE运行时的行为是相同的。

在NetBeans IDE中运行时,Windows 7上不会发生同样的问题。

我们该如何防止Java应用程序窃取对Ubuntu机器的关注?


更新1:发现这个问题似乎有同样的问题挣扎: How do I stop/workaround Java apps stealing focus in Linux window managers。 读它,我了解到,问题是使用JFrame作为容器,这是我们使用的。他们的解决方案是使用JWindow容器而不是JFrame容器。然而,寻找差异,JWindow是“裸体”,并不像“真实”的窗口,因为没有装饰品。有没有办法使用JWindow 里面的一个JFrame,从而消除重点窃取?


更新2:试图在PC上的Ubuntu的虚拟机上运行此程序会产生相同的错误行为。这表明Windows 7和Linux的Java运行时间存在差异,并且该问题不是特定于嵌入式Linux。


更新3:这里有一个SSCCE:

//package SSCCE; 

import java.awt.*; 
import java.awt.geom.*; 
import javax.swing.*; 

public class MonitorSSCCE extends JFrame{ 

    public static void main(String[] args) 
    { 
     // Set the frame 
     JFrame ecoreFrame = new JFrame("SSCCE"); 
     ecoreFrame.setSize(120, 120); 
     ecoreFrame.setVisible(true); 

     // Refresh frame every 200 msec 
     while (true) { 
      GRFX grfx = new GRFX(); 
      ecoreFrame.add(grfx); 
      ecoreFrame.setVisible(true); 
      grfx = null; 

      try { 
       Thread.sleep(200); 
      } catch (InterruptedException e) { 

      } 
     } 
    } 


    static int clr = 0; 

    public static class GRFX extends JPanel { 

     public void paintComponent(Graphics comp) { 
      Graphics2D comp2D = (Graphics2D) comp; 

      // Draw a changin color rectangle 
      comp2D.setColor(new Color(clr, 0, 0)); 
      Rectangle2D.Double rect = new Rectangle2D.Double(10, 10, 100, 100); 
      comp2D.fill(rect); 
      clr = clr + 10; 
      if (clr > 255) 
       clr = 0; 
     } 
    } 
} 

UPDATE 4:在编制SSCCE,我有一些阅读和了解的窗口刷新方法多如牛毛的JFrame对象。发生问题的原因是while循环内的setVisible()调用。解决方案是用repaint()方法替换它。

+0

请编辑您的问题,包括最小[SSCCE(HTTP: //sscce.org/),它表现出你描述的问题。 – trashgod

+0

作为参考,这个[示例](http://stackoverflow.com/a/12228640/230513)“显示一些图形......,每秒更新一次,”但它并不会窃取焦点。 – trashgod

+1

@trashgod - 谢谢。我不是Java程序员,编写应用程序的人是从书中复制代码示例 - 所以他对Java GUI概念的熟悉程度也非常有限。我会看看你提供的链接,看看它是否能解决问题。 – ysap

回答

0

更换while()循环由repaint()setVisible()方法调用淘汰的问题:

// Refresh frame every 200 msec 
    while (true) { 
     GRFX grfx = new GRFX(); 
     ecoreFrame.add(grfx); 
     ecoreFrame.repaint(); 
     grfx = null; 

     try { 
      Thread.sleep(200); 
     } catch (InterruptedException e) { 

     } 
    } 
+0

问题1 - 是否有必要在每次迭代中将'grfx'对象'空'?如果我不这样做,会造成内存泄漏吗? – ysap

+0

问题2 - 图形对象放在JFrame上是否真的是对象,意思是矩形的属性可以稍后改变,画布将被正确重新绘制(想象一个移动的方块 - 旧方块是否会被正确擦除)? – ysap

+0

我已经更新了我的答案。 – trashgod

2

在Ubuntu 12.04.2与统一窗口管理器,这个example在背景桌面上以1Hz通常动画而终端和软件更新也运行。的参考进行比较的几点:

附录:我重新分解下方的例子来说明一些附加分:

image

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Rectangle2D; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

/** 
* @see https://stackoverflow.com/a/18455006/230513 
*/ 
public class TestGRFX { 

    private static class GRFX extends JPanel { 

     private static final int N = 256; 
     private float clr = 0; 
     private Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, N, N); 
     private Timer t = new Timer(100, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       GRFX.this.repaint(); 
      } 
     }); 

     public void start() { 
      t.start(); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      Graphics2D g2D = (Graphics2D) g; 
      g2D.setColor(new Color(Color.HSBtoRGB(clr, 1, 1))); 
      g2D.fill(rect); 
      clr += .01; 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(N, N); 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("TestGRFX"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     GRFX g = new GRFX(); 
     f.add(g); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
     g.start(); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TestGRFX().display(); 
      } 
     }); 
    } 
} 
+0

第三个项目符号鼓励我研究窗口更新方法并找到解决方案。它发生'setVisible()'偷窃的焦点,不得不被替换。 – ysap

相关问题