2012-09-05 29 views
8

Tôi đã xác thực ứng dụng xoay chạy trên applet dành cho mac osx.Các vấn đề tập trung với các hộp thoại phương thức java7 trên mac osx

Trong xác nhận này, tôi tìm thấy những vấn đề sau đây với các hộp thoại modal:

  1. Khi một hộp thoại được mở và là setModal (true) nó ngăn chặn các nội dung của cửa sổ gốc, nhưng nếu bạn nhấp vào nơi nào đó trên cửa sổ gốc, hộp thoại nằm dưới nó, nhưng nó sẽ vẫn ở trên cùng của cửa sổ gốc.
  2. Nếu hộp thoại có JTextInputField, nó không nhận được tiêu điểm ngay cả khi bạn nhấp vào nó.

Vì vậy, tôi đã tạo một chương trình nhỏ để hiển thị sự cố. Bạn có thể giúp tôi hiểu điều gì sai ở đây không?

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); 
     } 
    } 

} 

Sử dụng ở trên để tạo tệp .jar (test.jar). Khi đã xong, hãy tạo tệp html có nội dung sau:

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

Khi việc này được thực hiện, hãy chạy tệp html. Bạn sẽ thấy một applet với một nền màu xám và với một nút. Sau đó, hãy thử:

  1. nhấp vào nút để mở hộp thoại. Sau đó, nhấp vào một nơi nào đó trên vùng màu xám: hộp thoại nằm trong cửa sổ trình duyệt nhưng nó sẽ vẫn ở trên cùng, phải không?
  2. nhấp vào nút để mở hộp thoại. Sau đó bấm vào trường văn bản của hộp thoại và cố gắng viết một cái gì đó: textdialog không nhận được tiêu điểm.

Vì vậy, tôi đang làm gì sai ở đây? Có thể ai đó với một máy tính mac thử nghiệm này xin vui lòng?

Cảm ơn

Specs:

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

browser  firefox 15 

Chú ý: xin vui lòng lưu ý rằng đây chỉ xảy ra khi applet chạy trên trình duyệt và chỉ trên Mac OSX.

+0

Không thể sao chép trên 10.5/1.6. – trashgod

+0

Đối với tôi, sử dụng 10.7/1.6.0_33 Tôi vẫn thấy vấn đề phương thức (1) nhưng không phải là vấn đề trọng tâm (2). –

+0

