- PR -

VISTAでsetCharacterSubsetsメソッドによるIMEモード変更が行われません

1
投稿者投稿内容
未記入
会議室デビュー日: 2008/01/15
投稿数: 11
投稿日時: 2008-03-19 11:41
いつもお世話様になっております。
質問させていただきたく思います。

setCharacterSubsets(・・・)を使用し
あるテキストフィールドにはひらがな入力、
あるテキストフィールドには半角カタカナ入力という入力制御を
行いたいと思っています。

しかし、あるフレームから新しいダイアログを表示したとき、
そのダイアログのテキストフィールドの入力制御が行われません。
なぜか、もとのフレームにおけるIMEの状態が
ダイアログでも保持されていて(?)
行っているはずの入力制御がきいていません。

この問題は、
XP(jre1.4.1_05-b01)だと発生せず、
VISTA(jre1.6.0_03-b05)だと発生します。

この問題について何かご存知の方がいらっしゃいましたら、
教えていただけますでしょうか。
よろしくお願い致します。

また、以下が現象を確認できるソースコードになります。
TestTextFieldというJTextFieldを継承したコンポーネントを使用し、
その使用元でTestTextFieldインスタンスにsetImeMode(入力モード)をすることで
IMEの制御を行っています。

問題が再現するテキストフィールドは、
testDialogクラスで使用されている「tfFalfLatinDigit」です。
IMEがONの状態でtestDialogを表示すると、
「tfFalfLatinDigit」はフォーカスが当たった際に直接入力モードになるはずが
ひらがな入力モードのままとなってしまいます。

===テストアプリケーションクラス=============================================

package testime;

import java.awt.Toolkit;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Dimension;

public class TestApplication {
boolean packFrame = false;

/**
* アプリケーションの構築と表示。
*/
public TestApplication() {
testFrame frame = new testFrame();
// validate() はサイズを調整する
// pack() は有効なサイズ情報をレイアウトなどから取得する
if (packFrame) {
frame.pack();
} else {
frame.validate();
}

// ウィンドウを中央に配置
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}

/**
* アプリケーションエントリポイント。
*
* @param args String[]
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.
getSystemLookAndFeelClassName());
} catch (Exception exception) {
exception.printStackTrace();
}
new TestApplication();
}
});
}
}

===始めに表示するフレーム===================================================
package testime;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import testime.component.TestTextField;

public class testFrame extends JFrame {
JPanel contentPane;
JButton jButton1 = new JButton();
TestTextField jTextField = new TestTextField();
JLabel jLabel1 = new JLabel();
public testFrame() {
try {
setDefaultCloseOperation(EXIT_ON_CLOSE);
jbInit();
} catch (Exception exception) {
exception.printStackTrace();
}
}

/**
* コンポーネントの初期化。
* @throws java.lang.Exception
*/
private void jbInit() throws Exception {
contentPane = (JPanel) getContentPane();
contentPane.setLayout(null);
setSize(new Dimension(400, 300));
setTitle("テストフレーム");
jButton1.setBounds(new Rectangle(106, 184, 193, 48));
jButton1.setText("ダイアログを表示");
jButton1.addActionListener(new testFrame_jButton1_actionAdapter(this));
jTextField.setBounds(new Rectangle(107, 119, 195, 37));
jTextField.setImeMode(TestTextField.MODE_WIDE_HIRAGANA);
jLabel1.setText("↓ここでひらがな入力モードに変更する");
jLabel1.setBounds(new Rectangle(110, 84, 198, 27));
contentPane.add(jButton1);
contentPane.add(jTextField);
contentPane.add(jLabel1);
}

public void jButton1_actionPerformed(ActionEvent e) {
testDialog testDialog = new testDialog();
testDialog.setSize(400,300);
testDialog.show();
}
}

class testFrame_jButton1_actionAdapter implements ActionListener {
private testFrame adaptee;
testFrame_jButton1_actionAdapter(testFrame adaptee) {
this.adaptee = adaptee;
}

public void actionPerformed(ActionEvent e) {
adaptee.jButton1_actionPerformed(e);
}
}

===問題が発生するダイアログ=============================================
package testime;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import testime.component.*;

