【问题标题】:Can I set JFrame's normal size while it is maximized?我可以在 JFrame 最大化时设置它的正常大小吗?
【发布时间】:2012-12-17 10:51:05
【问题描述】:

目标:

我希望在Frame.MAXIMIZED_BOTH 状态下显示一个框架,但我也希望它具有预定义的正常大小,因此当用户取消最大化它时,框架将调整为我想要的大小.我希望框架首先显示为最大化,无需视觉调整。我希望框架保持最大化,直到用户取消最大化它。

到目前为止我尝试过的事情:

1)

frame.setExtendedState( Frame.MAXIMIZED_BOTH );
frame.setVisible( true );
frame.setSize( 500, 500 );

评估:框架将切换到正常状态(不会保持最大化)=>不好。

2)

frame.setSize( 500, 500 );
frame.setExtendedState( Frame.MAXIMIZED_BOTH );
frame.setVisible( true );

评估: 窗口(或只是它的框架)将以 500x500 的大小出现,然后视觉调整大小(最大)将可见 => 不好。 这样做的原因是如果一个框架不可见,调用setExtendedState() 将被推迟到该框架可见。

3)

frame.setSize( 500, 500 );
frame.setVisible( true );
frame.setExtendedState( Frame.MAXIMIZED_BOTH );

评估: 就像尝试 #2 一样,框架会有视觉上的调整大小 => 不好。

4) 我尝试将组件侦听器添加到覆盖componentResize() 的框架并在那里更改状态。我还尝试添加一个覆盖windowStateChange() 的窗口状态侦听器。我还尝试添加一个覆盖 windowOpened() 的窗口侦听器。

评估:所有结果都像尝试 #2 一样导致视觉调整大小 => 不好。

如果我希望我的框架具有预定义的正常大小,但我希望它看起来最大化,我该怎么办?

编辑:将整个问题编辑得更清楚,并添加示例代码 (SSCCE)。

【问题讨论】:

  • 没有发布 SSCCE 的想法,顺便说一句,JFrame.pack() 也是如此
  • @mKorbel 调用 pack() 结果相同:我将看到一个我想要避免的可视窗口调整大小。
  • 您是否尝试过让 EDT 短时间休眠并直接调用您的调整大小?虽然可能不起作用,但也许值得一试。丑陋的变通办法有时可以解决丑陋的问题;)
  • @Zhedar 问题是我希望框架保持最大化。每当我调用 setSize() 时,框架都会自动从 MAXIMIZED_BOTH 状态切换到 NORMAL 状态。

标签: java swing


【解决方案1】:

我不确定你的意思,所以我举了一个例子来说明我认为你想要什么。

基本上用setExtendedState(JFrame.MAXIMIZED_BOTH) 创建一个JFrame,并在5000 毫秒后将状态更改为JFrame.NORMAL,没有闪烁。

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Test {

    public Test() {
        initComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }

    private void initComponents() {
        final JFrame frame = new JFrame() {
            @Override
            public Dimension getPreferredSize() {//used for testing purposes so JFrame has a size
                return new Dimension(300, 300);
            }
        };
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.pack();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);

        new Timer(5000, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                frame.setExtendedState(JFrame.NORMAL);
            }
        }).start();
    }
}

【讨论】:

  • 我希望框架保持在 MAXIMIZED_BOTH 状态。我编辑了这个问题,这样事情会更清楚。
  • “我希望框架保持在 MAXIMIZED_BOTH 状态。” 所以我猜你想删除用于演示框架正常大小的Timer?把那部分放在外面。
  • 如果我不考虑那部分,那么您提出的解决方案已经在我的尝试中列出。它有一个问题,我会看到我想避免的视觉调整大小。
  • @icza 在阅读了您的 cmets 等之后我想我明白了。尽管在您的示例代码中存在一个大问题,但绝对不建议使用 setSize。我不在我的电脑旁,但据我所知,您想在创建时将 jframe 设置为最大化而没有视觉闪烁?正如安德鲁汤普森所说,只需删除计时器。如果它仍然比我提供视觉调整大小,我认为它可能会停止。但我会在我的电脑附近确认什么时候
  • 是的,我希望 jframe 在创建时最大化,但我还希望在用户手动取消最大化时将窗口调整为指定大小。如果我省略了 setSize(),这不会发生。
