大 连 理 工 大 学 计 算 机 系
邓继光 翟丽萍 张丽滨
---- 一.java 简 介
---- java 技 术 是 一 个 崭 新 的 技 术, 它 从c++ 中 吸 收 了 许 多 强 有 力 的 成 分, 并 且 带 有 许 多 新 的 特 征, 如
? ? ?
---- java 标 准 类 库 中 对internet 和web 内 建 的 支 持, 使 得 开 发 者 可 方 便 地 开 发 网 络 应 用。
---- 自 从java 诞 生 以 来, 众 多 的 公 司 已 致 力 于java 开 发 平 台 的 研 制,sun,microsoft,borland 和symantec 争 相 推 出 了 自 己 的java 开 发 平 台。javasoft 公 司 推 出 的jdk 以 其 灵 活 性 和 强 大 功 能 得 到 了 众 多 开 发 者 的 青 睐。
---- 二. jdk1.1.1 中 的 菜 单 功 能
---- 在jdk1.1.1 中 菜 单 功 能 具 体 由java.awt.menu ,java.awt.menubar ,java.awt.menucomponent ,java.awt.menuitem ,java.awt.menushortcut 实 现, 其 继 承 关 系 如 下:
java.lang.object
java.awt.menucomponent
java.awt.menuitem
java.awt.menu
java.awt.popupmenu
java.awt.menubar
java.awt.menushortcut
---- 在java.awt.frame 中 实 现 了java.awt.menucontainer, 利 用 其setmenubar 方 法 即 可 提 供 菜 单 服 务。 但 一 个application 中 只 应 有 一 个frame(dialog 除 外) 同 时 存 在, 否 则 所 有 的component 不 能 构 成 一 个 整 体(frame 可 被 自 由 拖 动), 这 样 如 仅 利 用jdk1.1.1 提 供 的 功 能,application 中 只 能 存 在 一 个 菜 单。 由frame 的
---- ? ? ?
---- frame 是 一 个container, 它 可 以 装 入 多 个panel, 如 能 在panel 中 实 现 菜 单 功 能, 就 可 以 在application 中 提 供 多 菜 单 服 务 了。
---- 三. 在panel 中 实 现 菜 单 功 能
---- 在panel 中 实 现 菜 单 功 能 可 有 如 下 三 种 途 径
---- 1. 模 仿java.awt.frame 的 菜 单 服 务, 在panel 中 加 入 菜 单 功 能
---- 2. 利 用jdk 提 供 的 部 分 功 能, 和 自 己 的component 组 合 完 成
---- 3. 完 全 用 自 己 的component 实 现
---- java.awt.frame 和java.awt.panel 各 自 的 继 承 关 系 如 下:
java.lang.object
java.awt.component
java.awt.container
java.awt.window
java.awt.frame
java.awt.panel
---- 由 继 承 关 系 可 以 看 出, 要 模 仿java.awt.frame 的 菜 单 服 务, 在panel 中 加 入 菜 单 功 能, 是 比 较 困 难 的, 况 且,jdk 文 档 中 并 未 提 供 完 整 的 源 代 码。
---- 如 要 完 全 用 自 己 的component 实 现, 则 需 考 虑 复 杂 的 屏 幕 刷 新 和 事 件 处 理 问 题, 也 是
---- ? ? ?
---- 而 利 用jdk1.1.1 的java.awt.component 中 提 供 的popupmenu 功 能, 在 上 面 加 上label, 在 鼠 标 点 击label 时, 弹 出popupmenu, 以 此 模 仿frame 提 供 的 菜 单 服 务, 可 以 较 容 易 的 在panel 中 加 入 菜 单 功 能。 具 体 实 现 如 下:
---- // 此listener 用 于 发 出menubarlabel 点 击 事 件
public interface menubarlabellistener
{
public void processlabelclick(string labelname);
}
import java.awt.* ;
import java.awt.event.* ;
import java.util.*;
//menubarlabel 用 于 模 拟java.awt.menubar 的 功 能
public class menubarlabel extends
canvas implements mouselistener
{
protected color foreground = color.black ;
protected color background = color.lightgray;
protected string xlabel ;
protected boolean disabled = false ;
protected menubarlabellistener listener=null;
public menubarlabel(string xlabel)
{
this.xlabel = new string(xlabel);
setfont(new font("courier",font.plain,16));
setbackground(background);
addmouselistener(this);
}
public void addlistener(menubarlabellistener listener)
{
this.listener=listener;
}
public string getname()
{
return xlabel;
}
public void paint(graphics g)
{
dimension dm = getsize();
int width = dm.width;
int height= dm.height;
g.setcolor(foreground);
int descent = g.getfontmetrics().getdescent();
g.drawstring(xlabel,0,height-descent);
}
public void mouseclicked(mouseevent evt){ ;}
public void mouseentered(mouseevent evt){ ;}
public void mousepressed(mouseevent evt)
{
background=color.blue.darker().darker();
paint();
if (null !=listener)
listener.processlabelclick(xlabel);
}
public void mouseexited(mouseevent evt)
{
background=color.lightgray;
setbackground(background);
}
public void mousereleased(mouseevent evt)
{
background=color.lightgray;
setbackground(background);
}
public void setforeground(color foreground)
{
this.foreground = foreground;
repaint();
}
public void setbackground(color background)
{
this.background = background;
repaint();
}
public void paint()
{
graphics g=getgraphics();
if (null==g) return;
dimension dm = getsize();
int width = dm.width;
int height= dm.height;
int descent = g.getfontmetrics().getdescent();
int height1=g.getfontmetrics().getheight();
g.setcolor(color.blue.darker().darker());
g.fillrect(0,height-height1,width,height1);
g.setcolor(color.white);
g.drawstring(xlabel,0,height-descent);
g.dispose();
}
public void paintback()
{
graphics g=getgraphics();
if (null==g) return;
dimension dm = getsize();
int width = dm.width;
int height= dm.height;
int descent = g.getfontmetrics().getdescent();
g.setcolor(color.lightgray);
g.fillrect(0,0,width,height);
g.setcolor(foreground);
g.drawstring(xlabel,0,height-descent);
g.dispose();
}
}
// 此listener 用 于 提 供 所 有 的 菜 单 选 择 事 件
public interface menupanellistener
{
public void processmymenu(object source,object label);
//you can use source to indentify
different items with same label
}
//menupanel 提 供 菜 单 功 能 服 务
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
*pay attention:
*1.the menupanel′s height >==26, 26 recommended
*2.you can not change the
background of the menu because popup
* menu′s backgroud can not be changed
*/
public class menupanel extends panel implements
actionlistener,menubarlabellistener
{
panel mymenubar=new panel();
panel popuppanel=new panel();
menubarlabel previouslabel=null;
menupanellistener listener=null;
font labelfont=new font("courier",font.plain,16);
private vector labelvector=new vector();
private vector popupvector=new vector();
int maxwidth=0;
public menupanel()
{
setlayout(null);
mymenubar.setlayout(null);
mymenubar.setbackground(color.lightgray);
add(mymenubar);
add(popuppanel);
mymenubar.setbounds(0,0,400,25);
popuppanel.setlayout(null);
popuppanel.setbounds(0,26,400,500);
popuppanel.setvisible(false);
setfont(labelfont);
}
public void addlistener(menupanellistener listener)
{
this.listener=listener;
}
private void addmenuitemlistener(menucomponent menu)
{
((menuitem)menu).addactionlistener(this);
if (menu instanceof menu || menu instanceof popupmenu)
for (int i=0;i< ((menu)menu).getitemcount();i++)
addmenuitemlistener(((menu)menu).getitem(i));
}
private void setmenuitemfont(menucomponent menu)
{
menu.setfont(labelfont);
if (menu instanceof menu || menu instanceof popupmenu)
for (int i=0;i< ((menu)menu).getitemcount();i++)
setmenuitemfont(((menu)menu).getitem(i));
}
public void addmenu(popupmenu menu,string name)
{
if (menu==null || name==null ||name.length()< =0)
return;
menubarlabel label=new menubarlabel(name);
label.setfont(labelfont);
label.addlistener(this);
mymenubar.add(label);
labelvector.addelement(label);
setmenuitemfont(menu);
addmenuitemlistener(menu);
popupvector.addelement(menu);
popuppanel.add(menu);
}
public void setmenufont(font menufont)
{
int fontsize=menufont.getsize();
if (menufont.getsize() >25)
fontsize=25;
labelfont=new font(menufont.getname(),
menufont.getstyle(),fontsize);
setfont(labelfont);
for (int i=0;i< popupvector.size();i++)
setmenuitemfont(((popupmenu)
popupvector.elementat(i)));
repaint();
}
public void paint(graphics g)
{
menubarlabel label;
int width=0,width1;
int panelwidth=getparent().getsize().width;
if (panelwidth >0)
{
setsize(panelwidth,getsize().height);
mymenubar.setbounds(0,0,panelwidth,25);
popuppanel.setbounds(0,26,panelwidth,500);
}
for (int i=0; i< labelvector.size();i++)
{
label=(menubarlabel)labelvector.elementat(i);
label.setfont(labelfont);
width1=g.getfontmetrics().stringwidth(label.getname());
if (width1 >width)
width=width1;
}
if (width !=maxwidth)
{
maxwidth=width;
for (int i=0; i< labelvector.size();i++)
{
label=(menubarlabel)labelvector.elementat(i);
label.setbounds(i*maxwidth+(i+1)*15,0,maxwidth,25);
}
}
}
public void processlabelclick(string labelname)
{
menubarlabel label=null;
boolean invector=false;
int i=0;
while (i< labelvector.size())
{
label=(menubarlabel)labelvector.elementat(i);
if ((label.getname()).equals(labelname))
{
invector=true;
break;
}
i++;
}
if (invector)
{
if ((null !=previouslabel)&&
(!previouslabel.equals(label)))
previouslabel.paintback();
previouslabel=label;
if (((popupmenu)popupvector.element
at(i)).getitemcount() >0)
{
popuppanel.setvisible(true);
((popupmenu)popupvector.elementat(i)).
show(popuppanel,i*maxwidth+
(i+1)*15,0);
}
}
}
public void actionperformed(actionevent evt)
{
if(null!=listener)
listener.processmymenu(evt.getsource(),
evt.getactioncommand());
}
}
---- 四. 应 用 举 例
---- 本 例 程 利 用 上 面 的menupanel, 在testmenu 中 实 现 了 带 两 个 下 拉 菜 单 的 菜 单。
import java.awt.*;
public class testmenu extends frame
implements menupanellistener
{
public testmenu()
{
setlayout(null);
setsize(400,300);
menupanel mypanel=new menupanel();
menupanel.addlistener(this);
// 在mypanel 中 加 入listener
popupmenu popupmenu1=new popupmenu("menu1");
//"menu1" 即 为 显 示 的label
menu submenu1=new menu("test1");
submenu1.addmenuitem(new menuitem("item1"))
submenu1.addmenuitem(new menuitem("item2"))
menu submenu2=new menu("test2");
submenu2.addmenuitem(new menuitem("item3"))
submenu2.addmenuitem(new menuitem("item4"))
menu submenu3=new menu("test3");
submenu3.addmenuitem(new menuitem("item5"))
submenu3.addmenuitem(new menuitem("item6"))
popupmenu1.addmenuitem(submenu1);
popupmenu1.addmenuitem(submenu2);
popupmenu1.addmenuitem(submenu3);
mypanel.addmenu(popupmenu1);
popupmenu popupmenu2=new popupmenu
("menu2");//"menu2" 即 为 显 示 的label
menu submenu4=new menu("test4");
submenu4.addmenuitem(new menuitem("item7"))
submenu4.addmenuitem(new menuitem("item8"))
menu submenu5=new menu("test5");
submenu5.addmenuitem(new menuitem("item9"))
submenu5.addmenuitem(new menuitem("item10"))
menu submenu6=new menu("test6");
submenu6.addmenuitem(new menuitem("item11"))
submenu6.addmenuitem(new menuitem("item12"))
popupmenu2.addmenuitem(submenu4);
popupmenu2.addmenuitem(submenu5);
popupmenu2.addmenuitem(submenu6);
mypanel.addmenu(popupmenu2);
mypanel.setbounds(0,0,400,26);
add(menupanel);
}
public void processmymenu(object source,object label)
{ system.out.println((string)label);
}
protected void processevent(awtevent evt)
{ if (evt.id == event.window_destroy) system.exit(0);
}
}
---- 注: 本 文 程 序 在win95 下, 用jdk1.1 调 试 通 过。
闽公网安备 35060202000074号