Wenn ich eine JFrame
minimieren, die Aero-Snap wurde auf der linken Seite des Bildschirms durch Klicken auf die Minimieren-Schaltfläche der Windows WindowDecoration und unminimize es durch Alt-Tabbing oder klicken Sie auf es in der Windows-Taskleiste, wird der Rahmen ordnungsgemäß wiederhergestellt wiederhergestellt nach links. Gut!Ist dies die einzige Möglichkeit, einen Java-Frame etwas über die Aero Snap-Funktion von Windows beizubringen?
Aber wenn ich von
setExtendedState(getExtendedState() | Frame.ICONIFIED);
und Blick auf die Vorschau von schwebt über den Windows-Taskleiste den Rahmen minimieren, es zeigt den Rahmen eine falsche Position. Nachdem Sie es mit der Alt-Tab-Taste oder durch Klicken in der Windows-Taskleiste deaktiviert haben, wird der Rahmen an dieser falschen Position und Größe wiederhergestellt. Die Frame-Grenzen sind die "nicht napped" Werte, die Windows normalerweise wiederherstellen kann, wenn Sie den Frame vom ScreenBorder wegziehen.
Eine Bildschirmaufzeichnung des Bug:
Meine Schlussfolgerung ist, dass Java nicht über AeroSnap kennt und liefert die falschen Grenzen auf Windows. (Zum Beispiel Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_VERT));
gibt false zurück.)
Das ist mein Fix für den Fehler:
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);
}
});
}
}
Dies scheint für alle Situationen unter Windows7 zu arbeiten, aber es fühlt sich an wie zu viel Herumspielen mit dem Fenster-Management . Und ich habe es aus irgendeinem Grund vermieden, dies unter Linux oder MacOS zu testen ;-)
Gibt es eine bessere Möglichkeit, AeroSnap und Java Frames zusammenarbeiten zu lassen?
Edit:
ich einen Fehler bei Oracle angemeldet haben: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8147840
Sie sollten dies als JDK-Bug einreichen, wenn es nicht schon da ist. – user1803551
Kleiner Hinweis: Wenn Sie 'JFrame.ICONIFIED' anstelle von' Frame.ICONIFIED' usw. verwenden, können Sie den 'Frame'-Import entfernen. – user1803551
Sieht so aus, als wäre dies in JDK 9 behoben worden (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8037575). – user1803551