2012-03-12 42 views
7

Tôi có một ứng dụng Java Swing để tạo ra các hộp thoại con với các điều khiển văn bản. Và vấn đề là khi bạn thay đổi bố trí bàn phím trong hộp thoại con, nó thay đổi trở lại ngay sau khi hộp thoại được đóng lại.Bảo quản bố cục bàn phím trong ứng dụng xoay?

Điều tôi cần là bố cục keboard ở lại sau khi được chuyển đổi cho dù nó đã được chuyển đổi trong khung chính hoặc trong khung trẻ em.

Đây là một SSCCE minh họa các vấn đề:

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

public class InheritInputContext { 

    public static void main(String[] arg) { 
     final MainFrame mainFrame = new MainFrame(); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       mainFrame.setPreferredSize(new Dimension(300, 400)); 
       mainFrame.pack(); 
       mainFrame.setLocationRelativeTo(null); 
       mainFrame.setVisible(true); 
      } 
     }); 

    } 
} 


class MainFrame extends JFrame { 

    MainFrame() { 
     setLayout(new BorderLayout()); 
     JTextArea textArea = new JTextArea(); 
     add(textArea, BorderLayout.CENTER); 

     JButton dialogBtn = new JButton("Dialog"); 
     add(dialogBtn, BorderLayout.SOUTH); 
     dialogBtn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       ChildDialog cd = new ChildDialog(MainFrame.this); 
       cd.setPreferredSize(new Dimension(200, 200)); 
       cd.setLocationRelativeTo(MainFrame.this); 
       cd.pack(); 
       cd.setVisible(true); 
      } 
     }); 
    } 
} 


class ChildDialog extends JDialog { 

    ChildDialog(Window w) { 
     super(w); 
     JTextArea textArea = new JTextArea(); 
     getContentPane().add(textArea); 
    } 
} 
+1

Bạn đang nói về bố cục bàn phím của hệ điều hành? Một chút bối rối ở đây. –

Trả lời

2

Ok, tôi chỉ giải quyết với giải pháp này:

Thêm một người biết lắng nghe để toolkit java trong phương pháp main() như thế này:

AWTEventListener awtWindowListener = new AWTEventListener() { 
    @Override 
    public void eventDispatched(AWTEvent event) { 
     if (event instanceof WindowEvent) { 
      if (WindowEvent.WINDOW_CLOSED == event.getID() 
        || WindowEvent.WINDOW_CLOSING == event.getID()) { 
       Window child = ((WindowEvent) event).getWindow(); 
       Window parent = SwingUtilities.getWindowAncestor(child); 
       if (parent == null) return; 
       InputContext childIC = child.getInputContext(); 
       parent.getInputContext().selectInputMethod(childIC.getLocale()); 
      } 
     } 

    } 
}; 

Toolkit.getDefaultToolkit().addAWTEventListener(awtWindowListener, AWTEvent.WINDOW_EVENT_MASK); 

Nó hoạt động trên tất cả các hộp thoại con được tạo ra với cửa sổ cha mẹ như tham số hàm tạo. Trên sự kiện gần, Locale từ InputContext của hộp thoại con được đưa vào InputContext của cửa sổ chính của nó.

Có thể có một số cách tốt hơn.

1

Bạn chỉ cần tìm kiếm một cách để có bất kỳ sự thay đổi bố trí ảnh hưởng đến ứng dụng của bạn trên toàn cầu? Nếu có, một cách tiếp cận là tạo người nghe tùy chỉnh, có các thành phần khác nhau quan tâm đến thay đổi bố cục đăng ký sự quan tâm của họ trong các sự kiện đó và sau đó kích hoạt sự kiện bố cục thay đổi kích hoạt thay đổi trong tất cả các thành phần khi nó thay đổi trong bất kỳ một trong số họ.

Một cách khác để làm điều đó là lưu trữ thuộc tính bố cục trong đối tượng có thể truy cập được vào bất kỳ thành phần nào và yêu cầu chúng cập nhật bố cục của chúng theo định kỳ thông qua bộ hẹn giờ. Điều này sẽ ít hấp dẫn hơn, tuy nhiên, vì có lẽ sẽ có rất nhiều cập nhật không cần thiết so với chế độ hoạt động "chỉ cập nhật sự kiện". Tôi đoán người dùng ứng dụng của bạn sẽ không thay đổi bố cục bàn phím của họ nhiều hơn một lần hoặc hai lần mỗi phiên (trái với mỗi 5 giây)?

