简体   繁体   English

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

[英]Java/Swing OS X Full Screen Mode and Virtual Desktops

My Java app uses two JFrames - the first one to present a choice to the user from a limited number of options (no full screen), and the second to present the data (with the full screen option). 我的Java应用程序使用两个JFrames-第一个JFrames向用户显示有限数量的选项(无全屏),第二个JFrames显示数据(带全屏选项)。

I was using setVisible () to switch between my two frames which was good because it reused the previous Virtual Desktop and retained the full screen mode, but I had to switch to dispose () in order to hide the second JFrame because of a toolkit thread paint problem . 我正在使用setVisible ()在两个框架之间切换,这很好,因为它重用了以前的虚拟桌面并保留了全屏模式,但是由于工具包线程的原因,我不得不切换到dispose ()以隐藏第二个JFrame。 油漆问题

When I go into full screen mode in frame2, a new virtual desktop is created - but if I dispose frame2, that VD still exists as an empty grey desktop. 当我在frame2中进入全屏模式时,会创建一个新的虚拟桌面-但是,如果我丢弃frame2,则该VD仍将是一个空的灰色桌面。 Having disposed() it to return to frame1, if I then switch back again to frame2 we are no longer in full screen... and if I do... then I now have 2 virtual desktops. 处理完毕()返回到frame1之后,如果我再次切换回frame2,我们将不再处于全屏状态……如果这样做了,那么我现在有2个虚拟桌面。 And so on. 等等。

Using setVisible(false) on frame2 also leaves the empty virtual desktop in place, although that is less of a problem than the repaint/buffer issue, as the next time I setVisible(true) on frame2 at least it opens up in the same VD, as I mentioned above. 在frame2上使用setVisible(false)还将空虚拟桌面留在原处,尽管这比重绘/缓冲区问题要少,因为下次我在frame2上再次使用setVisible(true)时,它至少在同一VD中打开,如上所述。

My question is: can I save and restore the full screen mode in frame2 using the same VD after a dispose() , or can I at least force the VD to close? 我的问题是:可以在dispose()之后使用相同的VD在frame2中保存和还原全屏模式,还是至少可以强制VD关闭? Or have I missed another solution to the problem? 还是我错过了另一种解决方案? Or is this simply because I'm not strict following Apple's full screen guidelines?! 还是因为我不严格遵循Apple的全屏指南?

Thank you in advance for any help. 预先感谢您的任何帮助。

UPDATE : I went back to using setVisible (false) to hide frame2, but using new () each time I display it (to avoid repaint/buffer problem), and again I have the same duplicate VD problem. 更新 :我回到使用setVisible (false)来隐藏frame2,但是每次显示它时都使用new ()(以避免重绘/缓冲区问题),并且我再次遇到相同的VD问题。 I also implemented com.apple.eawt.Application.requestToggleFullScreen along with com.apple.eawt.FullScreenListener to quit full screen before I dispose, but the app hangs. 我还实现了com.apple.eawt.Application.requestToggleFullScreencom.apple.eawt.FullScreenListener,以在处置前退出全屏,但该应用程序挂起。 Now looks like I'll have to live with the repaint.buffer issue to allow full screen switching to work correctly. 现在看来,我将不得不忍受repaint.buffer问题,以允许全屏切换正常工作。

SSCCE: 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);

            }
        });

    }

}

My solution to this "catch 22" is to only instantiate frame2 once in frame1, to use dispose() when frame2 is not full screen (avoids repaint/buffer issue), and to use setVisible(false) when frame2 is fullscreen (maintains a single virtual desktop for frame2). 我对“捕获22”的解决方案是仅在frame1中实例化一次frame2,在frame2不是全屏时使用dispose()(避免重画/缓冲区问题),而在frame2是全屏时使用setVisible(false)(保持frame2的单个虚拟桌面)。 Since the repaint issue does not affect full screen views this works very well, although I'm sure the purists will baulk! 由于重涂问题不会影响全屏视图,因此,即使我相信纯粹主义者也不会相信,这样做效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM