未修饰的JFrame最大化始终使用OS X中的主监视器分辨率

时间:2015-04-09 12:03:58

标签: java macos swing

在OS X中辅助(或任何非主要)监视器上最大化未修饰帧时出现问题。似乎在第二台监视器上最大化帧时,使用主监视器的边界并且帧大小超出屏幕范围(如果主监视器更大)或者它没有填满整个屏幕(如果主监视器更小)。

OS X Yosemite中的Java 1.8.0_40出现问题。在Windows和Linux中测试时没有出现此问题。

运行应用程序时,它看起来像这样。添加了数字网格,以便能够查看框架是否超出屏幕边界。

Maximize Test

以下是代码:

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MaximizeTest extends JFrame {

    public static void main(String[] args) {
        MaximizeTest frame = new MaximizeTest();
        frame.dispose();
        frame.setUndecorated(true);
        frame.pack();
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private final JPanel mainPanel = new NumberGridPanel();
    private final JButton maximizeButton = new JButton();
    private final JButton closeButton = new JButton();

    public MaximizeTest() {
        initComponents();

        // Added this to be able to drag the frame to other monitors
        MouseAdapter mouseAdapter = new DragMouseAdapter();
        addMouseListener(mouseAdapter);
        addMouseMotionListener(mouseAdapter);
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        maximizeButton.setCursor(Cursor.getDefaultCursor());
        closeButton.setCursor(Cursor.getDefaultCursor());
    }

    private void initComponents() {
        GridBagConstraints gridBagConstraints;

        mainPanel.setLayout(new GridBagLayout());

        maximizeButton.setText("Maximize/Minimize");
        maximizeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                int state = getExtendedState();
                if ((state & Frame.MAXIMIZED_BOTH) != 0) {
                    setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
                    setSize(400, 400);
                } else {
                    // Take OS taskbars and dockbars into account
                    Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
                    if (screenInsets.left == 0 && screenInsets.right == 0
                            && screenInsets.top == 0 && screenInsets.bottom == 0) {
                        setMaximizedBounds(null);
                    } else {
                        Rectangle screenBounds = getGraphicsConfiguration().getBounds();
                        Rectangle newBounds = new Rectangle(
                                screenInsets.left,
                                screenInsets.top,
                                screenBounds.width - (screenInsets.left + screenInsets.right),
                                screenBounds.height - (screenInsets.top + screenInsets.bottom));
                        setMaximizedBounds(newBounds);
                    }

                    setExtendedState(state | Frame.MAXIMIZED_BOTH);
                }
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_END;
        mainPanel.add(maximizeButton, gridBagConstraints);

        closeButton.setText("Close");
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                System.exit(0);
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        mainPanel.add(closeButton, gridBagConstraints);

        getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER);
    }

    private static class NumberGridPanel extends JPanel {

        @Override
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLUE);
            int gridSize = 30;
            int cols = getWidth() / gridSize;
            int rows = getHeight() / gridSize;
            for (int col = 0; col < cols; col++) {
                for (int row = 0; row < rows; row++) {
                    g.drawString(Integer.toString((col + row) * gridSize), col * gridSize, row * gridSize + 10);
                }
            }
        }
    }

    private class DragMouseAdapter extends MouseAdapter {

        private int previousMouseX;
        private int previousMouseY;

        @Override
        public void mousePressed(MouseEvent e) {
            previousMouseX = e.getXOnScreen();
            previousMouseY = e.getYOnScreen();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            int state = getExtendedState();
            if ((state & Frame.MAXIMIZED_BOTH) == 0) { // if not maximized
                setLocation(
                        e.getXOnScreen() - previousMouseX + getX(), 
                        e.getYOnScreen() - previousMouseY + getY());
                previousMouseX = e.getXOnScreen();
                previousMouseY = e.getYOnScreen();
            }
        }
    }
}

到目前为止,我还未能在网上找到有关此问题的任何内容。如果有人能帮我解决这个问题,或者指出我正确的方向,我将不胜感激。提前谢谢。

编辑:

经过进一步调查后,似乎不是主屏幕的分辨率影响第二屏幕上的最大化区域,而是两个屏幕的虚拟排列的y偏移。如果主屏幕低于虚拟排列中的辅助屏幕,则在最大化帧时,辅助屏幕顶部会出现间隙。

此外,在更改主屏幕的分辨率后,问题完全消失,即使将分辨率更改回原来的状态,甚至在完成操作系统重启后,我也无法再次重现。

0 个答案:

没有答案