显示glasspane并使用事件而不丢失以前的焦点所有者

h9vpoimq  于 2021-06-26  发布在  Java
关注(0)|答案(0)|浏览(213)

我们正试图向用户展示 JGlassPane 表示由于当前显示的进度条或其他内容而当前不接受事件。虽然这通常会自动工作,因为我们显示了一个模态对话框,我们还希望 JGlassPane 不需要一个 JDialog ,意思是只是 JGlassPane 和一个等待的光标。
到目前为止,我们通过使用 JGlassPane 它忽略了事件并描绘出半透明的颜色。最初我们叫 requestFocusJGlassPane . 问题是,当玻璃板消失时,我们失去了先前聚焦的组件。解决这个问题的方法是简单地记住先前关注的组件。但是,如果 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 );
  }
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题