【解决方案2】:

对我来说,以下顺序有效

setSize(100,100);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);

【讨论】:

  • 他说,他有一个可见的 JFrame。你的不是。
  • 我在我尝试过的问题中写道,首先这样做,窗口(或者可能只是它的框架)将以您设置的大小(在您的示例中为 100x100)出现,然后它会被最大化。这是我想避免的视觉调整大小。
【解决方案3】:

您的 #2 尝试已经接近答案。 JFrame 类中有 setMaximizedBounds() 方法。被MAXIMIZED_BOTHextendedState 设置上的frame 用来显示具体大小的frame 而不会闪烁。什么对我有用:

frame.setLocation(location);
frame.setSize( 500, 500 );
frame.setMaximizedBounds(calculateMaximizedBounds(frame))
frame.setExtendedState( Frame.MAXIMIZED_BOTH );
frame.setVisible( true );

calculateMaximizedBounds() 根据当前帧的位置和大小计算帧的最大化边界(感谢,KO!) - 如果 U 有 2 个以上的监视器,这很重要,尤其是当它们具有不同的尺寸时。

【讨论】:

  • 无论我是否包含setMaximizedBounds(),我都会得到相同的结果(除了当我包含setMaximizedBounds() 时,最大化的大小显然是我设置的那个)。
  • 你的意思是框架一直在闪烁吗?
  • 是的,和没有setMaximizedBounds()一样。虽然 #2 是最接近我想要的,而且它甚至没有打扰......但我不知道setMaximizedBounds() 所以谢谢。
  • 还有一点 PS:在调用 frame.setVisible(true) 之前,框架应该是不可见的
  • 是的,就是这样。
【解决方案4】:
this.addWindowStateListener(new WindowStateListener() {

        @Override
        public void windowStateChanged(WindowEvent e) {
                if (e.getNewState() == Frame.NORMAL) {
                    if (getSize().width == 0 || getSize().height == 0) {
                        setSize(500, 500);
                    }
                }
        }
    });

【讨论】:

  • 这个问题是我从一个最大化的框架开始。当我取消最大化它时,将调用您的侦听器,但 getSize() 将返回宽度和高度均大于 0 的大小,因此不会调用 setSize()。
  • 你可以测试一下。那时你调用 getSize(),它会返回 (0, 0)。因为您调用 frame.setExtendedState(Frame.MAXIMIZED_BOTH),而不是实际调用 setSize()。所以帧大小是(0,0)。
  • 我确实测试过了。 getSize() 还给我一个Dimension,它的分辨率接近我的屏幕分辨率。
  • 你曾经调用过 setSize() 吗?
  • 不,我没有。我刚刚调用了setExtendedState(MAXIMIZED_BOTH) 和setVisible(true)。
【解决方案5】:

下面的代码对我有用。我使用了 Perzers 的 WindowEvent 侦听器的想法,但我检查了窗口状态是否从最大化更改,但没有最小化(因此在恢复程序后,恢复了完整的先前状态):

    setExtendedState(JFrame.MAXIMIZED_BOTH);
    this.addWindowStateListener(new WindowStateListener() {
        @Override
        public void windowStateChanged(WindowEvent e) {
                // In Windows10 state 7 is returned if you minimize, usually ICONIFIED should mean the window is minimized, I used JDK1.6 on W10 (don't ask why)..
                if (e.getNewState() != JFrame.MAXIMIZED_BOTH && e.getNewState() != 7 && e.getNewState() != JFrame.ICONIFIED) {  
                    setSize(768, 500);
                }
        }
    });
    setVisible(true);

我不确定状态 7 实际上是什么。

更新:在 W10 中使用 JDK1.8 - 这里的状态实际上应该是“JFrame.ICONIFIED”。 状态 7 实际上是已弃用的“NE_RESIZE_CURSOR”。 https://docs.oracle.com/javase/7/docs/api/constant-values.html#java.awt.Frame

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    相关资源
    最近更新 更多