public class testDialog extends JDialog {
JPanel panel1 = new JPanel();
//半角英数用テキストフィールド
TestTextField tfFalfLatinDigit = new TestTextField();
//IMEオフ(直接入力固定)用テキストフィールド
TestTextField tfWideHiragana = new TestTextField();
//戻るボタン
JButton btnHide = new JButton();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
public testDialog(Frame owner, String title, boolean modal) {
super(owner, title, modal);
try {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
jbInit();
pack();
} catch (Exception exception) {
exception.printStackTrace();
}
}

public testDialog() {
this(new Frame(), "testDialog", false);
}

private void jbInit() throws Exception {
panel1.setLayout(null);

tfFalfLatinDigit.setBounds(new Rectangle(19, 39, 182, 32));
     //半角英数入力を指定
tfFalfLatinDigit.setImeMode(TestTextField.MODE_HALF_LATIN_DIGIT);

tfWideHiragana.setBounds(new Rectangle(19, 124, 183, 33));
//ひらがな入力モードを指定
tfWideHiragana.setImeMode(TestTextField.MODE_WIDE_HIRAGANA);

btnHide.setBounds(new Rectangle(257, 119, 108, 38));
btnHide.setText("戻る");
btnHide.addActionListener(new testDialog_btnHide_actionAdapter(this));
jLabel1.setText("半角英数(ひらがな入力モードへの切り替え可)");
jLabel1.setBounds(new Rectangle(20, 11, 173, 23));
jLabel2.setText("ひらがな");
jLabel2.setBounds(new Rectangle(24, 92, 174, 28));
panel1.add(tfFalfLatinDigit);
panel1.add(tfWideHiragana);
panel1.add(btnHide);
panel1.add(jLabel1);
panel1.add(jLabel2);
getContentPane().add(panel1);
}
public void btnHide_actionPerformed(ActionEvent e) {
this.hide();
}
}


class testDialog_btnHide_actionAdapter implements ActionListener {
private testDialog adaptee;
testDialog_btnHide_actionAdapter(testDialog adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e) {
adaptee.btnHide_actionPerformed(e);
}
}

===IME制御を内部的に行うテキストフィールド=========================================
package testime.component;

import java.awt.TextField;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.im.InputContext;
import java.awt.im.InputSubset;

public class TestTextField extends TextField {
public static final int MODE_HALF_LATIN_DIGIT = 1; //半角英数モード
public static final int MODE_WIDE_HIRAGANA = 2;//ひらがなモード

public int imeMode = -1;

public TestTextField() {
super();
super.addFocusListener(new TextFieldListener(this));
}

public void setImeMode(int imeMode) {
switch (imeMode) {
case MODE_HALF_LATIN_DIGIT: //半角英数
enableInputMethods(true);
break;
case MODE_WIDE_HIRAGANA: //ひらがな
enableInputMethods(true);
break;
default:
System.out.println("不正なパラメータです");
}
int oldImeMode = this.imeMode;
this.imeMode = imeMode;
firePropertyChange("imeMode", oldImeMode, imeMode);
}


public final class TextFieldListener implements FocusListener {
/** キーボードフォーカスイベントを受け取るテキストフィールド */
private TestTextField textField;

public TextFieldListener(TestTextField txtFld) {
textField = txtFld;
}
public void focusGained(FocusEvent fEvent) {
switch (textField.imeMode) {
case MODE_HALF_LATIN_DIGIT: //半角英数
textField.setCharacterSubsets(new Character.
Subset[] {InputSubset.LATIN_DIGITS});
break;
case MODE_WIDE_HIRAGANA: //ひらがな
textField.setCharacterSubsets(new Character.
Subset[] {InputSubset.KANJI});
break;
default:
break;
}
}

public void focusLost(FocusEvent fEvent) {
}
}

public void setCharacterSubsets(Character.Subset[] subsets) {
InputContext input = this.getInputContext();
if (input != null) {
input.setCharacterSubsets(subsets);
}
}
}

以上がソースになります。

長文になってしまい申し訳ありませんが
よろしくお願い致します。
1

スキルアップ/キャリアアップ(JOB@IT)