2012-09-05 58 views
8

我一直在驗證在mac osx的applet上運行的swing應用程序。在mac osx上使用java7模態對話框的焦點問題

在此確認,我發現與模態對話框以下問題:

  1. 當對話是開放的,是setModal(真),它會阻止根窗口的內容,但如果你點擊某處根窗口,對話框會在它下面,但它應該保留在根窗口的頂部。
  2. 如果對話框有一個JTextInputField,即使點擊它,它也不會獲得焦點。

所以我創建了一個小程序來顯示問題。你能幫我理解這裏有什麼問題嗎?

package com.macosx.tests; 

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class DialogExample extends JApplet{ 

    private static final long serialVersionUID = 1L; 
    private JPanel panel; 
    private JButton openDialogBtn; 

    private void doStart() { 
     panel = new JPanel(); 
     panel.setPreferredSize(new Dimension(500,500)); 

     openDialogBtn = new JButton("open dialog"); 
     openDialogBtn.addActionListener(new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       ModalDialog dialog = new ModalDialog(panel, true); 
       dialog.setVisible(true); 
      } 

     }); 
     panel.add(openDialogBtn); 
     setContentPane(panel); 
    } 


    class ModalDialog extends JDialog { 
     private static final long serialVersionUID = 1L; 

     public ModalDialog(Component parent, boolean modal) { 
      Dimension dimensionParentFrame = parent.getSize(); 
      setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width/2, 75)); 

      setModal(modal); 
      setModalityType(ModalityType.APPLICATION_MODAL); 

      JTextField txtField = new JTextField(); 
      add(txtField, BorderLayout.CENTER); 
     } 
    } 


    @Override 
    public void start() { 
     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       public void run() { 
        doStart(); 
       } 
      }); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

使用上述命令創建.jar文件(test.jar)。一旦完成,創建一個包含以下內容的html文件:

<html> 
<head> 
<title>Dialog test Applet</title> 
</head> 
<body> 
<applet id="DialogTestApplet" height="800" width="600" 
    code="com.macosx.tests.DialogExample" 
    archive="test.jar"> 
</applet> 
</div> 
</body> 
</html> 

完成此操作後,運行html文件。你會看到一個灰色背景的小程序和一個按鈕。然後嘗試:

  1. 單擊按鈕打開對話框。之後,點擊灰色區域的某個地方:對話框在瀏覽器窗口下方,但它應該保留在頂部,對嗎?
  2. 點擊按鈕打開對話框。之後,單擊對話框的文本字段並嘗試寫入內容:文本對話框不會收到焦點。

那麼,我在這裏做錯了什麼?有人可以用Mac電腦測試這個嗎?

感謝

規格:

java.vendor Oracle Corporation 
java.version 1.7.0_07 
os.name  Mac OS X 
os.version  10.7.4 

browser  firefox 15 

注:請注意,這只是發生在小程序在瀏覽器上運行,並且只在Mac OSX上。

+0

無法在10.5/1.6上重現。 – trashgod

+0

對我來說,使用10.7/1.6.0_33我仍然可以看到模態問題(1),但不是焦點問題(2)。 –

+0

