3

ウィンドウへの入力をブロックしたいが、それでも移動できるようにしたい。

それを生成したウィンドウを移動できるモーダル ダイアログ タイプがあれば、私は満足です。

別のウィンドウを開くウィンドウがあるとします。次に、この 2 番目のウィンドウがモーダル ダイアログを開き、他の 2 つのウィンドウへの入力をブロックします (問題ありません) が、これら 2 つのウィンドウを所定の位置にロックします (なぜ - Amigas はこれを行わなかったのですか :) ?)。

私の問題は、ダイアログで使用するために最初のウィンドウで何かを視覚的に読み取る必要がある場合があることですが、2番目のウィンドウが所定の位置にロックされており、それを覆っているため、これは不可能な場合があります。

私はこれをガラス板でほぼ解決したと思います。以下のクラスをウィンドウのルート ペインのガラス ペインに設定し、ブロックするときは setVisible(true) を呼び出し、ウィンドウのロックを解除するときは setVisible(false) を呼び出します。ロックすると、ウィンドウが灰色になり、これを示します。

ウィンドウを閉じる以外はマウス入力がブロックされますが、今のところは問題ありません。問題は、ブロックされたウィンドウのコンポーネントをタブで移動でき、編集可能なウィンドウに到達した場合は、キーボードで編集できることです。空の KeyListener。

ガラス ペインの背後にあるコンポーネントがフォーカスされないようにする簡単な方法はありますか?

「InputSink」クラス自体で実行できることを願っています。

独自の利己的なフォーカス トラバーサル ポリシーを追加し、フォーカスが表示されたときにフォーカスを要求しようとしましたが、これは効果がありません。

また、FocusListener が追加された場所で見つかった例を試してみました。その focusLost メソッドは、ガラス ペインが表示されている場合にフォーカスを要求しますが、ウィンドウが常に前面にあるため、やり過ぎです。

これらの両極端の間の解決策を知っている人はいますか? これは私が持っているものです:

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;

import javax.swing.JPanel;


public class InputSink extends JPanel {


public InputSink() {
    this(0.2f); //Default opacity.
}
public InputSink(float alpha) {
    setOpaque(false);
    setBackground(new Color(0, 0, 0, alpha)); //Just store it here.
    addMouseListener(new MouseAdapter() {});
    addKeyListener(new KeyAdapter() {});
    setFocusTraversalPolicy(new FocusTraversalPolicy() {
        @Override
        public Component getLastComponent(Container aContainer) {
            return InputSink.this;
        }
        @Override
        public Component getFirstComponent(Container aContainer) {
            return InputSink.this;
        }
        @Override
        public Component getDefaultComponent(Container aContainer) {
            return InputSink.this;
        }
        @Override
        public Component getComponentBefore(Container aContainer, Component aComponent) {
            return InputSink.this;
        }
        @Override
        public Component getComponentAfter(Container aContainer, Component aComponent) {
            return InputSink.this;
        }
    });
}

public void paintComponent(final Graphics gfx) { //Handle grey-out.
    gfx.setColor(getBackground());
    Rectangle rect = gfx.getClipBounds();
    gfx.fillRect(rect.x, rect.y, rect.width, rect.height);
}


@Override
public void setVisible(boolean visible) {
    super.setVisible(visible);
    if (visible)
        requestFocus();
}

}

したがって、Guillaume Polet の提案に従って使用したバージョンは

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class InputSink extends JPanel {

KeyEventDispatcher blockingDispatcher = new KeyEventDispatcher() {
    @Override
    public boolean dispatchKeyEvent(KeyEvent e) {
        return InputSink.this == ((JFrame) SwingUtilities.getWindowAncestor((Component) e.getSource())).getGlassPane(); //Consume!
    }
};

public InputSink) {
    this(0.2f); //Default opacity.
}
public InputSinkfloat alpha) {
    setOpaque(false);
    setBackground(new Color(0, 0, 0, alpha)); //Just store it here.
    addMouseListener(new MouseAdapter() {});
    addKeyListener(new KeyAdapter() {});
}

public void paintComponent(final Graphics gfx) { //Handle grey-out.
    gfx.setColor(getBackground());
    Rectangle rect = gfx.getClipBounds();
    gfx.fillRect(rect.x, rect.y, rect.width, rect.height);
}

@Override
public void setVisible(boolean visible) {
    super.setVisible(visible);
    if (visible)
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(blockingDispatcher);
    else
        KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(blockingDispatcher);
}

}

ありがとうございました!

4

2 に答える 2

2

に を追加しKeyEventDispatcherて、KeyboardFocusManagerキーボード入力をブロックできます。

以下の小さなデモ:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestGlassPane {

    private static final int COUNTDOWN = 10;

    private static final String CLICK_ME = "Click me";

    private static final Color GRAY = new Color(192, 192, 192, 128);

    private JFrame frame;

    private JButton button;

    private Timer timer;

    private int countdown;

    private KeyEventDispatcher blockingDispatcher;

    private static class GrayPanel extends JComponent {
        @Override
        protected void paintComponent(Graphics g) {
            g.setColor(GRAY);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }

    public TestGlassPane() {
        blockingDispatcher = new KeyEventDispatcher() {

            @Override
            public boolean dispatchKeyEvent(KeyEvent e) {
                return true;
            }
        };

    }

    protected void initUI() {
        frame = new JFrame(TestGlassPane.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        button = new JButton(CLICK_ME);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                blockUserInput();
            }
        });
        GrayPanel glassPane = new GrayPanel();
        glassPane.addMouseListener(new MouseAdapter() {
        });
        frame.setGlassPane(glassPane);
        frame.add(button);
        frame.setSize(200, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    protected void blockUserInput() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(blockingDispatcher);
        frame.getGlassPane().setVisible(true);
        countdown = COUNTDOWN;
        timer = new Timer(1000, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                countdown--;
                if (countdown == 0) {
                    timer.stop();
                    frame.getGlassPane().setVisible(false);
                    button.setText(CLICK_ME);
                    KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(blockingDispatcher);
                } else {
                    button.setText("We will be back in " + countdown + " seconds");
                }
            }
        });
        timer.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestGlassPane().initUI();
            }
        });
    }

}

通常、ボタンはSpaceキーでアクティブにできますが、実際にはブロックされていることがわかります。

于 2013-01-17T15:07:17.753 に答える
0

2番目のウィンドウが所定の位置にロックされているため

JDialog は、私にとって (Windows を使用して) 常に「移動可能」でした。

入力をブロックする別の可能性:

非モーダルダイアログを表示するときは、この行を含めてください

frame.setEnabled(false);

ダイアログにwindowListenerも追加して、閉じるときに

frame.setEnabled(true);

Windows では問題なく動作するようですが、その他のプラットフォームは不明です

于 2013-01-18T00:53:20.197 に答える