Java / Swing OS X全屏模式和虚拟桌面

时间:2014-02-03 23:16:31

标签: java macos swing jframe awt

我的Java应用程序使用两个JFrame - 第一个用于从有限数量的选项(无全屏)向用户提供选项,第二个用于显示数据(使用全屏选项)。

我正在使用 setVisible ()在我的两个帧之间切换,这很好,因为它重用了以前的虚拟桌面并保留了全屏模式,但我不得不切换到 dispose < / strong>()以便隐藏第二个JFrame,原因是toolkit thread paint problem

当我在第2帧进入全屏模式时,会创建一个新的虚拟桌面 - 但是如果我处理了frame2,那么该VD仍然是一个空的灰色桌面。已经处置()它返回到frame1,如果我再次切换回frame2我们不再全屏...如果我这样做...那么我现在有2个虚拟桌面。等等。

在frame2上使用 setVisible(false)也会留下空的虚拟桌面,虽然这比重绘/缓冲问题少,因为下次我 setVisible(在frame2上至少它在同一个VD中打开,如上所述。

我的问题是:我可以在 dispose()之后使用相同的VD保存和恢复第2帧中的全屏模式,还是我至少可以强制VD关闭?或者我错过了另一个问题的解决方案?或者这只是因为我不严格遵循Apple的全屏指南?!

提前感谢您的帮助。

更新:我回去使用 setVisible (false)来隐藏frame2,但每次显示时都使用 new ()避免重绘/缓冲问题),我再次遇到重复的VD问题。我还实施了 com.apple.eawt.Application.requestToggleFullScreen 以及 com.apple.eawt.FullScreenListener 以在我处置之前退出全屏,但应用程序挂起。现在看起来我将不得不忍受repaint.buffer问题,以允许全屏切换正常工作。

SSCCE:

import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SwingFramesFullScreenMacDemo extends javax.swing.JFrame {

    JFrame secondFrame;
    JPanel myPanel;

    public SwingFramesFullScreenMacDemo() {

        //Setup UI With Button to show secondFrame
        JPanel thisPanel = new JPanel();
        JButton jbtOpenFullScreenFrame = new JButton("Open Full Screen Frame");
        jbtOpenFullScreenFrame.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                secondFrame.setVisible(true);
                setVisible(false);
            }
        });

        thisPanel.add(jbtOpenFullScreenFrame);
        this.add(thisPanel);
        this.pack();

        // Setup Second Frame With Full Screen Support
        secondFrame = new JFrame();

        myPanel = new JPanel();

        //Dispose() works without residual image, but leaves open virtual desktop for each time
        //you go to full screen then dispose
        JButton jbtDispose = new JButton("Dispose");

        jbtDispose.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                setVisible(true);
                secondFrame.dispose();

            }
        });

        //SetVisible(false) gives residual image on reopening second frame despite clearing colour
        //works well for fullscreen, only one virtual desktop open for lifetime of app
        JButton jbtSetVisibleFalse = new JButton("Set Visible to False");

        jbtSetVisibleFalse.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                secondFrame.setVisible(false);
                setVisible(true);

            }
        });

        myPanel.add(jbtDispose);
        myPanel.add(jbtSetVisibleFalse);

        secondFrame.add(myPanel);
        secondFrame.pack();

        enableFullScreenMode(secondFrame);

        secondFrame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosed(WindowEvent e) {
                setVisible(true);
                secondFrame.setVisible(false);

            }
        });

    }

    public static void enableFullScreenMode(Window window) {

        String methodName = "setWindowCanFullScreen";

        try {
            Class<?> clazz = Class.forName(com.apple.eawt.FullScreenUtilities.class.getName());
            Method method = clazz.getMethod(methodName, new Class<?>[]{
                Window.class, boolean.class});
            method.invoke(null, window, true);
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException t) {
            System.err.println("Full screen mode is not supported");
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                javax.swing.JFrame fullScreenMacProblem = new SwingFramesFullScreenMacDemo();
                fullScreenMacProblem.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {

                        System.exit(0);
                    }
                });

                fullScreenMacProblem.setVisible(true);

            }
        });

    }

}

1 个答案:

答案 0 :(得分:0)

我对这个“catch 22”的解决方案是只在frame1中实例化一次frame2,在frame2不是全屏时使用dispose()(避免重绘/缓冲问题),并在frame2全屏时使用setVisible(false) (为frame2维护一个虚拟桌面)。由于重绘问题不影响全屏视图,因此效果非常好,尽管我确信纯粹主义者会阻挠!