锁定老帖子 主题:Swing中窗口菜单动态变化的实现
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-09-02
JavaEye首发 转载请注明出处(每次都需要这么写上 现实真可悲)
MDI窗体中一般都会提供“窗口”菜单,其菜单项是 MDI 父窗体中打开的所有子窗体的标题或者其他信息。并且可以在“窗口”菜单中进行相应的选择,使用户选择的窗体能够显示在最前列。这样的功能在 WinForm 中实现太简单了,只需要将“窗口”菜单指定为 MDI 菜单即可,所有相关的操作 ( 比如新建子菜单之后窗口菜单中会多一个菜单项,用户在菜单中选中后将选中的子窗口激活等 ) 全部都可以自动完成 ( 再次膜拜 Microsoft 的强大,虽然有很多人每天都在骂,但 Microsoft 在桌面应用方面的优势至少在这个地球上,还无人能及 ) 。反观我喜爱并忠诚的 Java 中,所有这些操作都要自己去实现了。
跟MDI 窗体相关的 JDesktopPane 、 JInternalFrame 之间的关系,再次就不再重复了,还不太清楚的朋友自行带着小板凳回家面壁思过就好了。重点说说当一个 JInternalFrame 被实例化出来的时候, JDesktopPane 和主面板上的“窗口”菜单如何进行相应就好了。
需要完成的事情: 1.当一个JInternalFrame 被实例化出来的时候,窗口菜单中应该多一个选项,并默认被选中 2. 当关闭一个JInternalFrame 的时候,窗口菜单中应该减少对应的一个菜单选项 3. 当用户在窗口菜单中选择时,应该将用户选中的JInternalFrame 显示到最前 4. 当用户选中某个JInternalFrame 时,窗口菜单中对应的菜单选项应该处于选中状态
在JDesktopPane 中有这样一个方法 setDesktopManager() ,此方法中传入的参数是一个 DesktopManager 接口,并且在 JDK 中已经有一个默认实现类 DefaultDesktopManager 。其实我们需要做的事情,就是实现这个接口,用我们自己的方式 ( 以上要完成的任务为核心 ) 去实现它即可。
我们写一个类MyDesktopManager 继承自 DefaultDesktopManager 类,实现其中我们需要关心的方法。为完成以上的任务,我们需要重写 DefaultDesktopManager 中相应的方法。经常需要重写的方法可能包括一下几个: void activateFrame(JInternalFrame f) //窗口被激活 ( 获取焦点 ) 时触发 void deactivateFrame(JInternalFrame f) //窗口失去焦点时触发 void openFrame(JInternalFrame f) //根据 JDK 文档,这个该死的方法一般 不触发 void closeFrame(JInternalFrame f) //关闭窗口时出发
根据以上的信息,我们完全可以想办法实现“窗口”菜单的动态变化。当新的子窗口被打开的时候,我们可以向菜单中加入一个新的菜单选项。这个实现,可以放置在openFrame() 方法中。但是, 请注意openFrame() 方法一般情况下不会触发 ,因为,在JInternalFrame 被加入到 JDesktopPane 中以后,应该手动调用这个方法,使之触发。实现如下: public void openFrame(JInternalFrame f) { f.setTitle("untitled document "+frameCount + " ");//文档标题 item = new JRadioButtonMenuItem(f.getTitle());//用文档标题做菜单文本 item.setSelected(true);//默认选中 btnGroup.add(item);//实现互斥效果 item.addActionListener(new SelectedAction(f));//事件监听 frMain.getWindowMenu().add(item);//加入到主面板的“窗口”菜单中 super.openFrame(f);//此方法不可以删除 }
以上实现之后,在将JInternalFrame 和 JDesktopPane 进行组合时,手动调用这个方法,如下: JInternalFrame internal = new JInternalFrame("爷爷的",true,true,true,true); internal.setSize(new Dimension(480,320)); //加入到desktop中 frMain.getDesktopPane().add(internal); frMain.getDesktopPane().getDesktopManager().openFrame(internal);//调用 internal.setVisible(true);
在关闭子窗体时应该将加入的菜单选项从菜单中移除,因为这样实现: public void closeFrame(JInternalFrame f) { JMenu menu = frMain.getWindowMenu();//得到“窗口”菜单 int count = menu.getItemCount();//得到该菜单中选项的个数,注意分割线也算是菜单选项 for (int i = 0; i < count; i++) { JMenuItem it = menu.getItem(i); if(it!=null) { if(it.getText().equals(f.getTitle())) { menu.remove(i); break; } } } super.closeFrame(f); } 实现窗体激活和失去焦点的相应,实现起来也很简单,因此就不再重复,感兴趣的童鞋可以下载代码研究。
其实,Swing 是可以很美的。 ( 不记得是那句广告词了,暂时先拿来用。 ) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-09-03
监听JDesktopPane中的所有JInternalFrame的InternalFrameListener岂不更简单
|
|
返回顶楼 | |
发表时间:2010-09-03
不是想争吵或者怎么样,去研究一下xcode的开发mac应用的方式,以及mac的人性化方面的设计,你会发现:微软什么的还是要差一点。
|
|
返回顶楼 | |
发表时间:2010-09-03
HeDYn 写道 监听JDesktopPane中的所有JInternalFrame的InternalFrameListener岂不更简单
这种方法我还没有试过,不够应该可以实现同样的功能。 看了一下这个接口和对应的Adapter,貌似这样的方法实现动态窗口菜单会更好。 只是需要在每一个interframe上面都需要添加监听器;并且如果需要实现窗口层叠显示估计会麻烦一点。 anyway,InternalFrameListener接口和InternalFrameAdapter看起来像是更好的选择。 多谢兄弟回复。 |
|
返回顶楼 | |
发表时间:2010-09-03
viperasi 写道 不是想争吵或者怎么样,去研究一下xcode的开发mac应用的方式,以及mac的人性化方面的设计,你会发现:微软什么的还是要差一点。
很想用一下xcode做mac的开发,可是没钱啊,买不起mac的电脑或者笔记本。。。只能遥望而已。。。 |
|
返回顶楼 | |
发表时间:2010-09-03
viperasi 写道 不是想争吵或者怎么样,去研究一下xcode的开发mac应用的方式,以及mac的人性化方面的设计,你会发现:微软什么的还是要差一点。
微软一开始就是跟mac学的,要是mac不搞封闭的硬件策略,现在的软件业还真没微软啥事 |
|
返回顶楼 | |
发表时间:2010-09-03
EventManager,EventLister,EventObject...
|
|
返回顶楼 | |
发表时间:2010-09-17
yn5411 写道 EventManager,EventLister,EventObject... 这么个方法确实还没有实现过?静听思路。 |
|
返回顶楼 | |
发表时间:2010-09-25
只需监听JInternalFrame的InternalFrameListener、ComponentListener,以及JDesktopPane的ContainerListener即可实现。贴张我做的一个程序的截图
|
|
返回顶楼 | |
发表时间:2010-09-26
HeDYn 写道 只需监听JInternalFrame的InternalFrameListener、ComponentListener,以及JDesktopPane的ContainerListener即可实现。贴张我做的一个程序的截图
额,这个过程很赞。 不过这个变成了监听顶层的ComponentListener和ContainerListener,有点复杂。哈哈。 |
|
返回顶楼 | |
浏览 9920 次