類似的問題,但在Ubuntu [stackoverflow](http://stackoverflow.com/questions/12373140/java-applet-jtextfield-inaccesible-after-jdialog-on-ubuntu)。 – user1307657

回答

1

你應該在你的ModalDialog上放置一個「所有者」窗口。爲此,您必須在ModalDialog構造函數中調用super(所有者),並且可以使用SwingUtilities.getWindowAncestor(parent)檢索組件parent的父窗口。

+0

感謝您的建議。我只是嘗試了你提到的,但結果是一樣的...... –

+0

@LuisGonçalves嘗試發佈[SSCCE](http://sscce.org)而不必使用小程序。 –

+0

爲什麼不把代碼複製到Eclipse中,並選擇Run As - > Java Applet。這將運行小程序,你會看到它運行。但正如我在備註中提到的:只有當我們在瀏覽器上運行applet時,纔會出現這個問題,這正是我感興趣的工作。 –

1
  • 不支持Mac/OSX用戶,但是這是關於FocusJDialog常見的問題,

  • 還有另一個問題,即JDialog是在運行時創建的情況下,

  • Focus是基於異步物業來自Native OS

  • 創建此JDialog只有一次和re_usecontainer另一個行動

  • JDialog#setVisible應該被包裝成invokeLater()

  • 是有可能迫使Focus通過JTextField#setText(JTextField#getText())裹成invokeLater()

  • Dialog Focus,一個偉大的解決辦法由@camickr

+0

我會做一些代碼更改以包含dos建議,以查看它們是否能解決問題。 只需提及,如果您在Windows上運行相同的代碼,則不會發生任何問題。 –

+0

@LuisGonçalves這個常見的問題在Win,** nix和OSX平臺上的大多數複雜的GUI中都有介紹,只有黑客可以幫助你 – mKorbel

+0

你真的在Windows上運行過嗎?!原因是,如果我在Windows機器上運行它,我看不到任何問題... –

1

I確認,我和在OS X上運行在JDK7中的舊applet有相同的錯誤。正如提到的海報,只有在瀏覽器(ff)中運行的小程序纔會看到該錯誤,而不是appletviewer。

+0

感謝您的報告。順便說一下,你可以看看http://stackoverflow.com/questions/12180557/swing-menus-java-7-mac-osx。我也創建了一個似乎是一個bug的。你確認嗎? –

1

我可以驗證這是在Mountain Lion上運行的Safari 6和Firefox上的Java 1.7 Update 7+的問題。奇怪的是,在Lion上運行的早期版本的Safari並不是一個問題,但它在較早的操作系統上是Firefox中的問題。我非常渴望找到解決辦法,因爲我的許多applet用戶都在Mac上。我發現的一個解決方法(這是不夠的)是縮小窗口,然後重新打開它。 textfields/textareas然後變得可編輯。希望我們能找到一個更好的解決方案來解決這個煩人的需求。

1

我使用Safari和Firefox在Mac上使用Java 7 update 9時遇到了同樣的問題。當我打開一個包含JTextField的JDialog時,JTextField無法訪問。

我確實找到了解決方案。我從用戶按下「顯示對話框按鈕」到執行顯示按鈕的代碼時插入了一個延遲。

例如:

ActionListener al = new ActionListener(){ 
    public void actionPerformed(ActionEvent ae){ 
     TitleDialog dialog = new TitleDialog(main.findParentFrame()); // My JDialog which contains a JTextField. 
     dialog.setVisible(true); 
    } 
}; 
javax.swing.Timer timer = new javax.swing.Timer(1000, al); 
timer.setRepeats(false); 
timer.start(); 

我經歷過,如果延誤是做空的解決方案是行不通的。

如果使用SwingUtilities.invokeLater而不是javax.swing.Timer它將不起作用。也許延遲SwingUtilities.invokeLater太短。

+0

這對我不起作用,所以要小心這個解決方案 –

6

我發現了另一種解決方法。當窗口打開時,顯示一個選項窗格幾毫秒並關閉它。它將重點放在選項面板上,然後返回到對話框,允許忽略該錯誤。

這個代碼snipet添加到您的對話框的構造函數,它應該工作:

addWindowListener(new WindowAdapter(){ 
public void windowOpened(WindowEvent e){ 
    JOptionPane pane = new JOptionPane(); 
    final JDialog dialog = pane.createDialog("Please Wait"); 
    Timer timer = new Timer(50, new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      dialog.dispose(); 
     } 
    }); 
timer.setRepeats(false); 
timer.start(); 
dialog.setVisible(true); 
} 
+1

你可以嘗試看不見的對話框:'最終的JDialog對話框=新的JDialog(); dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); dialog.setUndecorated(真); dialog.setModal(真);' – xmedeko

0

我想用上面的解決方法(打開從對話的對話),但沒有顯示任何對話框。 以下是不可見對話框的代碼。

final JDialog dialog = new JDialog(); 
dialog.setUndecorated(true); 
dialog.setSize(0, 0); 
dialog.setModal(true); 
dialog.pack(); 
相關問題