2016-07-18 128 views
0

我有一個Java應用程序用於運行錦標賽,其中我建立了一個自動建議功能,從數據庫獲取名稱並將其顯示在JPopupMenu中。我一直無法按需複製這個bug,但偶爾有一個JPopupMenus會像平常一樣消失,只不過它的位置輪廓仍然在屏幕上,並且顯示在所有其他程序甚至包括其他程序上如果我的應用程序最小化。JPopupMenu不會消失,因爲它應該

以下是我在談論的一個截圖: enter image description here

你可以看到下面「埃斯皮諾薩」 JPopupMenu的一些殘餘仍然被顯示出來。這有時包含文本內部和其他時間只是在一個空框中的背景顏色。這種殘留物是純粹的化妝品,我還沒有找到任何物理或編程方式與其進行交互的方式(熱編碼)。

這裏是我用來顯示JPopupMenu的方法:

private void resetLastNamePopup() { 

    Thread t = new Thread() { 

     @Override 
     public void run() { 

      lnPopup.setVisible(false); 
      lnPopup.removeAll(); 

      if(DBHSDatabaseIntermediary.isConnected()) { 

       if(!(fnTextField.getText().equals("") && lnTextField.getText().equals(""))) { 

        JMenuItem item = null; 
        String[] names = DBHSDatabaseIntermediary.getLastNames(fnTextField.getText(), lnTextField.getText()); 
        for(int i=0; i < names.length; i++) { 

         if(!names[i].equals(lnTextField.getText().trim())) { 

          item = new JMenuItem(names[i]); 
          item.addActionListener(lnActionListener); 
          item.addMouseListener(NewPlayerPanel.this); 
          lnPopup.add(item); 

         } 

        } 

        if(names.length > 0 && !names[0].equals("")) { 

         lnPopup.setVisible(true); 

        } 
        lnPopup.grabFocus(); 

       } 

      } 

     }// ends run() 

    }; 

    t.start(); 

} 

預先感謝您。

回答

3

必須在AWT事件分派線程上調用Swing方法和構造函數。您正在另一個線程上調用這些方法。其結果是「未定義的行爲」 - 通常意味着事情有時會起作用,但並非總是這樣。

您需要的Swing調用從數據庫調用,這是使用EventQueue.invokeLater(或它的別名,SwingUtilities.invokeLater)來進行分離:

private void resetLastNamePopup() { 

    lnPopup.setVisible(false); 
    lnPopup.removeAll(); 

    final String fn = fnTextField.getText(); 
    final String ln = lnTextField.getText(); 

    Thread t = new Thread() { 

     @Override 
     public void run() { 
      if(DBHSDatabaseIntermediary.isConnected() 
        && !fn.isEmpty() && !ln.isEmpty()) { 

       final String[] names = 
        DBHSDatabaseIntermediary.getLastNames(fn, ln); 

       // Rebuild JPopupMenu in AWT event thread. 
       EventQueue.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         for (String name : names) { 
          if (!name.equals(ln)) { 
           JMenuItem item = new JMenuItem(name); 
           item.addActionListener(lnActionListener); 
           lnPopup.add(item); 
          } 
         } 

         if (names.length > 0 && !names[0].isEmpty()) { 
          lnPopup.setVisible(true); 
          lnPopup.grabFocus(); 
         } 
        } 
       }); 
      } 
     }// ends run() 

    }; 
    t.start(); 
} 

欲瞭解更多信息,請參閱javax.swing package contract,並在Java教程Concurrency in Swing

相關問題