从 4k 显示器拖到全高清显示器时,应用程序变黑
Application turns black when dragged from a 4k monitor to a FullHD monitor
我的笔记本有 4k 显示屏。我的外接显示器是 1920。当我将我的 Java Swing 应用程序 window 从 4k 显示器拖到外接显示器上时,除了 window 帧外,它变得全黑。我在外接显示器上最大化不最大化都无所谓
这是我从 Oracle.com 得到的 HelloWorldSwing
示例。它显示了完全相同的行为。
import javax.swing.*;
public class HelloWorldSwing {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
这看起来像是 Swing 中的一个错误。反正我得找个solution/work-around。有什么想法吗?
我是 运行 jdk/jre 1.8.0 121.
虽然我在目前为止尝试使用 Swing 的任何 multi-screen 环境中都没有遇到这样的问题 - 我可能会帮助调试它。
尝试 运行使用此代码示例:
public class HelloWorldSwing
{
private static void createAndShowGUI ( final GraphicsDevice device )
{
final GraphicsConfiguration conf = device.getDefaultConfiguration ();
final JFrame frame = new JFrame ( "HelloWorldSwing", conf );
frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
final JLabel label = new JLabel ( "Hello World", SwingConstants.CENTER );
frame.getContentPane ().add ( label );
final Rectangle sb = conf.getBounds ();
frame.setBounds ( sb.x + sb.width / 2 - 100, sb.y + sb.height / 2 - 100, 200, 200 );
frame.setVisible ( true );
}
public static void main ( final String[] args )
{
SwingUtilities.invokeLater ( new Runnable ()
{
@Override
public void run ()
{
final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
final GraphicsDevice[] devices = env.getScreenDevices ();
for ( final GraphicsDevice device : devices )
{
if ( device.getType () == GraphicsDevice.TYPE_RASTER_SCREEN )
{
createAndShowGUI ( device );
}
}
}
} );
}
}
这基本上会在您系统中可用的每个屏幕设备上放置一个框架。它还将为每个帧提供默认屏幕图形配置。
看看你拖拽frame到笔记本屏幕是否有同样的问题,是否还有其他问题。
Edit1: 此外,了解您使用的 JDK/JRE 对 运行 您的代码示例可能非常重要,因为有一些相关的内部更改.如果您运行正在使用一些旧的JDK,那么在较新的Mac OS X 版本上可能不是最好的主意。
Edit2: 我会尝试做更多的事情来了解更多:
在显示框架之前设置 Nimbus Look and Feel 并尝试在安装了自定义 L&F 的情况下拖动它们。
设置系统(本机)外观和感觉为 shown in the tutorial here - 这可能对 Mac OS X 有一些影响。
尝试 运行 Java FX example 并在显示器之间拖动它,看看你是否在那里遇到同样的问题 - 你已经在使用 JDK 8 所以它应该很容易做到。 Java FX 只是不久前推出的新 UI 框架。
总的来说,我可以说 Swing 对 high-res 显示器的支持很差,所以即使 运行 一切正常并且您没有黑屏,您也会看到其他问题例如 UI 模糊或 low-quality 文本渲染。
我找到了解决办法。基本上我在我的主框架上添加了一个组件监听器并监听移动事件。每当框架移动时,我都会检查它位于哪个显示器上。将框架移动到另一个显示器后,我将其设置为不可见,然后在 "new" 显示器上设置新边界,将扩展状态设置为最大化,最后再次使框架可见。
在最后几分钟,我疯狂地将 windows 从一个显示器拖到另一个显示器,同时高兴得跳了起来。如果你也想要生活中的乐趣,这里是代码:
mainFrame.addComponentListener(new ComponentListener()
{
@Override
public void componentMoved(ComponentEvent evt)
{
GraphicsConfiguration conf = mainFrame.getGraphicsConfiguration();
GraphicsDevice curDisplay = conf.getDevice();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allDisplays = env.getScreenDevices();
for (int i = 0; i < allDisplays.length; i++)
{
if (allDisplays[i].equals(curDisplay))
{
//the window has been dragged to another display
if (i != _currentDisplayIndex)
{
final Rectangle sb = conf.getBounds();
mainFrame.setVisible(false);
//it is important to set the bounds somewhere on the new display before setting the extended state to maximized
mainFrame.setBounds(sb.x, sb.y, 1000, 800);
mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
mainFrame.setVisible(true);
_currentDisplayIndex = i;
}
}
}
}
@Override
public void componentShown(ComponentEvent evt)
{
}
@Override
public void componentResized(ComponentEvent evt)
{
}
@Override
public void componentHidden(ComponentEvent evt)
{
}
});
耶皮!
旁注:我之前尝试截取黑色 window 的屏幕截图。但是,屏幕截图不是黑色的,而是正常显示所有 swing 组件。这让我相信,这不仅是挥杆问题,而且还是某种 windows/display 驱动程序问题。按 "printscreen" 不会触发 java 中的任何内容(我猜),但只会刷新显示。
我的笔记本有 4k 显示屏。我的外接显示器是 1920。当我将我的 Java Swing 应用程序 window 从 4k 显示器拖到外接显示器上时,除了 window 帧外,它变得全黑。我在外接显示器上最大化不最大化都无所谓
这是我从 Oracle.com 得到的 HelloWorldSwing
示例。它显示了完全相同的行为。
import javax.swing.*;
public class HelloWorldSwing {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
这看起来像是 Swing 中的一个错误。反正我得找个solution/work-around。有什么想法吗?
我是 运行 jdk/jre 1.8.0 121.
虽然我在目前为止尝试使用 Swing 的任何 multi-screen 环境中都没有遇到这样的问题 - 我可能会帮助调试它。
尝试 运行使用此代码示例:
public class HelloWorldSwing
{
private static void createAndShowGUI ( final GraphicsDevice device )
{
final GraphicsConfiguration conf = device.getDefaultConfiguration ();
final JFrame frame = new JFrame ( "HelloWorldSwing", conf );
frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
final JLabel label = new JLabel ( "Hello World", SwingConstants.CENTER );
frame.getContentPane ().add ( label );
final Rectangle sb = conf.getBounds ();
frame.setBounds ( sb.x + sb.width / 2 - 100, sb.y + sb.height / 2 - 100, 200, 200 );
frame.setVisible ( true );
}
public static void main ( final String[] args )
{
SwingUtilities.invokeLater ( new Runnable ()
{
@Override
public void run ()
{
final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
final GraphicsDevice[] devices = env.getScreenDevices ();
for ( final GraphicsDevice device : devices )
{
if ( device.getType () == GraphicsDevice.TYPE_RASTER_SCREEN )
{
createAndShowGUI ( device );
}
}
}
} );
}
}
这基本上会在您系统中可用的每个屏幕设备上放置一个框架。它还将为每个帧提供默认屏幕图形配置。
看看你拖拽frame到笔记本屏幕是否有同样的问题,是否还有其他问题。
Edit1: 此外,了解您使用的 JDK/JRE 对 运行 您的代码示例可能非常重要,因为有一些相关的内部更改.如果您运行正在使用一些旧的JDK,那么在较新的Mac OS X 版本上可能不是最好的主意。
Edit2: 我会尝试做更多的事情来了解更多:
在显示框架之前设置 Nimbus Look and Feel 并尝试在安装了自定义 L&F 的情况下拖动它们。
设置系统(本机)外观和感觉为 shown in the tutorial here - 这可能对 Mac OS X 有一些影响。
尝试 运行 Java FX example 并在显示器之间拖动它,看看你是否在那里遇到同样的问题 - 你已经在使用 JDK 8 所以它应该很容易做到。 Java FX 只是不久前推出的新 UI 框架。
总的来说,我可以说 Swing 对 high-res 显示器的支持很差,所以即使 运行 一切正常并且您没有黑屏,您也会看到其他问题例如 UI 模糊或 low-quality 文本渲染。
我找到了解决办法。基本上我在我的主框架上添加了一个组件监听器并监听移动事件。每当框架移动时,我都会检查它位于哪个显示器上。将框架移动到另一个显示器后,我将其设置为不可见,然后在 "new" 显示器上设置新边界,将扩展状态设置为最大化,最后再次使框架可见。
在最后几分钟,我疯狂地将 windows 从一个显示器拖到另一个显示器,同时高兴得跳了起来。如果你也想要生活中的乐趣,这里是代码:
mainFrame.addComponentListener(new ComponentListener()
{
@Override
public void componentMoved(ComponentEvent evt)
{
GraphicsConfiguration conf = mainFrame.getGraphicsConfiguration();
GraphicsDevice curDisplay = conf.getDevice();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allDisplays = env.getScreenDevices();
for (int i = 0; i < allDisplays.length; i++)
{
if (allDisplays[i].equals(curDisplay))
{
//the window has been dragged to another display
if (i != _currentDisplayIndex)
{
final Rectangle sb = conf.getBounds();
mainFrame.setVisible(false);
//it is important to set the bounds somewhere on the new display before setting the extended state to maximized
mainFrame.setBounds(sb.x, sb.y, 1000, 800);
mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
mainFrame.setVisible(true);
_currentDisplayIndex = i;
}
}
}
}
@Override
public void componentShown(ComponentEvent evt)
{
}
@Override
public void componentResized(ComponentEvent evt)
{
}
@Override
public void componentHidden(ComponentEvent evt)
{
}
});
耶皮!
旁注:我之前尝试截取黑色 window 的屏幕截图。但是,屏幕截图不是黑色的,而是正常显示所有 swing 组件。这让我相信,这不仅是挥杆问题,而且还是某种 windows/display 驱动程序问题。按 "printscreen" 不会触发 java 中的任何内容(我猜),但只会刷新显示。