2017-06-12 44 views
-1

我在寫我自己的類通知(不介意的代碼,它是由GUI的IntelliJ設計器生成)的的JWindow不正確渲染

public class NotificationWindow extends JWindow { 

private JLabel icon; 
private JTextArea message; 
private JLabel title; 
private JPanel mainPanel; 
private Spacer spacer1; 
private Spacer spacer2; 

public NotificationWindow(String ttl, String msg) { 

    mainPanel = new JPanel(); 
    mainPanel.setLayout(new GridLayoutManager(3, 3, new Insets(5, 5, 5, 5), -1, -1)); 

    icon = new JLabel(); 
    icon.setIcon(new ImageIcon(getClass().getResource("/resources/employee 64.png"))); 

    title = new JLabel(ttl); 
    title.setFont(
      new Font(title.getFont().getName(), Font.BOLD, title.getFont().getSize())); 


    message = new JTextArea(3, 44); 
    message.setText(msg); 
    message.setOpaque(false); 
    message.setFont(message.getFont().deriveFont(12f)); 
    message.setLineWrap(true); 
    message.setWrapStyleWord(true); 

    spacer1 = new Spacer(); 
    spacer2 = new Spacer(); 

    this.pack(); 
    this.setSize(400, 80); 
    this.setAlwaysOnTop(true); 
    this.setVisible(true); 

    this.getRootPane().setBorder(
      BorderFactory.createMatteBorder(1, 1, 1, 1, Color.DARK_GRAY)); 

    Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize(); 

    Insets toolHeight = Toolkit.getDefaultToolkit() 
      .getScreenInsets(this.getGraphicsConfiguration()); 

    this.setLocation(
     scrSize.width - this.getWidth() - 20, 
     scrSize.height - toolHeight.bottom - this.getHeight() - 20); 

    this.initUI(); 
} 

private void initUI() { 

    mainPanel.add(icon, 
     new GridConstraints(0, 0, 3, 1, 
       GridConstraints.ANCHOR_CENTER, 
       GridConstraints.FILL_NONE, 
       GridConstraints.SIZEPOLICY_FIXED, 
       GridConstraints.SIZEPOLICY_FIXED, 
       null, null, null, 0, false)); 

    mainPanel.add(title, 
     new GridConstraints(0, 1, 1, 2, 
       GridConstraints.ANCHOR_WEST, 
       GridConstraints.FILL_NONE, 
       GridConstraints.SIZEPOLICY_FIXED, 
       GridConstraints.SIZEPOLICY_FIXED, 
       null, null, null, 0, false)); 

    mainPanel.add(message, 
     new GridConstraints(1, 1, 1, 2, 
       GridConstraints.ANCHOR_WEST, 
       GridConstraints.FILL_NONE, 
       GridConstraints.SIZEPOLICY_FIXED, 
       GridConstraints.SIZEPOLICY_FIXED, 
       null, null, null, 0, false)); 

    mainPanel.add(spacer1, 
     new GridConstraints(2, 1, 1, 1, 
       GridConstraints.ANCHOR_CENTER, 
       GridConstraints.FILL_VERTICAL, 
       1, 
       GridConstraints.SIZEPOLICY_WANT_GROW, 
       null, null, null, 0, false)); 

    mainPanel.add(spacer2, 
     new GridConstraints(2, 2, 1, 1, 
       GridConstraints.ANCHOR_CENTER, 
       GridConstraints.FILL_HORIZONTAL, 
       GridConstraints.SIZEPOLICY_WANT_GROW, 
       1, null, null, null, 0, false)); 


    this.setContentPane(mainPanel); 
    this.repaint(); 

    // time after which notification will be disappeared 
    new Thread(() -> { 
     try { 
      Thread.sleep(6000); 
      dispose(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }).start(); 
} 
    } 

的想法是,該程序將顯示通知每隔一小時作爲提醒用戶。爲此,我使用ScheduledExecutorService類。我打電話通知這種方式(用於測試的通知稱爲每20秒):

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); 
     ses.scheduleAtFixedRate(new Runnable() { 
      private int i = 1; 
      @Override 
      public void run() { 
       NotificationWindow notificationWindow = 
        new NotificationWindow(
         "blah blah", 
         "Please, " + 
         "specify the details of the task you're currently working on."); 
      } 
     }, 10, 20, TimeUnit.SECONDS); 

的問題是,通知窗口有時不能正常顯示。有時它只是與通知窗口大小一樣,只能在沒有任何元素的情況下使用白色背景。 我的錯誤在哪裏?

+0

哪裏GridLayoutManager從何而來?這是一個Android佈局管理器,不是Swing。你在使用另一個圖書館嗎?我個人只使用Swing佈局管理器,從來沒有與他們有任何問題。 – markbernard

+0

@markbernard,GridLayoutManager是默認的IntelliJ IDEA GUI Designer佈局。我沒有改變任何東西。 – whyiamhere

+0

這意味着它依賴於Swing的外部庫。這不是標準的LayoutManager。我個人對使用非標準佈局猶豫不決,因爲有太多的選擇。 – markbernard

回答

2

有時,它只是幀通知窗口應與白色背景只有相同大小沒有任何元素時,在Event Dispatch Thread (EDT)不執行代碼會導致

隨機問題。

我正在使用ScheduledExecutorService類。

擺動部件應在EDT上創建。從ScheduledExecutorService調用的代碼不會在EDT上運行。您可以使用Swing Timer來安排活動。

閱讀Swing tutorial。上有幾個部分:

  1. 併發在Swing - 講解更多關於EDT
  2. 如何使用Swing計時器
+0

這不完全準確。您不必在EDT上創建您的GUI。他們的活動隨後由EDT控制(繪畫,事件派發等)。 – markbernard

+0

@markbernard曾經是這樣,但不再是。請參閱https://stackoverflow.com/questions/491323/is-it-safe-to-construct-swing-awt-widgets-not-on-the-event-dispatch-thread。 – VGR

+0

@VGR謝謝你。我不知道這個變化。 – markbernard