Why jframe hides taskbar when maximized?

前端 未结 3 1866
不思量自难忘°
不思量自难忘° 2021-01-17 02:52

I\'m using setUndecorated(true); and getRootPane().setWindowDecorationStyle(JRootPane.FRAME); in my jFrame. This works great but now when I maximiz

相关标签:
3条回答
  • 2021-01-17 03:28

    Maybe you can set the maximum size of the jFrame and restrict it according to the screen size.

    EDIT

    Also check out setExtendedState

    0 讨论(0)
  • 2021-01-17 03:28

    Fortega answer worked however, some part is not needed (or no longer needed with Java 8):

    • The Rectangle does not need to be saved.
    • The code does not take into account dual screen configuration. In particular, the GraphicsConfiguration will change if the window change screen.
    • As far as I tested, the only required override is setExtendedState.

    When factoring dual screen configuration, at least on Windows, the below code does not work as intended:

    Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                        screenInsets.top + screenSize.y, 
                                        screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                        screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);
    

    On the following dual screen set up:

    • Left screen 1920x1080 (not primary), position: -1920, 0
    • Right screen 1920x1080 (primary), position: 0, 0

    The maxBounds will contains negative x (-1920) but the setMaximizedBounds is somehow expecting a coordinate in the screen space (where (x,y) starts at (0,0)) , not the virtual screen:

    • It will set to setMaximizedBounds(x=-1920,y=0,width=1920,height=1050)
    • Windows will see the window on the left screen (because I have one taskbar per screen showing only window on that screen) however the window won't be shown on the screen because it is off bounds.
    • If the resolution of the screen, or worse, its scale factor (with a laptop, Windows 10 will apply a scale factor, ex: 25%, making the screen "not so" 1920x1080), then the above code does not adapt. For example, if my configuration have 3 screens with the right most being the primary, the window will badly display on the left and middle screen. I don't think I fixed this in the below code.

    The following code work on Windows, with dual screen:

      @Override
      public synchronized void setExtendedState(final int state) {
        if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
          final GraphicsConfiguration cfg = getGraphicsConfiguration();
          final Insets screenInsets = getToolkit().getScreenInsets(cfg);
          final Rectangle screenBounds = cfg.getBounds();
          final int x = screenInsets.left + screenBounds.x * 0;
          final int y = screenInsets.top + screenBounds.y * 0;
          final int w = screenBounds.width - screenInsets.right - screenInsets.left;
          final int h = screenBounds.height - screenInsets.bottom - screenInsets.top;
          final Rectangle maximizedBounds = new Rectangle(x, y, w, h);
    
          System.out.println("cfg (" + cfg + ") screen.{bounds: " + screenBounds + ", insets: " + screenInsets + ", maxBounds: " + maximizedBounds);
    
          super.setMaximizedBounds(maximizedBounds);
        }
        super.setExtendedState(state);
      }
    

    On a simple JFrame:

    • Maximizing on the left screen ("screen=0") will print cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=0],pixfmt=0]) screen.{bounds: java.awt.Rectangle[x=-1920,y=0,width=1920,height=1080], insets: java.awt.Insets[top=0,left=0,bottom=30,right=0], maxBounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1050]
    • Maximizing on the right screen ("screen=1") will print cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=1],pixfmt=0]) screen.{bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1080], insets: java.awt.Insets[top=0,left=0,bottom=30,right=0], maxBounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1050]
    0 讨论(0)
  • 2021-01-17 03:38

    This is a known bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4737788

    Quote from this link:

    A workaround is to subclass JFrame and override the setExtendedState method, catching any maximize events before they happen and setting the maximum bounds of the frame appropriately before calling the superclass's setExtendedState method.

    import java.awt.*;
    import javax.swing.*;
    
    public class PFrame extends JFrame
    {
    private Rectangle maxBounds;
    
    public PFrame()
    {
        super();        
        maxBounds = null;
    }
    
    //Full implementation has other JFrame constructors
    
    public Rectangle getMaximizedBounds()
    {
        return(maxBounds);
    }
    
    public synchronized void setMaximizedBounds(Rectangle maxBounds)
    {
        this.maxBounds = maxBounds;
        super.setMaximizedBounds(maxBounds);
    }
    
    public synchronized void setExtendedState(int state)
    {       
        if (maxBounds == null &&
            (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH)
        {
            Insets screenInsets = getToolkit().getScreenInsets(getGraphicsConfiguration());         
            Rectangle screenSize = getGraphicsConfiguration().getBounds();
            Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                        screenInsets.top + screenSize.y, 
                                        screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                        screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);
            super.setMaximizedBounds(maxBounds);
        }
    
        super.setExtendedState(state);
    }
    }
    
    0 讨论(0)
提交回复
热议问题