6

Swing Pro の皆様、こんにちは。良い (といいのですが) 質問があります。

以下は、タスクの要件と考えられる解決策です。このようなハードコアな経験をした人に、これについていくつかの考えを共有してもらいたい.

これにはコーディングなどは必要ありません。sun.swing および/または javax.swing.plaf パッケージに存在するプライベートシンボルを操作する必要があるという事実に関して、どのアプローチがより信頼できるかについての一般的なアドバイスが必要です。

タスクは、JFileChooser の動作を変更/変更することです (実際にはほんの少しです)。

  1. ユーザーがファイル名 JTextField で Enter キーを押し、フィールドにディレクトリへのパスが含まれている場合、そのディレクトリを「選択」せずにそのディレクトリに切り替えます。はい、ダイアログはディレクトリを受け入れるように構成されていますが、[開く] ボタンのクリックと、(場合によっては) ファイル リスト テーブルのダブルクリックのみを受け入れる必要があります。

  2. ユーザーがファイル名テキスト フィールドで Enter キーを押して、1GB を超えるデータを含むディレクトリ/ファイルを選択できないようにします

以下に、一般的なソリューション オプションをいくつか示します。

を。JFileChooser が提供するプロパティベースの変更をリッスンします (AFAICS は事後にトリガーされ、ここで必要な程度の制御を提供しません)。

b. javax.swing.plaf.basic.BasicFileChooserUI をいじくり回し (リフレクションを介して、プライベート レベルのカプセル化を破る)、への参照を変更します。

private Action approveSelectionAction = new ApproveSelectionAction();

カスタム アクションが 1 と 2 の追加チェックを行うようにします。このアプローチは plaf パッケージとリンクし、この UI クラスの下のクラスでこのアクションが何らかの形でオーバーライドされた場合に失敗する可能性があります。

c. JFileChooser コンポーネント階層をトラバースし、JTextField (コンポーネント ツリーで 1 回だけ発生するようです) を見つけ、その JTextField にぶら下がっているすべてのアクション リスナーをカスタム チェックで装飾します。私のデバッグ セッションは、この JTextField が、sun.swing.FilePane にある JTextField の匿名サブクラスであることを示しています。このアプローチは OO に適しているように見えますが、一部の OS ではこのテキスト フィールドが存在しないか、階層内に他の JTextField も存在する可能性があります。

公共の JFileChooser API は、その動作を実現するのに十分ではないようです。他の 2 つのオプションは、ディープ マジックまたは非移植性 (長期的) のいずれか、あるいはその両方です。

では、問題は次のとおりです。どのアプローチを選択し、その理由は何ですか?

4

2 に答える 2

6

オプション 2 に関しては、受け入れアクションをカスタマイズするためにリフレクションを使用する必要はありません。ApproveSelection() メソッドをオーバーライドするだけです。何かのようなもの:

JFileChooser chooser = new JFileChooser( new File(".") )
{
    public void approveSelection()
    {
        if (getSelectedFile().exists())
        {
            System.out.println("duplicate");
            return;
        }
        else
            super.approveSelection();
    }
};
于 2010-11-20T17:29:15.950 に答える
3

私は最近、同じ要件に遭遇しました。つまり、JFileChooser の JTextField で Enter キーを押すと、表示されたダイアログがダイアログから戻るのではなく、ディレクトリをトラバースする必要があります。[開く] ボタンをクリックするだけで、最終的な選択が行われます。

ソリューションはかなり単純で (少なくとも私のアプリケーションでは)、2 つのコンポーネントがあります (めちゃくちゃなフォーマットを許してください。私はこのフォーラムに不慣れで、コードが正しく表示されない理由がわかりません)。

1 - AWTListener を登録して、ユーザーによって生成された最後のイベント タイプを追跡します。

class MyChooser extends JFileChooser implements java.awt.AWTEventListener {

    ...
    MyChooser(){
        Toolkit.getDefaultToolkit().addAWTEventListener(this,
        AWTEvent.MOUSE_EVENT_MASK + AWTEvent.KEY_EVENT_MASK);
        ...

    }

    int lastEventId;

    public void eventDispatched(AWTEvent e) {
        lastEventId=e.getID();
    }
}

2 - JFileChooser の approvalSelection() メソッドをオーバーライドし、承認要求がマウス イベント (ユーザーが [開く] ボタンをクリックしたことが原因である可能性が高い) によるものか、ユーザーが Enter キーを押したことによるキー イベントによるものかを確認します。「lastEventId」変数は、この情報へのアクセスを提供します。私自身のapproveSelectionは次のようになります。

public void approveSelection() {
    File f=getSelectedFile();
    if (f.exists() && isTraversable(f) && lastEventId ==
        KeyEvent.KEY_PRESSED) {
        setCurrentDirectory(f);
        return;
    }
    super.approveSelection(); } 
于 2014-06-25T04:26:09.393 に答える