java - Java Swing - 显示玻璃窗格并使用事件而不会失去以前的焦点所有者
问题描述
我们正在尝试向用户显示一个乳白色JGlassPane
,以表示由于进度条或当前正在显示的其他内容,当前不接受事件。虽然这通常会自动工作,因为我们正在显示一个模态对话框,我们还希望在JGlassPane
没有 a 的情况下使用JDialog
,这意味着只有 aJGlassPane
和一个等待光标。
到目前为止,我们通过使用JGlassPane
忽略事件并绘制半透明颜色的 a 来做到这一点。最初我们调用requestFocus
. JGlassPane
这样做的问题是,当玻璃板消失时,我们会丢失先前聚焦的组件。解决方案是简单地记住之前关注的组件。但是,在通过菜单调用Action
触发 的 的情况下JGlassPane
,焦点组件是 windows JRootPane
。通常 swing 会在关闭菜单后正确恢复焦点,但是,在这种情况下,我们正在破坏此功能。有没有办法在不破坏焦点行为的情况下实现我们想要的?
在此演示中,您可以看到,在使用两个按钮之一后按 ESC 时正确返回焦点,但不是使用桌面上的上下文菜单。
public class FocusDemo
{
//Temporary static veriable for demo purposes.
private static final AtomicReference<Component> previouslyFocused = new AtomicReference<>();
private static class ConsumingGlassPane extends JPanel
{
public ConsumingGlassPane()
{
setOpaque( false );
setFocusable( true );
addMouseListener( new MouseListener()
{
@Override
public void mouseClicked( @NonNull final MouseEvent e )
{
e.consume();
}
@Override
public void mousePressed( @NonNull final MouseEvent e )
{
e.consume();
}
@Override
public void mouseReleased( @NonNull final MouseEvent e )
{
e.consume();
}
@Override
public void mouseEntered( @NonNull final MouseEvent e )
{
e.consume();
}
@Override
public void mouseExited( @NonNull final MouseEvent e )
{
e.consume();
}
} );
addKeyListener( new KeyListener()
{
@Override
public void keyTyped( final KeyEvent e )
{
e.consume();
}
@Override
public void keyReleased( final KeyEvent e )
{
e.consume();
}
@Override
public void keyPressed( final KeyEvent e )
{
if ( e.getKeyCode() == KeyEvent.VK_ESCAPE )
{
setVisible( false );
final Component component = previouslyFocused.get();
if ( component != null )
{
component.requestFocusInWindow();
}
}
e.consume();
}
} );
// This component keeps the focus until is made hidden
setInputVerifier( new InputVerifier()
{
@Override
public boolean verify( final JComponent input )
{
return !isVisible();
}
} );
}
@Override
protected void paintComponent( final Graphics g )
{
final Graphics2D g2 = (Graphics2D) g.create();
g2.setColor( new Color( 240, 230, 230, 128 ) );
g2.fillRect( 0, 0, getWidth(), getHeight() );
g2.dispose();
}
}
public static void main( final String[] args )
{
final JFrame frame = new JFrame();
frame.setGlassPane( new ConsumingGlassPane() );
final ActionListener showglasspane = __ ->
{
previouslyFocused.set( frame.getFocusOwner() );
frame.getRootPane().getGlassPane().setVisible( true );
frame.getRootPane().getGlassPane().requestFocus();
};
final JButton button1 = new JButton( "Show GlassPane" );
final JButton button2 = new JButton( "Show GlassPane" );
button1.addActionListener( showglasspane );
button2.addActionListener( showglasspane );
final Object[][] objects = { { 1, 2, 3 }, { 1, 2, 3 } };
final String[] col = { "Lel", "Lol", "Lul" };
final JTable table = new JTable( objects, col );
final JMenuItem menuItem = new JMenuItem( "Show GlassPane" );
menuItem.addActionListener( showglasspane );
final JPopupMenu popup = new JPopupMenu();
popup.add( menuItem );
table.setComponentPopupMenu( popup );
frame.setLayout( new GridBagLayout() );
frame.add( button1 );
frame.add( button2 );
frame.add( table );
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
解决方案
推荐阅读
- node.js - 节点js中的SSH命令突然重试
- objective-c - iOS 11 视觉。冻结前只能执行 VNImageBasedRequest 15 次
- javascript - 不允许我在同一个按钮上提交和点击
- ruby-on-rails - Rails - 将搜查结果转换为 xls
- java - 当我尝试通过 javaFX 中的不同场景传递值时,Setter 方法不起作用
- python - 使用特定分隔符将 Pandas 转换为字符串
- java - 如何将jar文件放入html的embed标签中
- android - android XML中的name属性和context属性有什么区别?
- typescript - 指定参数类型为 T | 为空但不为空
- python - 使用 Django 管理员用户表单添加内联用户配置文件表单时出现问题