当前位置: 首页 > 知识库问答 >
问题:

将JInternalFrames从一个JDesktopPane移动到另一个

宁飞宇
2023-03-14

我一直在设计一个基于Swing的桌面RPG程序,以促进带有GUI控制元素的基于文本的角色扮演。

为了促进这一点,每个正在运行的客户端都会获得一个带有所有重要JFrames的主桌面(托管客户端上的“GM Desktop”和远程客户端上的“Player Desktop”)。此外,GM和Players都可以为角色打开“透视桌面”,为他们提供一个单独的JDesktopPane,其中包含提供该角色视角的“角色扮演聊天窗口”,以及其他JInternalFrames,例如“角色表窗口”等。

用户使用JTabbedPane在桌面之间导航。

我遇到的问题是,我希望某些窗口能够在桌面之间移动。例如,如果OOC(角色外)聊天在用户处于透视桌面时收到消息,我希望OOC聊天窗口有一个选项自动重新定位到当前桌面,以便用户立即看到消息。类似地,我希望玩家能够使用菜单栏将某些窗口“调用”到当前桌面。

然而,当我试图将一个JInternalFrame从一个JDesktopPane移动到另一个JDestoppane时,我收到了一个异常。

com.finnickslab.textroleplayonline.exceptions.CommandEventHandlingException
An exception was thrown during command handling. CommandEvent type: UI_OOC_CHAT (26).
Cause Exception: java.lang.IllegalArgumentException
illegal component position
java.awt.Container.addImpl(Unknown Source)
javax.swing.JLayeredPane.addImpl(Unknown Source)
javax.swing.JDesktopPane.addImpl(Unknown Source)
java.awt.Container.add(Unknown Source)
com.finnickslab.textroleplayonline.ui.GameDesktop.receiveTransfer(GameDesktop.java:80)
com.finnickslab.textroleplayonline.ui.GameDesktop.access$0(GameDesktop.java:74)
com.finnickslab.textroleplayonline.ui.GameDesktop$2.run(GameDesktop.java:69)
com.finnickslab.textroleplayonline.ui.UI.invokeEvent(UI.java:818)
com.finnickslab.textroleplayonline.ui.GameDesktop.transfer(GameDesktop.java:62)
com.finnickslab.textroleplayonline.ui.UI$HostCommandHandler.handle(UI.java:605)
com.finnickslab.textroleplayonline.comm.Server$3.run(Server.java:324)

我的程序中的所有JInternalFrame都源自JInternalFrame的同一个子类(“InternalWindow”)。

这个例外使它看起来有点复杂,但它归结为调用JDesktopPane.remove(JInternalFrame),然后调用JDesktopPane.add(JInternalFrame)。

然后当在GameDesktop第80行调用“add”方法时,我会收到异常。

/**
 * Transfers the specified InternalWindow from this GameDesktop to
 * the specified GameDesktop. Use this method to prevent
 * automatic removal of listeners performed with the
 * {@link GameDesktop.remove(InternalWindow)} method.
 */
public synchronized void transfer(
      final InternalWindow window,
      final GameDesktop gd) {
   final GameDesktop desktop = this;
   contents.remove(window);

   UI.invokeEvent(new Runnable() {
      @Override
      public void run() {
         desktop.remove((JInternalFrame) window);
         desktop.validate();
         desktop.repaint();

         gd.receiveTransfer(window);
      }
   });
}

private synchronized void receiveTransfer(InternalWindow window) {
   contents.add(window);

   window.changeDesktop(this);
   window.center();
   this.add((JInternalFrame) window);    // LINE 80
   this.validate();
   this.repaint();
   window.resetPosition();
}

"UI.invokeEvent(Runnable)"方法是我为SwingUtilities.invokeAndWait(Runnable)编写的一个方便方法。它检查当前线程是否是EDT,如果是,则立即执行run()方法。否则,它使用调用和等待(Runnable)来调度EDT上的可运行项。

任何关于如何解决这个问题的想法都将不胜感激。

编辑:

我对此误差的所有研究表明,它与组件的Z轴位置有关。我尝试更改添加调用以指定z位置

super.add(window, getComponentCount());

但是没有变化。仍然得到相同的IllegalArgumentException。

共有1个答案

伍玮
2023-03-14

看看在运行时是否会出现同样的错误。如果不是,问题不在于切换内部帧的父帧,而在于同步

public class IFSwitch extends JDesktopPane {

    final JDesktopPane pane1 = this;

    public IFSwitch() {

        JFrame frame1 = new JFrame("Frame1");
        JFrame frame2 = new JFrame("Frame2");
//      JDesktopPane pane1 = new JDesktopPane();
        JDesktopPane pane2 = new JDesktopPane();
        final JInternalFrame if1 = new JInternalFrame();

        frame1.add(pane1);
        frame2.add(pane2);
        pane1.add(if1);

        if1.setBounds(10, 10, 100, 100);
        frame1.setBounds(100, 100, 200, 200);
        frame2.setBounds(500, 500, 200, 200);
        frame1.setVisible(true);
        frame2.setVisible(true);
        if1.setVisible(true);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        pane2.add(if1);
        pane1.remove(if1); // You don't even need this line.
        pane1.repaint();

    }

    public static void main(String[] args) {

        new IFSwitch();
    }
}
 类似资料:
  • 我的mac电脑中没有internet连接。我需要使用docker pull。我的想法是,我将使用docker拉入我的一台连接互联网的mac电脑,然后将其复制到没有互联网连接的mac电脑上。如何复制?

  • 我创建了一个简单的webjob,并将其部署在我的试用azure门户上的测试webapp上,以了解一些事情。 作为本次学习的一部分,我希望将此webjob移动到同一azure门户中的另一个webapp,而无需通过visual studio重新部署。如何实现? 感谢任何帮助。谢谢

  • 问题内容: 情况:我有两个固定高度的div,两个溢出都设置为隐藏,并且第一个div中包含动态文本内容。如果该内容超出了第一个div的溢出边界,我希望它自动溢出到第二个div中。 我的问题就是该怎么做?我进行了研究,发现最接近的是一个JQuery插件,该插件会自动为类似报纸的布局创建列。尽管这并不是我真正需要的,但它确实使我希望可以在一个更简单的级别上实现。 可视示例: 谢谢大家!根据所有输入,我将

  • 问题内容: 我想将一个DIV元素移到另一个元素中。例如,我要移动此对象(包括所有子对象): 到这个: 这样我有: 问题答案: 曾经尝试过普通的JavaScript … 吗?

  • 在我的AnyLogic模型中,容器代理在主代理中移动到不同的位置。 Main包含位于特定位置的多个块代理实例。Block包含一台多桥桥式起重机,该起重机应能捡起集装箱并将其运至当地仓库。 当容器被放置在块的起重机范围内的吸引器处时,块内的一个进程被调用。此进程包含入口、移动起重机和出口块。在移动起重机块中,在抓取步骤中,AnyLogic给我以下错误: 所有块代理都位于main中的不同坐标处。它们各

  • 问题内容: 听起来很简单,但我无法使其正常工作。我有两个活动。第一个是表单,第二个是根据在第一个活动中输入的值显示JSON文件中的数据。 因此,我正在尝试制作一个简单的版本。我有一个EditText和一个按钮,因此当他们按下按钮时,EditText中的内容将出现在下一个活动的TextView中。 到目前为止,这是我的代码: 主要活动 主要XML 第二次活动 第二个XML 通过这种方式,我为Edit