2013-08-26 25 views
5

Trên hệ thống Ubuntu 12.04 (nhúng), chúng tôi có một chương trình Java đơn giản hiển thị một số mẫu đồ họa trên cửa sổ, cập nhật từng giây một lần. Chúng tôi sử dụng nó để theo dõi một số quy trình đang chạy trên hệ thống. Vấn đề là trong khi nó đang hoạt động và không được giảm thiểu, nó đánh cắp sự tập trung bất cứ khi nào cửa sổ được cập nhật. Điều này làm cho các cửa sổ thiết bị đầu cuối mở không thể thực hiện được.Làm thế nào để ngăn chặn một chương trình đồ họa Java lấy cắp lấy nét khi cập nhật cửa sổ?

Hành vi này giống nhau khi chạy dòng lệnh biểu mẫu ứng dụng hoặc từ IDE Eclipse.

Vấn đề tương tự không xảy ra trên Windows 7 khi chạy dưới NetBeans IDE.

Làm cách nào để ngăn ứng dụng Java lấy cắp tiêu điểm trên máy Ubuntu?


UPDATE 1: Tìm thấy câu hỏi này mà dường như phải vật lộn với vấn đề tương tự: How do I stop/workaround Java apps stealing focus in Linux window managers. Đọc nó, tôi đã học được rằng vấn đề là sử dụng JFrame như một container, đó là những gì chúng ta sử dụng. Giải pháp của họ là sử dụng container JWindow thay vì JFrame container. Tuy nhiên, tìm kiếm sự khác biệt, JWindow là "trần truồng" và không hoạt động giống như một cửa sổ "thực", vì không có đồ trang trí. Có cách nào để sử dụng JWindow bên trong một JFrame và do đó loại bỏ việc lấy cắp trọng tâm?


UPDATE 2: Đang cố gắng để chạy chương trình này trên một Ubuntu Virtual Machine trên máy tính cung cấp cho các hành vi sai trái như vậy. Điều này cho thấy có sự khác biệt về thời gian chạy Java của Windows 7 và Linux, và rằng vấn đề không cụ thể đối với Linux được nhúng.


UPDATE 3: Dưới đây là một 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; 
     } 
    } 
} 

CẬP NHẬT 4: Trong khi chuẩn bị SSCCE, tôi đã có một số việc đọc và tìm hiểu về rất nhiều phương pháp cửa sổ làm mới của đối tượng JFrame. Nó xảy ra rằng vấn đề là cuộc gọi setVisible() bên trong vòng lặp while. Giải pháp là thay thế bằng phương pháp repaint().

+0

Hãy chỉnh sửa câu hỏi của bạn để bao gồm một tối thiểu [sscce] (http: //sscce.org/) thể hiện vấn đề bạn mô tả. – trashgod

+0

Để tham khảo, [ví dụ] (http://stackoverflow.com/a/12228640/230513) "hiển thị một số đồ họa ..., cập nhật mỗi giây", nhưng nó không _not_ ăn cắp tập trung. – trashgod

+1

@trashgod - cảm ơn. Tôi không phải là một lập trình viên Java, và người viết ứng dụng đã sao chép mã ví dụ từ một cuốn sách - vì vậy sự quen thuộc của anh ta với các khái niệm GUI của Java cũng rất hạn chế. Tôi sẽ xem xét liên kết bạn cung cấp và xem liệu nó có giải quyết được vấn đề không. – ysap

Trả lời

0

Thay thế các cuộc gọi setVisible() phương pháp bên trong while() vòng lặp bởi repaint() loại bỏ các vấn đề:

// 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

Câu hỏi 1 - có cần thiết 'null' đối tượng' grfx' ở mỗi lần lặp không? Nếu tôi không, điều này có gây ra rò rỉ bộ nhớ không? – ysap

+0

Câu hỏi 2 - Các đối tượng đồ họa có đặt trên các đối tượng thực sự của JFrame theo nghĩa là hình chữ nhật có các thuộc tính có thể được thay đổi sau đó không và canvas sẽ được vẽ lại chính xác (nghĩ một hình vuông chuyển động - hình vuông cũ có bị xóa đúng không)? – ysap

+0

Tôi đã cập nhật câu trả lời của mình. – trashgod

2

Trên Ubuntu 12.04.2 với Thống nhất trình quản lý cửa sổ, example hoạt ảnh bình thường trên màn hình nền ở 1 Hz trong khi bản cập nhật phần mềm và thiết bị đầu cuối cũng đang chạy. Một vài điểm tham chiếu để so sánh:

Phụ Lục: Tôi lại yếu tố ví dụ của bạn dưới đây để minh họa một số điểm bổ sung:

  • Đừng ngủ trên EDT; do sử dụng javax.swing.Timer để tăng tốc hoạt ảnh.

  • Ghi đè getPreferredSize() để thiết lập hình học ban đầu của thành phần đồ họa.

  • Profile để xác minh mức sử dụng vùng dự kiến.

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

Viên đạn thứ 3 khuyến khích tôi nghiên cứu các phương pháp cập nhật cửa sổ và tìm giải pháp. Nó xảy ra rằng 'setVisible()' đang ăn cắp sự tập trung và phải được thay thế. – ysap

Các vấn đề liên quan