我想阻止对窗口的输入,但仍然可以移动它。
如果有一个模态对话框类型允许生成它的窗口移动,那么我会很高兴。
假设我有一个窗口可以打开另一个窗口。然后第二个窗口打开一个模式对话框,它阻止输入到其他两个窗口(很好),但也将这两个窗口锁定在适当的位置(为什么 - Amigas 没有这样做:)?)。
我的问题是我可能需要在第一个窗口中直观地阅读一些内容以在对话框中使用,但这可能是不可能的,因为第二个窗口被锁定到位,覆盖了它。
我想我几乎用玻璃板解决了这个问题。我将下面的类设置为窗口根窗格的玻璃窗格,然后在我想要阻止时调用 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);
}
}
谢谢!