Swing:ユーザーによるItemEventとアプリケーションによるItemEventを区別する方法はありますか?

StackOverflow https://stackoverflow.com/questions/176150

質問

Swingベースのアプリケーションでコンボボックスを使用していますが、ユーザーイベントから生成されたItemEventとアプリケーションが原因のItemEventを区別するために何をすべきかを考えるのに苦労しています。

たとえば、コンボボックス「 combo 」があり、ItemListener「 listener 」でitemStateChangedイベントをリッスンしているとします。ユーザーが選択を項目2に変更するか、次の行(擬似コード)を実行すると:

combo.setSelection(2)

..これらのイベントを区別することができないようです。

とはいえ、私は決してSwingの専門家ではないので、尋ねたいと思いました。

ありがとう!

役に立ちましたか?

解決

行動と反応の法則は非常に明確です:)。変更に対応しようとする場合、ユーザーとアプリケーションを区別する必要はありません。 「区別」する必要があるユースケースは1つだけだと想像できます。アプリケーションがいくつかのデータを表示している場合。この場合、おそらくアプリケーションのデータモデルがあります。また、このモデルにはいくつかの変更リスナーがあり、アプリケーションGUIはコンポーネントに値を設定することで反応します。そしてまた。ユーザーがGUIコンポーネントに何かを選択した場合。データモデルは値を変更することで反応します。この場合、観測されたオブジェクトからのイベントを無視するようにモデルに通知するデータモデルに何らかの読み取り専用状態を設定するのは簡単です。この通知セットはEDTで実行する必要があり、フラグ設定に問題はありません。小さな例:

class ApplicationDataModel {

    private Flag current = Flag.RW;

    public void setData(ApplicationData data) {
        current = Flag.RO;
        setDataImpl(data);
        notifyObservers();
        current = Flag.RW;
    }

    public void reaction(Event e) {
        if (flag = Flag.RO) return;
        ...
    }

}

フラグ付けに注意し、スレッド化を忘れないでください。別のスレッドからsetDataを呼び出している場合、EDTで問題が発生します。もちろん。 ApplicationData オブジェクトの抽出は、別のスレッドで実行する必要があります;)。一般に、アプリケーションの設計を再考します。

他のヒント

ユーザーがアイテム2を選択するか、APIがsetSelection(2)を呼び出すかどうか、イベントは同じように表示されます

問題の解決策は、選択が変更されたときにitemStateChangedコードに何をさせたいかを考え直すことです。条件ごとにアプリの動作が異なるのはなぜですか?たぶんあなたが有利に使える類似点があるでしょう。

フラグを使用するときは注意してください。 itemStateChangedイベントは、イベントディスパッチスレッドで発生します。これは、フラグの状態を設定するスレッドとは異なるスレッドです。これは、フラグの使用が100%信頼できない可能性があることを意味します。

選択を設定する前にコードにフラグを設定し、リスナーでこのフラグを確認します(設定されている場合はフラグを解除します)...

Java 6以降、より良い方法があるかもしれませんが、これは私がいつも使っていた方法です...

[編集] :Davidが指摘しているように、SwingUtilities.invokeLaterなどを使用してEDTでフラグを設定(およびコンボを更新)する必要があります(とにかくこれを行う必要がありますUIコントロールを変更しています)

イベントを区別する必要がある場合は、おそらくデザインについて何か再考する必要があるでしょう。 MVCのポイントは、モデルの変更をユーザーの実際のマウスクリックから切り離すことです。

おそらく、これらの2つの状況を区別したいなぜの観点から質問を再度述べる必要があります。その後、目標を達成する別の方法に関するガイダンスを提供できます。

だから、単純に古い直接的な状態変更ではなく、ユーザー選択が何らかのアクションを実行することを望んでいると思います。これは、柔軟性の制限が原因で発生する問題です(特に他の方向に柔軟性がある場合、柔軟性は常に制限されます)。

私の提案:

まず、常にSwingでモデルを使用することに直行します。ウィジェットは複雑な方法であり、さまざまな懸念事項を分割する必要があります。幸いなことに、Swingはそのモデルと共にすでに存在しています。

一般的なパターンは、モデル間で委任することです。したがって、この場合は、「本物」を使用します。データを保持するデフォルトモデル。 JComboBoxと実際のComboBoxModelの間に挿入し、状態変更命令でアクションを実行するComboBoxModelを委任します。アプリケーションコードはJComboBoxを無視し、委任モデルをバイパスして実際のComboBoxModelに直行する必要があります。ダイアグラムで:

User -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- Application code
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top