Если я минимизирую JFrame
, который был привязан к левому краю экрана слева от экрана, нажав кнопку "Свернуть" окна WindowDecoration и исключив его с помощью Alt-Tabbing или щелкнув по нему в панели задач Windows, восстановлен правильно отрезан влево. Хорошо!
Но если я скрою кадр на
setExtendedState( getExtendedState() | Frame.ICONIFIED );
и просмотрите предварительный просмотр, наведя указатель мыши на панель задач Windows, она показывает фрейм неправильно. После unminimizing его Alt-Tabbing или щелкая его в Windows TaskBar, кадр восстанавливается в этом неправильном положении и размере. Фрейм-границы - это "нераскрытые" значения, которые Windows обычно запоминает для восстановления, если вы перетащите кадр из ScreenBorder.
Экранная запись ошибки:
Мой вывод состоит в том, что 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 Frames работать вместе?
Edit:
Я зарегистрировал ошибку в Oracle: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8147840