2012-03-12 2 views
7

텍스트 컨트롤을 사용하여 자식 대화 상자를 생성하는 Java Swing 응용 프로그램이 있습니다. 그리고 문제는 자식 대화 상자에서 자판 배열을 변경할 때 대화 상자가 닫힌 직후 다시 바뀝니다.스윙 앱에서 자판 배열을 유지 하시겠습니까?

내가 필요로하는 것은 메인 프레임이나 하위 프레임에서 전환되었는지 여부를 전환 한 후에 머무르는 키 보드 레이아웃입니다.

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

운영체제의 키보드 레이아웃에 대해 이야기하고 있습니까? 조금 혼란스러워. –

답변

2

가 좋아, 난 그냥이 솔루션으로 정착 :

는 다음과 같이 main() 메소드에서 자바 툴킷에 리스너를 추가 : 그것은 부모 창 등으로 생성 된 모든 자식 대화 상자에서 작동

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

생성자 매개 변수. Close 이벤트에서 자식 대화 상자의 InputContext 로케일은 부모 창의 InputContext에 놓입니다.

더 좋은 방법이있을 수 있습니다.

1

방금 ​​어떤 레이아웃 변경 전 세계적으로 응용 프로그램에 영향을 가지고 할 수있는 방법을 찾고 계십니까 : 여기

문제를 설명하는 SSCCE입니까?

그렇다면 한 가지 방법은 사용자 지정 리스너를 만들고 레이아웃 변경을 염려하는 다양한 구성 요소에 해당 이벤트를 등록한 다음 모든 구성 요소가 변경 될 때 변경 내용을 트리거하는 변경 레이아웃 이벤트를 시작하는 것입니다 그들 중 하나의 변화.

또 다른 방법은 구성 요소에 액세스 할 수있는 객체에 레이아웃 속성을 저장하고 타이머를 통해 레이아웃을 주기적으로 업데이트하도록하는 것입니다. 그러나 이는 "이벤트에 대한 유일한 업데이트"모드 대 많은 불필요한 업데이트가있을 것이기 때문에 바람직하지 않습니다. 귀하의 응용 프로그램 사용자가 키보드 레이아웃을 세션 당 1 ~ 2 회 이상 (5 초마다) 변경하지 않는다고 생각합니까?

또 다른 세 번째 방법은 키보드 레이아웃 설정을 응용 프로그램 수준에 저장하고 시작시로드하는 것입니다. 그런 다음 키보드 레이아웃이 변경되면 사용자에게 앱을 다시 시작하여 변경 사항이 전체적으로 적용되도록합니다.

+0

예, 나는 각 새로운 대화 상자에서 레이아웃을 반복해서 변경할 필요가 없도록 응용 프로그램에서 변경 한 레이아웃을 보존하는 방법을 찾고 있습니다. 지금 당장은 모든 하위 프레임에 대해 추가 코드를 쓰는 것을 피하기 위해 앱 수준에서 AWTEventListener를 사용하는 옵션을 모색 중입니다 – yggdraa

+0

타이머가 지나치게 업데이트되었습니다. 과부하 일 수 있습니다. app-reload 요청은 문제가되지 않으므로 사용자는 항상 2 개 언어를 변경해야합니다. – yggdraa

+0

NetBeans와 IntellijIdea도 보았습니다. 똑같은 것이 있습니다. 설정 (예 : 입력 언어 변경, 설정 닫기)을 열면 키보드 레이아웃이 이전의 상태로 되돌아갑니다. 다른 응용 프로그램 (브라우저, mssql, 메모장)에서는 키보드 레이아웃 변경이 앱 전체에서 일관되게 적용됩니다. – yggdraa

1

예 아니요 : yggdraa의 3 월 13 일 코드는 Windows에서 제대로 작동했지만 Linux에서는 실패했습니다.

Windows 용 GetKeyboardLayout() 및 ActivateKeyboardLayout()과 같은 기능이없는 Linux 용 보편적 인 솔루션이 전혀 없을 수 있습니다. xset (details here)의 출력을 구문 분석하고 키 업/다운에서 레이아웃을 강제 실행하는 것과 같은 구성 의존적 인 해킹이 가능할 수도 있습니다.

위 예제에서 eventDispatched()의 입력 선택 코드는 너무 늦게 호출됩니다. 즉, OS 키보드가 이미 시스템 기본 US로 다시 전환되었을 때입니다.

몇 가지 무작위 시도가 작동하지 않았습니다. 필드 포커스 핸들러의 myParticularJField.setLocale (myForcedLocale)은 첫 번째 키를 누를 때 즉시 취소됩니다. 최상위 (JFrame/JDialog) 로케일 강제 수행과 동일합니다.

업데이트 :

우리가 리눅스에서이 작품을 제작, 생산은 Windows가이 불가능하다 : 너무 많은 노력.

경우에 따라 부산물. 이는 어떤 레이아웃이 현재 활성 상태인지를 올바르게 결정합니다 : 기본값 또는 대체 ("로컬"). 그것은 여러 가지 대체 레이아웃을 구별 할 수 없습니다

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

} 

업데이트 :

우분투에서

다시 기본 레이아웃에 변화가 X 윈도우 레벨 (DBUS 이벤트)에서 발생합니다. 해결 방법 : 각 창에 대해 별도의 레이아웃을 끄려면 : 설정 => 키보드 => 레이아웃, "각 창마다 레이아웃 분리"를 선택 해제하십시오.

관련 문제