[英]Is this the only way to teach a Java Frame something about the Aero Snap feature of Windows?
如果我通过单击Windows WindowDecoration的最小化按钮并通过Alt-Tabbing最小化它或在Windows任务栏中单击它来最小化Aero捕捉到屏幕左侧的JFrame
,框架将恢复正确地捕捉到剩下。 好!
但是,如果我最小化帧
setExtendedState( getExtendedState() | Frame.ICONIFIED );
并通过将鼠标悬停在Windows TaskBar上来查看预览,它会将框架显示错误的位置。 通过Alt-Tabbing取消最小化或在Windows任务栏中单击它后,框架将在此错误的位置和大小恢复。 帧边界是“未绑定”值,如果您将帧拖离ScreenBorder,Windows通常会记住恢复该值。
Bug的屏幕录制:
我的结论是,Java不了解AeroSnap并向Windows提供了错误的界限。 (例如Toolkit.getDefaultToolkit().isFrameStateSupported( Frame.MAXIMIZED_VERT ) );
返回false。)
这是我对bug的修复:
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协同工作?
编辑:
我在Oracle上提交了一个错误: http : //bugs.java.com/bugdatabase/view_bug.do?bug_id=8147840
是否有更好的方法让AeroSnap和Java Frames协同工作?
好多了。 直接设置扩展状态会绕过操作系统设置它的处理。
如果你看一下JFrame#setExtendedState
的源代码,你会看到它调用了FramePeer
的setState
方法。 JDK的FramePeer
接口的JFrame
实现是WFramePeer
类,它将setState
方法声明为native
。 因此,在Oracle对此做一些事情或使用本机代码之前,你运气不好(见下文)。
幸运的是,您不必为事件监听器和缓存边界而疯狂。 隐藏和显示框架足以将大小“重置”为最小化之前的大小:
public class AeroResize extends JFrame {
public AeroResize(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();
minimize.addActionListener(e -> {
setVisible(false);
setExtendedState(getExtendedState() | JFrame.ICONIFIED);
setVisible(true);
// setLocation(getLocationOnScreen()); // Needed only for the preview. See comments section below.
});
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new AeroResize("AeroSnap and the Frame State").setVisible(true));
}
}
虽然这确实有副作用,没有给出框架内容的详细预览:
如果您想使用JNA ,那么您可以完全模仿本机平台的最小化。 您需要在构建路径中包含jna.jar
和jna.jar
jna-platform.jar
。
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
public class AeroResize extends JFrame {
public AeroResize(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();
minimize.addActionListener(e -> {
HWND windowHandle = new HWND(Native.getComponentPointer(AeroResize.this));
User32.INSTANCE.CloseWindow(windowHandle);
});
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new AeroResize("AeroSnap and the Frame State").setVisible(true));
}
}
这是非常自我解释的。 你得到一个指向窗口的指针,并使用本机CloseWindow
(实际上最小化,去图)。 请注意,我编写它的简约方法会在第一次按下按钮时导致一个小延迟,因为User32
实例已加载。 您可以在启动时加载它以避免第一次延迟。
信用证转到这里接受的答案 。
这似乎是一个Swing bug。 关于Bug数据库的错误报告:
JDK-7029238:在捕捉表单时未调用componentResized
在这个报告中,错误无法再现,现在您遇到了相同的错误(我认为它是相同的,或至少相关),也许是重新打开此报告的好时机。 (我没有找到任何其他参考,所以我认为它没有被修复)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.