Cách khác, thứ ba là thực hiện cài đặt bố cục bàn phím được lưu trữ ở cấp ứng dụng và được tải khi khởi động. Sau đó, khi thay đổi bố cục bàn phím xảy ra, hãy nhắc người dùng khởi động lại ứng dụng để các thay đổi có hiệu lực trên toàn cầu.

+0

Có, tôi đang tìm cách bảo toàn bất kỳ thay đổi bố cục nào được thực hiện trong ứng dụng, để tránh phải thay đổi bố cục lặp đi lặp lại trong mỗi hộp thoại mới. Ngay bây giờ tôi đang khám phá tùy chọn sử dụng AWTEventListener ở cấp ứng dụng, để tránh viết mã bổ sung cho mỗi khung con – yggdraa

+0

Cập nhật trên máy tính bị lỗi, nó sẽ bị quá tải. Yêu cầu tải lại ứng dụng cũng không được giải đáp, người dùng cần phải thay đổi giữa 2 ngôn ngữ mọi lúc. – yggdraa

+0

Tôi cũng đã xem NetBeans và IntellijIdea, cũng vậy. Bạn mở Cài đặt, ví dụ: thay đổi ngôn ngữ nhập, đóng Cài đặt và bố cục bàn phím trả về những gì trước đây. Trong các ứng dụng khác (trình duyệt, mssql, notepad), việc thay đổi bố trí bàn phím là nhất quán trên tất cả các ứng dụng. – yggdraa

1

Có và không: mã yggdraa của Mar 13 hoạt động tốt trên Windows nhưng không thành công trên Linux.

Có thể không có giải pháp phổ quát cho Linux cả: không có những thứ như Windows 'GetKeyboardLayout() và ActivateKeyboardLayout() ở đó. Tuy nhiên, một số hack phụ thuộc vào cấu hình có thể được thực hiện, chẳng hạn như phân tích cú pháp kết quả đầu ra của xset (details here) và buộc bố cục, ví dụ, khi bấm phím lên/xuống.

Trong ví dụ trên, mã lựa chọn đầu vào trong eventDispatched() được gọi quá muộn - khi bàn phím OS đã chuyển về hệ thống mặc định của Hoa Kỳ.

Một vài lần thử sức mạnh vũ phu không hoạt động: myParticularJField.setLocale (myForcedLocale) từ trình xử lý tiêu điểm của trường sẽ ngay lập tức được hoàn tác khi nhấn phím đầu tiên. Tương tự để buộc miền địa phương cấp cao nhất (JFrame/JDialog).

Cập nhật:

Chúng tôi chỉ có Windows trong sản xuất, vì vậy làm cho công việc này dưới Linux là không thực tế: quá nhiều công sức.

Chỉ trong trường hợp, một sản phẩm phụ. Điều này xác định chính xác bố cục nào hiện đang hoạt động: mặc định hoặc thay thế ("cục bộ"). Nó không thể phân biệt giữa một số bố trí thay thế:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 

public class LinuxKeyboardLayoutStatus { 

    public enum LayoutType { DEFAULT, LOCAL } 

    public LinuxKeyboardLayoutStatus.LayoutType getCurrentKeyboardLayoutType() throws IOException, InterruptedException { 
     String[] command = createCommand(); 
     Process p = Runtime.getRuntime().exec(command); 
     BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); 
     String l = r.readLine(); 
     r.close(); 
     p.waitFor(); 
     return decodeLayoutType(l); 
    } 

    protected String[] createCommand() { 
     return new String[] { "/bin/sh", "-c", "xset -q | grep LED | awk '{ print $10 }' | cut -c5" }; 
    } 

    protected LinuxKeyboardLayoutStatus.LayoutType decodeLayoutType(String commandOutput) { 
     return 
      commandOutput != null && !commandOutput.equals("0") ? LayoutType.LOCAL : LayoutType.DEFAULT; 
    } 

} 

Cập nhật:

Trong Ubuntu, sự thay đổi về cách bố trí mặc định xảy ra tại cửa sổ X mức (dbus sự kiện). Giải pháp thay thế: để tắt bố cục riêng cho mỗi cửa sổ: Cài đặt => Bàn phím => Bố cục, bỏ chọn "Bố cục riêng cho mỗi cửa sổ".

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