16. 树(JTree)使用示例
例16.1 创建JTree示例。
package GUI1; import java.awt.BorderLayout; import java.awt.Container; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.*; public class demoJTree implements TreeSelectionListener { JFrame jf; JLabel jl; Container con; JTree jt; JScrollPane jsp; DefaultMutableTreeNode node,root; public demoJTree(){ jf = new JFrame("JTree使用示例"); jl = new JLabel(); con = jf.getContentPane(); root = new DefaultMutableTreeNode("Option"); node = new DefaultMutableTreeNode("A"); root.add(node); node.add(new DefaultMutableTreeNode("a1")); node.add(new DefaultMutableTreeNode("a2")); node = new DefaultMutableTreeNode("B"); root.add(node); node.add(new DefaultMutableTreeNode("b1")); node.add(new DefaultMutableTreeNode("b2")); node.add(new DefaultMutableTreeNode("b3")); node.add(new DefaultMutableTreeNode("b4")); jt = new JTree(root); jt.addTreeSelectionListener(this); jsp = new JScrollPane(jt); con.add(jsp, BorderLayout.CENTER); con.add(jl, BorderLayout.SOUTH); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void valueChanged(TreeSelectionEvent e) { jl.setText(e.getPath().toString()); } public static void main(String[] args) { new demoJTree(); } }
例16.2 在JTree中增加节点示例。
package GUI1; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.*; public class addNodeInJTree implements TreeSelectionListener,ActionListener { JFrame jf; JLabel jl; JPanel jp; Container con; JTree jt; JScrollPane jsp; JTextField jtf; JButton jbtn; private DefaultMutableTreeNode node,root; private DefaultTreeModel dtm; public addNodeInJTree(){ jf = new JFrame("JTree使用示例"); jl = new JLabel(); jp = new JPanel(); jtf = new JTextField(); jtf.setColumns(11); jbtn = new JButton("增加子节点"); jbtn.addActionListener(this); con = jf.getContentPane(); root = new DefaultMutableTreeNode("Option"); node = new DefaultMutableTreeNode("A"); root.add(node); node.add(new DefaultMutableTreeNode("a1")); node.add(new DefaultMutableTreeNode("a2")); node = new DefaultMutableTreeNode("B"); root.add(node); node.add(new DefaultMutableTreeNode("b1")); node.add(new DefaultMutableTreeNode("b2")); node.add(new DefaultMutableTreeNode("b3")); node.add(new DefaultMutableTreeNode("b4")); dtm = new DefaultTreeModel(root); jt = new JTree(dtm); jt.addTreeSelectionListener(this); jsp = new JScrollPane(jt); jp.setLayout(new FlowLayout()); jp.add(jl); jp.add(jtf); jp.add(jbtn); con.add(jsp, BorderLayout.CENTER); con.add(jp, BorderLayout.SOUTH); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } DefaultMutableTreeNode rdmt; public void valueChanged(TreeSelectionEvent e) { jl.setText(e.getPath().toString()); rdmt = (DefaultMutableTreeNode)jt.getLastSelectedPathComponent(); } public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode dmt; if(e.getSource()==jbtn){ dmt = new DefaultMutableTreeNode(jtf.getText()); dtm.insertNodeInto(dmt,rdmt,0); } } public static void main(String[] args) { new addNodeInJTree(); } }
17. 菜单使用示例
一个完整的菜单通常由3部分构成:菜单条(JMemuBar)、下拉式菜单(JMemu)和菜单项(JMemuItem)。
例17.1 菜单使用示例。
package GUI1; import java.awt.BorderLayout; import java.awt.Container; import javax.swing.*; public class demoJMenu { JFrame jf; JScrollPane jsp; JTextArea jta; Container con; JMenuBar jmb; JMenu file,edit,format,check,help; //文件菜单项 JMenuItem newItem,open,save,saveas,page,print,exit; //编辑菜单项 JMenuItem undo,cut,copy,paste,find,replace,selectall; //格式菜单项 JMenuItem font; JCheckBoxMenuItem wrap; //查看 JMenuItem state; //帮助 JMenuItem helpItem,about; public demoJMenu(){ jf = new JFrame("JMenu使用示例"); jta = new JTextArea(); jsp = new JScrollPane(jta); con = jf.getContentPane(); createMenu(); jf.setJMenuBar(jmb); con.add(jsp, BorderLayout.CENTER); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private void createMenu() { jmb = new JMenuBar(); file = new JMenu("文件"); edit = new JMenu("编辑"); format = new JMenu("格式"); check = new JMenu("查看"); help = new JMenu("帮助"); //文件 newItem,open,save,saveas,page,print,exit newItem = new JMenuItem("新建"); open = new JMenuItem("打开.."); save = new JMenuItem("保存.."); saveas = new JMenuItem("另存为.."); page = new JMenuItem("页面设置.."); print = new JMenuItem("打印.."); exit = new JMenuItem("退出"); file.add(newItem); file.add(open); file.add(save); file.add(saveas); file.add(page); file.add(print); file.add(edit); jmb.add(file); //编辑 undo,cut,copy,paste,find,replace,selectall; undo = new JMenuItem("撤销"); cut = new JMenuItem("剪切"); copy = new JMenuItem("复制"); paste = new JMenuItem("粘贴"); find = new JMenuItem("查找.."); replace = new JMenuItem("替换.."); selectall = new JMenuItem("全选"); edit.add(undo); edit.addSeparator(); edit.add(cut); edit.add(copy); edit.add(paste); edit.addSeparator(); edit.add(find); edit.add(replace); edit.addSeparator(); edit.add(selectall); jmb.add(edit); //格式JMenuItem font;JCheckBoxMenuItem wrap; wrap = new JCheckBoxMenuItem("自动换行"); font = new JMenuItem("字体"); format.add(wrap); format.add(font); jmb.add(format); //查看JMenuItem state; state = new JMenuItem("状态栏"); check.add(state); jmb.add(check); //帮助JMenuItem helpItem,about; helpItem = new JMenuItem("帮助主题"); about = new JMenuItem("关于.."); help.add(helpItem); help.add(about); jmb.add(help); } public static void main(String[] args) { new demoJMenu(); } }
文字菜单项中间的分隔线采用这样的方法:fileMenu.addSeparator()。
注:可以用数组简化。
最后,讨论一下JPopupMenu的使用。它的创建和JMenu的创建并没有什么不同。只是它不需要加到JMenuBar中,而是需要绑定到某个组件上(例如上例中的JTextArea),这可以使用组件的setComponentPopupMenu(JPopupMenu popup)方法,以后当用户在这个组件上右击时,该菜单将会自动弹出来,这就无需程序员计算菜单显示的位置。
18. 布局管理
18.1 流式布局(FlowLayout)
18.2 边框布局(BorderLayout)
18.3 网格布局(GridLayout)
18.4 卡片布局(CardLayout)
由于一次只能看到一张卡片,而且不能任意地切换卡片,所以CardLayout比较适合分类操作或者是有多个操作步骤、每个步骤有先后关系的情况。当第一步完成后,切换到第二张卡片,然后切换到第三张卡片......典型的例子是程序的安装向导。
注意:如果需要在多张卡片之间来回切换,一般会选择JTablePane,通过它的标签来选择卡片。
例. 模拟一般软件安装过程的卡片布局使用示例。
package GUI1; import java.awt.CardLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; public class demoCardLayout implements ActionListener { JFrame jf; JPanel jp1,jp2,jp3; JLabel jl1,jl2,jl3; JButton nextBtn1,prevBtn1,nextBtn2,prevBtn2,OKBtn; Container con; CardLayout cl; public demoCardLayout(){ jf = new JFrame("CardLayout使用示例"); cl = new CardLayout(); con = jf.getContentPane(); con.setLayout(cl); jl1 = new JLabel("这是第一步"); nextBtn1 = new JButton("下一步"); nextBtn1.addActionListener(this); jp1 = new JPanel(); jp1.add(jl1); jp1.add(nextBtn1); con.add("first",jp1); jl2 = new JLabel("这是第二步"); prevBtn1 = new JButton("上一步"); prevBtn1.addActionListener(this); nextBtn2 = new JButton("下一步"); nextBtn2.addActionListener(this); jp2 = new JPanel(); jp2.add(jl2); jp2.add(prevBtn1); jp2.add(nextBtn2); con.add("second", jp2); jl3 = new JLabel("这是第三步"); prevBtn2 = new JButton("上一步"); prevBtn2.addActionListener(this); OKBtn = new JButton("完成"); OKBtn.addActionListener(this); jp3 = new JPanel(); jp3.add(jl3); jp3.add(prevBtn2); jp3.add(OKBtn); con.add("third", jp3); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if(obj==nextBtn1||obj==nextBtn2) cl.next(con); if(obj==prevBtn1||obj==prevBtn2) cl.previous(con); if(obj==OKBtn) jf.dispose(); } public static void main(String[] args) { new demoCardLayout(); } }
18.5 增强网格布局(GridBagLayout)
它的功能类似于GridLayout,但比后者的功能更强大,使用起来也要复杂得多。它能够制造出跨行和跨列的单元格。
例. 增强网格布局使用示例。
package GUI1; import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import javax.swing.*; public class demoGridBagLayout { JFrame jf; Container con; GridBagLayout gbl; private void makebutton(String name,GridBagLayout gbl,GridBagConstraints c){ JButton btn = new JButton(name); //参数c决定了如何放置这个按钮 gbl.setConstraints(btn, c); con.add(btn); } public demoGridBagLayout(){ jf = new JFrame("增强网格布局使用示例"); con = jf.getContentPane(); GridBagConstraints c = new GridBagConstraints(); gbl = new GridBagLayout(); con.setLayout(gbl); c.fill = GridBagConstraints.BOTH; //下面每个按钮占一行一列 c.weightx = 1.0; makebutton("Button1",gbl,c); makebutton("Button2",gbl,c); makebutton("Button3",gbl,c); c.gridwidth = GridBagConstraints.REMAINDER; //占据本行到结束 makebutton("Button4",gbl,c); //开始布置第二行按钮 c.weightx = 0.0; //重设为默认值 //这里的gridwidth属性仍然是REMINDER,所以占据一整行 makebutton("Button5",gbl,c); //开始布置第三行 c.gridwidth = GridBagConstraints.RELATIVE; //重起一行,占三格 makebutton("Button6",gbl,c); c.gridwidth = GridBagConstraints.REMAINDER; //占据本行到结束 makebutton("Button7",gbl,c); //开始布置第四五行 c.gridwidth = 1; //本单元格占两行一列 c.gridheight = 2; c.weighty = 1; makebutton("Button8",gbl,c); //开始布置其它按钮,他们分别在两行中 c.weighty = 0.0; c.gridwidth = GridBagConstraints.REMAINDER; //占据到本行结束 c.gridheight = 1; //只占一行 makebutton("Button9",gbl,c); makebutton("Button10",gbl,c); //布局设置完毕 jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { new demoGridBagLayout(); } }