0

我的用户喜欢拥有多个JFrames;它允许他们调整不同组件的大小并将它们放置在屏幕上的任何位置。但是,我有一个要求让所有子窗口一起出现在前面......换句话说,假设他们最大化所有窗口前面的另一个窗口,然后使用任务栏单击其中一个JFrames。我怎样才能设置它让他们都来到前面?注意:也可以关闭子窗口;如果他们真的被隐藏了,我希望他们来到前面。我有一个类ApplicationModel可以跟踪窗口是否隐藏。

我尝试过的事情:

  1. 使用windowActivated()andfocusGained()尝试将它们全部放在前面。这通常会导致无限循环。问题是我的事件框架将这些请求从事件调度线程发送出去,所以任何类型的阻塞AtomicBoolean都不会持续足够长的时间。
    • 主要的问题不是我不能让他们上前线……我已经让他们上前线了。问题是他们一直试图走到最前面,因为把一个窗口带到前面会引发 focusGained 和 windowActivated 事件,这会创建一个无限循环......
  2. 将一个窗口设为主窗口,将其他窗口设为JDialog. 不幸的是,这些窗口要么是无模式的(因此不会出现在主窗口的前面),要么它们是模态的(因此会阻塞主窗口)。

我该如何解决这些问题,或者是否有完全不同的第三种解决方案?

4

2 回答 2

0

您可以使用布尔字段作为标志来防止无限循环:

private boolean movingAllFramesToFront;

public void windowActivated(WindowEvent event) {
    if (movingAllFramesToFront) {
        return;
    }

    movingAllFramesToFront = true;

    List<Frame> frames = getAllApplicationFrames();
    for (Frame frame : frames) {
        if (!applicationModel.isHidden(frame)) {
            frame.toFront();
        }
    }

    event.getWindow().toFront();
    event.getWindow().requestFocus();

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            movingAllFramesToFront = false;
        }
    );
}

您可以尝试的另一件事是autoRequestFocusJava 1.7 中引入的新属性。我从未尝试过使用它,但这是我对其工作原理的理解:

public void windowActivated(WindowEvent event) {
    final List<Frame> frames = getAllApplicationFrames();

    for (Frame frame : frames) {
        if (!applicationModel.isHidden(frame)) {
            frame.setAutoRequestFocus(false);
            frame.toFront();
        }
    }

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            for (Frame frame : frames) {
                if (!applicationModel.isHidden(frame)) {
                    frame.setAutoRequestFocus(true);
                }
            }
        }
    );
}
于 2013-09-25T23:37:55.830 回答
0

我有一个带有很多窗口的应用程序,并且遇到了与您类似的问题。我的解决方法是:

@Override
    public void windowActivated(WindowEvent e) {
        if (e.getOppositeWindow() == null) {
            //front every window
        }
    }

首先,我创建了一个类“SlveFrame”(Slve 是我的应用程序的名称),它是“JFrame”的一个子类。

public class SlveFrame extends JFrame implements WindowListener {
    static ArrayList<SlveFrame> frames = new ArrayList<SlveFrame>();

    public SlveFrame () {
         addWindowListener(this); / /to make JFrame fire WindowListener's method
    }

    / /... every method added from WindowListener
    @Override
    public void windowActivated(WindowEvent e) {
        if (e.getOppositeWindow() == null) { // return null if window is not from my (or Your) work
            for (SlveFrame frame : frames) { // if you have no idea what this is, look for "for each loop java" in google
                 frame.toFront();
            }
        }
    }

    /**
    * The use of SlveFrame is almost the same as Jframe
    */
    @Override
    public void setVisible (boolean b) {
        if (b) 
            frames.add(this);
        else
            frames.remove(this); // may raise an exception if you're not careful
        super.setVisible(b); //   or your window will simply not be visible.
    }

    @Override
    public void dispose () {
        frames.dispose(this) // may raise an exception you'll want to handle
   }
}


诀窍是如果 JFrame(或子类)来自您自己的程序,则 WindowEvent.getOppositeWIndow() 返回一个Jframe ,这意味着如果您切换到另一个程序或应用程序(例如 eclipse、Firefox 或文本编辑器)然后返回您的任何窗口,然后调用getOppositeWindow()将返回“null”。一个简单的if (e.getOppositeWindow())方法可以很容易地确定您的窗口是否在需要您将每个窗口都放在前面的条件下获得焦点,或者更确切地说是让一切都在。

setVisible (boolean b) 和的覆盖 dispose () 是可选的,但允许开发人员将其用作常规窗口。


我希望我能有所帮助。真诚的~喇嘛

于 2016-08-09T22:18:45.117 回答