gpt4 book ai didi

java - 这是向 Java Frame 教授有关 Windows 的 Aero Snap 功能的唯一方法吗?

转载 作者:IT老高 更新时间:2023-10-28 21:13:14 29 4
gpt4 key购买 nike

如果我通过单击 Windows WindowDecoration 的最小化按钮来最小化被 Aero 捕捉到屏幕左侧的 JFrame 并通过 Alt-Tabbing 或在 Windows 中单击它来取消最小化任务栏,框架被正确地恢复到左侧。好!

但是如果我将框架最小化

setExtendedState( getExtendedState() | Frame.ICONIFIED );

并通过将鼠标悬停在 Windows 任务栏上来查看预览,它显示框架的位置错误。通过 Alt-Tabbing 取消最小化它或在 Windows 任务栏中单击它后,框架将恢复到错误的位置和大小。框架边界是“未对齐”值,如果您将框架拖离 ScreenBorder,Windows 通常会记住恢复该值。

Bug 的屏幕录像:

enter image description here

我的结论是,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

最佳答案

Is there a better way to let AeroSnap and Java Frames work together?

也好不了多少。直接设置扩展状态会绕过操作系统的设置处理。

如果你看一下JFrame#setExtendedState的源代码,你会发现它调用了FramePeersetState方法。 FramePeer 接口(interface)的 JDK 的 JFrame 实现是 WFramePeer 类,它将其 setState 方法声明为 native 。因此,在 Oracle 对此采取措施或您使用 native 代码(见下文)之前,您很不走运。

幸运的是,您不必对事件监听器和缓存边界发疯。隐藏和显示框架足以将大小“重置”为最小化之前的大小:

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));
}
}

虽然这确实有一个副作用,即不提供框架内容的详细预览:

enter image description here

使用 native 代码的解决方案

如果您愿意使用 JNA ,那么就可以完全模仿原生平台的最小化了。您需要在构建路径中包含 jna.jarjna-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 实例已加载。您可以在启动时加载它以避免这种首次延迟。

归功于 the accepted answer here .

关于java - 这是向 Java Frame 教授有关 Windows 的 Aero Snap 功能的唯一方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34638183/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com