Vấn đề tương tự nhưng trên ubuntu [stackoverflow] (http://stackoverflow.com/questions/12373140/java-applet-jtextfield-inaccesible-after-jdialog-on-ubuntu). – user1307657

Trả lời

1

Bạn nên đặt cửa sổ "chủ sở hữu" trên ModalDialog của mình. Để làm điều đó, bạn phải gọi super (owner) trong constructor ModalDialog của bạn và bạn có thể truy xuất cửa sổ cha của thành phần parent với SwingUtilities.getWindowAncestor(parent).

+0

Cảm ơn đề xuất của bạn. Tôi chỉ cố gắng những gì bạn đề cập nhưng kết quả là như nhau ... –

+0

@ LuisGonçalves cố gắng đăng một [SSCCE] (http://sscce.org) mà không cần phải sử dụng một applet. –

+0

tại sao bạn không chỉ sao chép mã đó vào Eclipse, ví dụ, và chọn Run As -> Java Applet. Điều đó sẽ chạy applet và bạn sẽ thấy nó đang chạy. Nhưng như tôi đã đề cập trong lưu ý: vấn đề này chỉ xảy ra khi chúng tôi chạy applet trên trình duyệt, đó là chính xác cách tôi quan tâm để làm cho nó hoạt động. –

1
  • không Mac/OSX sử dụng nhưng đây là vấn đề phổ biến về FocusJDialog,

  • có những vấn đề khác trong trường hợp đó JDialog được tạo ra trên Runtime,

  • Focus là không đồng bộ dựa trên trên các sản phẩm đến từ Native OS

  • tạo này JDialog chỉ một lần và re_usecontainer này cho một hành động

  • JDialog#setVisible nên được bọc vào invokeLater() quá

  • có thể buộc các Focus bởi JTextField#setText(JTextField#getText()) quấn vào invokeLater()

  • Dialog Focus, một trong những cách giải quyết tuyệt vời bằng cách @camickr

+0

Tôi sẽ thực hiện một số thay đổi mã để bao gồm các đề xuất dos để xem có bất kỳ giải pháp nào trong số đó giải quyết được sự cố hay không. Chỉ cần đề cập rằng nếu bạn chạy cùng một mã trên cửa sổ, không có vấn đề nào xảy ra. –

+0

@Luis Gonçalves vấn đề phổ biến này được trình bày trong GUI phức tạp nhất trên nền tảng Win, ** nix và OSX, chỉ hack có thể giúp bạn – mKorbel

+0

Bạn có thực sự chạy trên Windows ?! Nguyên nhân, tôi thấy không có vấn đề gì nếu tôi chạy nó trên máy tính của mình ... –

1

I xác nhận, tôi có lỗi tương tự với một applet cũ chạy trong JDK7 trên OS X. Như các poster đã đề cập, lỗi chỉ được thấy với applet đang chạy trong trình duyệt (ff) và không phải với appletviewer.

+0

Cảm ơn bạn đã báo cáo. Nhân tiện, bạn có thể xem trong http://stackoverflow.com/questions/12180557/swing-menus-java-7-mac-osx không. Tôi cũng tạo ra cái đó có vẻ như là một lỗi. Bạn có xác nhận điều đó không? –

1

Tôi có thể xác minh rằng đây là vấn đề đối với Java 1.7 Update 7+ trên Safari 6 và Firefox chạy trên Mountain Lion. Thật kỳ lạ nó không phải là một vấn đề trên các phiên bản trước của Safari chạy trên Lion nhưng nó là một vấn đề trong Firefox trên hệ điều hành cũ. Tôi khá tuyệt vọng để tìm một sửa chữa cho điều này như là một số người dùng applet của tôi là trên máy Mac. Một cách giải quyết mà tôi đã tìm thấy (điều đó không đủ bằng bất kỳ phương tiện nào) là để làm nhỏ cửa sổ và sau đó mở lại nó. Các textfields/textareas sau đó trở thành có thể chỉnh sửa. Hy vọng rằng, chúng ta có thể tìm thấy một giải pháp tốt hơn mà được xung quanh yêu cầu này gây phiền nhiễu.

1

Tôi gặp phải sự cố tương tự trên Mac với bản cập nhật Java 7 9 với Safari và Firefox. Khi tôi mở một JDialog có chứa một JTextField JTextField là không thể tiếp cận.

Tôi đã tìm được giải pháp. Tôi chèn một sự chậm trễ từ khi người dùng nhấn nút "hiển thị hộp thoại" để thực thi mã hiển thị nút.

Ví dụ:

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(); 

tôi có kinh nghiệm rằng nếu chậm trễ là ngắn giải pháp sẽ không làm việc.

Nếu người dùng sử dụng SwingUtilities.invokeLater thay vì javax.swing.Timer, nó sẽ không hoạt động. Có thể sự chậm trễ của SwingUtilities.invokeLater quá ngắn.

+0

điều này không làm việc cho tôi vì vậy hãy cẩn thận với giải pháp này –

0

Tôi đã tìm thấy một giải pháp khác. Khi JDialog được gọi từ JavaScript, nó có trọng tâm.

  1. Tạo phương thức của applet sẽ hiển thị hộp thoại
  2. Gọi phương thức này từ JavaScript.

Hy vọng điều đó sẽ hữu ích.Nhân tiện, các mẫu bắt đầu trên web từ hướng dẫn Java có cùng một vấn đề http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html

6

Tôi tìm thấy cách giải quyết khác. Khi cửa sổ được mở ra, hiển thị một tùy chọntrong khoảng vài mili giây và đóng nó lại. Nó tập trung vào optionpane và sau đó quay trở lại hộp thoại, cho phép bỏ qua lỗi.

Thêm snipet mã này để constructor thoại của bạn và nó sẽ làm việc:

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

Bạn có thể thử hộp thoại ẩn: 'final JDialog dialog = new JDialog(); dialog.setDefaultCloseOperation (JDialog.DO_NOTHING_ON_CLOSE); dialog.setUndecorated (true); dialog.setModal (true); ' – xmedeko

0

Tôi muốn sử dụng workaround trên (để mở hộp thoại từ hộp thoại), nhưng không hiển thị bất kỳ hộp thoại. Đây là mã cho hộp thoại không hiển thị.

final JDialog dialog = new JDialog(); 
dialog.setUndecorated(true); 
dialog.setSize(0, 0); 
dialog.setModal(true); 
dialog.pack(); 
Các vấn đề liên quan