2

たとえば、ユーザーが表示時に感嘆符を設定したJOptionPane.WARNING_MESSAGE音や、表示時にエラー音を再生するにはどうすればよいJOptionPane.ERROR_MESSAGEですか?

4

3 に答える 3

3

私の仮定 -特別なことをする必要はなく、JOptionPane がそれを行うだけ- は、BasicOptionPaneUI コードをスキミングし、optionPane の audioActionMap がインストールされているかどうかを確認することに基づいていました。

オーディオが再生される場所は、UI のプロパティChangeListener で、その祖先プロパティが変更されます。

if ("ancestor" == e.getPropertyName()) {
    JOptionPane op = (JOptionPane)e.getSource();
    boolean isComingUp;

    // if the old value is null, then the JOptionPane is being
    // created since it didn't previously have an ancestor.
    if (e.getOldValue() == null) {
        isComingUp = true;
    } else {
        isComingUp = false;
    }

    // figure out what to do based on the message type
    switch (op.getMessageType()) {
    case JOptionPane.PLAIN_MESSAGE:
        if (isComingUp) {
            BasicLookAndFeel.playSound(optionPane,
                               "OptionPane.informationSound");
        }
        break;
    // all other message types handled as well
}

共有 actionMap がインストールされます (遅延のため、optionPane が一度表示されている必要があります)。

assertTrue(UIManager.get("AuditoryCues.actionMap") instanceof ActionMap);
ActionMap map = (ActionMap) UIManager.get("AuditoryCues.actionMap");
assertNotNull(map.get("OptionPane.errorSound"));

OS(win 7)レベルでサウンドが有効になり、ハードウェアのサウンドがオンになりました(テストのためだけに)... WTF:しかし何も起こりません(そして仮定が間違っていることが証明されました;-)

デバッグセッション(私はそれが嫌いです...しかし時々...)は、audioActionの実行が起こらないことが判明しました。ここに関連するメソッドがあります:

static void playSound(JComponent c, Object actionKey) {
    LookAndFeel laf = UIManager.getLookAndFeel();
    if (laf instanceof BasicLookAndFeel) {
        ActionMap map = c.getActionMap();
        if (map != null) {
            Action audioAction = map.get(actionKey);
            if (audioAction != null) {
                // pass off firing the Action to a utility method
                // JW: we have an audioAction, so on to the next method
                ((BasicLookAndFeel)laf).playSound(audioAction);
            }
        }
    }
}

protected void playSound(Action audioAction) {
    if (audioAction != null) {
        Object[] audioStrings = (Object[])
                                UIManager.get("AuditoryCues.playList");
        if (audioStrings != null) {
           // JW: here the action is performed ... except we don't reach this
           ....
        }

}

それはかなり驚くべきことですね。結局のところ、アクションが作成されたので、プレイリストがない場合、なぜ作成されたのでしょうか?

そして、ここに問題があります。アクションの作成に使用されるリストは別のリストです

// in BasicLookAndFeel
protected ActionMap getAudioActionMap() {
    ActionMap audioActionMap = (ActionMap)UIManager.get(
                                          "AuditoryCues.actionMap");
    if (audioActionMap == null) {
        // here it's named cueList
        Object[] acList = (Object[])UIManager.get("AuditoryCues.cueList");

}

別のリストである理由は... LAFが実際に再生されるサウンドをカスタマイズできるようにするためです

// BasicLookAndFeel
// *** Auditory Feedback
"AuditoryCues.cueList", allAuditoryCues,
// this key defines which of the various cues to render.
// L&Fs that want auditory feedback NEED to override playList.
"AuditoryCues.playList", null,

Ooookaaayy .. それでは、具体的な LAF が何をしているか見てみましょう。

// *** Auditory Feedback
// this key defines which of the various cues to render
// Overridden from BasicL&F. This L&F should play all sounds
// all the time. The infrastructure decides what to play.
// This is disabled until sound bugs can be resolved.
"AuditoryCues.playList", null, // table.get("AuditoryCues.cueList"),

EOL。

そうではありません:-) このコメントは、実行可能なことを示唆しています:

Object[] cueList = (Object[]) UIManager.get("AuditoryCues.cueList");
UIManager.put("AuditoryCues.playList", cueList);

実際、これは WindowsLAF では機能しますが (OS サウンド スキーマを尊重し、最も重要なことに、無効にすると再生されません)、他のコア LAF では機能しません。

于 2012-08-28T09:42:33.760 に答える
2

MadProgrammer が提供したリンク (最後に再投稿) を出発点として使用すると、次のことがわかりました。

import java.awt.*;
import javax.swing.JOptionPane;

//retrieve the default sound from windows system sounds
//for another sound replace "default" accordingly
    final Runnable SOUND = (Runnable)Toolkit.getDefaultToolkit().getDesktopProperty
    ("win.sound.default");

そして、JOptionPane を表示する直前:

if(SOUND != null)SOUND.run();

注: Program Error などの一部のサウンド イベントには、この方法ではアクセスできません。アクセス可能なサウンド イベントのリストは、Oracle のWindows デスクトップ プロパティ サポートページのオーディオ フィードバックの見出しの下にあります。

これは Windows 以外の OS ではまったく機能しませんが、ブログによると、別の OS ではプログラムがクラッシュすることはありません。JDKLinux パーティション用の をまだ持っていないため、現在これをテストできません。

于 2012-08-27T01:26:50.297 に答える
2

まず、私はアンドリューに同意します

ただし、ここを見からここを見てください

PS私はこれを自分でテストしていません

于 2012-08-26T08:17:33.477 に答える