28

JFrameWindows WindowDecoration の最小化ボタンをクリックして画面の左側に Aero スナップされた を最小化し、Alt-Tab キーを押して最小化を解除するか、Windows タスクバーでクリックすると、フレームが左に正しくスナップされて復元されます. 良い!

しかし、フレームを最小化すると

setExtendedState( getExtendedState() | Frame.ICONIFIED );

Windows タスクバーにカーソルを合わせてプレビューを確認すると、フレームが間違った位置に表示されます。Alt-Tab キーを押して最小化を解除するか、Windows タスクバーでフレームをクリックすると、フレームがこの間違った位置とサイズに復元されます。フレーム境界は、「スナップされていない」値であり、フレームを ScreenBorder からドラッグした場合に Windows が通常復元することを記憶しています。

バグの画面記録:

ここに画像の説明を入力

私の結論は、Java は AeroSnap を認識しておらず、Windows に間違った境界を提供しているということです。(たとえば、Toolkit.getDefaultToolkit().isFrameStateSupported( Frame.MAXIMIZED_VERT ) );false を返します。)

これはバグに対する私の修正です:

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionListener;

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

/**
 * Fix for the "Frame does not know the AeroSnap feature of Windows"-Bug.
 *
 * @author bobndrew 20160106
 */
public class SwingFrameStateWindowsAeroSnapBug extends JFrame
{
  Point     location = null;
  Dimension size     = null;


  public SwingFrameStateWindowsAeroSnapBug( final String title )
  {
    super( title );
    initUI();
  }

  private void initUI()
  {
    setDefaultCloseOperation( EXIT_ON_CLOSE );
    setLayout( new FlowLayout() );
    final JButton minimize = new JButton( "Minimize" );
    final JButton maximize = new JButton( "Maximize" );
    final JButton normal = new JButton( "Normal" );
    add( normal );
    add( minimize );
    add( maximize );
    pack();
    setSize( 200, 200 );


    final ActionListener listener = actionEvent ->
    {
      if ( actionEvent.getSource() == normal )
      {
        setExtendedState( Frame.NORMAL );
      }
      else if ( actionEvent.getSource() == minimize )
      {
        //Size and Location have to be saved here, before the minimizing of an AeroSnapped WindowsWindow leads to wrong values:
        location = getLocation();
        size = getSize();
        System.out.println( "saving location (before iconify) " + size + " and " + location );

        setExtendedState( getExtendedState() | Frame.ICONIFIED );//used "getExtendedState() |" to preserve the MAXIMIZED_BOTH state

        //does not fix the bug; needs a Window-Drag after DeMinimzing before the size is applied:
        //          setSize( size );
        //          setLocation( location );
      }
      else if ( actionEvent.getSource() == maximize )
      {
        setExtendedState( getExtendedState() | Frame.MAXIMIZED_BOTH );
      }
    };

    minimize.addActionListener( listener );
    maximize.addActionListener( listener );
    normal.addActionListener( listener );

    addWindowStateListener( windowEvent ->
    {
      System.out.println( "oldState=" + windowEvent.getOldState() + "  newState=" + windowEvent.getNewState() );

      if ( size != null && location != null )
      {
        if ( windowEvent.getOldState() == Frame.ICONIFIED )
        {
          System.out.println( "Fixing (possibly) wrong size and location on de-iconifying to " + size + " and " + location + "\n" );
          setSize( size );
          setLocation( location );

          //Size and Location should only be applied once. Set NULL to avoid a wrong DeMinimizing of a following Windows-Decoration-Button-Minimize!
          size = null;
          location = null;
        }
        else if ( windowEvent.getOldState() == (Frame.ICONIFIED | Frame.MAXIMIZED_BOTH) )
        {
          System.out.println( "Set size and location to NULL (old values: " + size + " and " + location + ")" );
          //Size and Location does not have to be applied, Java can handle the MAXIMIZED_BOTH state. Set NULL to avoid a wrong DeMinimizing of a following Windows-Decoration-Button-Minimize!
          size = null;
          location = null;
        }
      }

    } );
  }


  public static void main( final String[] args )
  {
    SwingUtilities.invokeLater( new Runnable()
    {
      @Override
      public void run()
      {
        new SwingFrameStateWindowsAeroSnapBug( "AeroSnap and the Frame State" ).setVisible( true );
      }
    } );
  }
}

これは、Windows7 ではすべての状況で機能するように見えますが、ウィンドウ管理をいじりすぎているように感じます。そして、何らかの理由でLinuxまたはMacOSでこれをテストすることを避けました;-)

AeroSnap と Java フレームを連携させるためのより良い方法はありますか?


編集:

Oracle にバグを報告しました: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8147840

4

2 に答える 2

0

これは Swing のバグのようです。バグ データベースのバグ レポート:

JDK-7029238 : フォームがスナップされたときに componentResized が呼び出されない

このレポートではバグを再現できませんでした。同じバグに遭遇した場合 (同じか、少なくとも関連していると思います)、このレポートを再度開く良い機会かもしれません。(これに関する他の参照は見つからなかったので、修正されていないと思います)

于 2016-01-11T13:10:10.650 に答える