Swing基础知识学习

高级Swing学习

一.列表

1.1 JList构件

JList———————显示对象列表并且允许用户选择一个或多个项的组件。单独的模型 ListModel 维护列表的内容。

String word[] = {"1","2","3"};

JList list = new JList(word);

一般JList 都是滚动的,但是java有滚动面板,普通组件不能自动滚动

JScollPane scollPane = new JScollPane(list );

然后把滚动面板插入都外围面板上。

默认JList能显示8个选项,但是可以setVisibleRowCount(8)设置显示。

JList.VERTICAL-------------垂直排放所有选项

JList.VERTICAL_WRAP--------如果选项超过可视列,开始新的一列

JList.HORIZONTAL_WRAP------ 如果选项超过可视行,开始新的一行

public void setSelectionMode(int selectionMode) --------------对选择模式进行设置

如果允许多选,列表返回的值

Object[] o = list.getSelectedValues();

如果不允许多选,返回的值

String s = (String)list.getSelectedValue();

package swing.JList;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class ListFrame extends JFrame {
	
	private static final int DEFAULT_WIDTH = 400;
	private static final int DEFAULT_HEIGHT = 300;
	private JPanel listPanel;
	private JList wordList;
	private JLabel label;
	private JPanel buttonPanel;
	private ButtonGroup group;
	private String prefix = "The ";
	private String suffix = "fox jumps over the lazy dog.";
	
	public ListFrame(){
		setTitle("ListTest");
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		
		String[] words={"1","2","123","36","72","46","67","15","54","34","23","ds","22","12"};
		wordList = new JList(words);
		wordList.setVisibleRowCount(4);
		JScrollPane scrollPane = new JScrollPane(wordList);
		
		listPanel = new JPanel();
		listPanel.add(scrollPane);
		
		wordList.addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent e) {
				// TODO Auto-generated method stub
				Object[] values =  wordList.getSelectedValues();
				
				StringBuilder text = new StringBuilder(prefix);
				for(int i=0;i<values.length;i++){
					String word = (String)values[i];
					text.append(word);
					text.append(" ");
				}
				text.append(suffix);
				label.setText(text.toString());
			}
		});
		
		buttonPanel = new JPanel();
		group = new ButtonGroup();
		makeButton("Vertical", JList.VERTICAL);
		makeButton("Vertical Wrap", JList.VERTICAL_WRAP);
		makeButton("Horizontial Wrap", JList.HORIZONTAL_WRAP);
		add(listPanel,BorderLayout.NORTH);
		label = new JLabel(prefix+suffix);
		add(label,BorderLayout.CENTER);
		add(buttonPanel,BorderLayout.SOUTH);
	}
	
	private void makeButton(String label, final int o){
		JRadioButton button = new JRadioButton(label);
		buttonPanel.add(button);
		if(group.getButtonCount()==0){
			button.setSelected(true);
		}
			group.add(button);
			button.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					wordList.setLayoutOrientation(o);
					listPanel.revalidate();
				}
			});
	}
}

 1.2 列表模式

JList显示的列表是固定不变的,但是现实生活中式可变的,但是JList并没有对列表增删的操作,这是因为JList只是负责数据的可视化外观,而是用列表模型来获取数据的。

public interface ListModel{

        int getSize();

        Object getElementAt(int index);

        addListDataListener(ListDataListener l);         //增加元素时,通知JList

        removeListDataListener(ListDataListener l);   //删除元素时,通知JList

}

这个接口并没有指定数据时怎么样存储的,而且它也没有强制要求这些对象被存储,无论何时getElementAt(),它都会重新计算获得,这样的好处是如果一个数组很大,那样这样的设计是很有用的。

1.3 值的插入和移除

不能直接编辑列表集合,必须先获得列表模型

ListModel model = list.getModel();

 

1.4 值的绘制

JList不仅仅现实字符串列表,也可以显示icon对象填充的数组或者向量,只需要在JList安装一个自定义的列表单元格绘制器。

/******************************/
JList fontList = new JList(fonts.toArray());
      fontList.setVisibleRowCount(4);
      fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      fontList.setCellRenderer(new FontCellRenderer());
/******************************/

 

class FontCellRenderer extends JPanel implements ListCellRenderer
{  
   public Component getListCellRendererComponent(JList list, Object value, int index, 
      boolean isSelected, boolean cellHasFocus)
   {  
      font = (Font) value;
      background = isSelected ? list.getSelectionBackground() : list.getBackground();
      foreground = isSelected ? list.getSelectionForeground() : list.getForeground();
      return this;
   }

   public void paintComponent(Graphics g)
   {                 
      String text = font.getFamily();
      FontMetrics fm = g.getFontMetrics(font);
      g.setColor(background);
      g.fillRect(0, 0, getWidth(), getHeight());
      g.setColor(foreground);
      g.setFont(font);
      g.drawString(text, 0, fm.getAscent());
   }
   
   public Dimension getPreferredSize()
   {  
      String text = font.getFamily();
      Graphics g = getGraphics();
      FontMetrics fm = g.getFontMetrics(font);
      return new Dimension(fm.stringWidth(text), fm.getHeight());
   }

   private Font font;
   private Color background;
   private Color foreground;
}

 Component getListCellRendererComponent(JList list,       //正在绘制的列表
                                       Object value,           //由 list.getModel().getElementAt(index) 返回的值。
                                       int index,                 //单元格索引
                                       boolean isSelected,
                                       boolean cellHasFocus //如果指定的单元格拥有焦点,则为 true

                   )

 

二.树

一棵树是由一些节点(node)组成,每个节点要么是叶节点或者是孩子节点除了根节点(root node),每个节点都有唯一父节点,一棵树有且唯一个根节点,有时每棵树都有自己的根节点,那么它是森林

2.1 简单的树

JTree遵循模型——视图——控制器模式,构造一个JTree组件,需要提供一个树模型

JTree tree= new JTree(new TreeModel());

然而树模型是由节点组成的TreeNode.

TreeModel接口的默认实现类是DefaultTreeModel,TreeNode的默认实现类是DefaultMutableTreeNode.

TreeNode root=...;

DefaultTreeModel defaultTreeModel = new defaultTreeModel(root);

DefaultMutableTreeNode root= new DefaultMutableTreeNode("root");

DefaultMutableTreeNode child1= new DefaultMutableTreeNode("child1");

root.add(child1);

从上面不难看出,树模型就是由根节点构成的模型,然后将所有节点贯穿起来,最后形成树模型。

package swing.simple;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;

public class SimpleTree extends JFrame {

	public SimpleTree() {
		setTitle("Simple Tree");
		setSize(400, 400);
		// TreeModel model = new DefaultTreeModel():
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
		DefaultMutableTreeNode city1 = new DefaultMutableTreeNode("北京");

		DefaultMutableTreeNode city2 = new DefaultMutableTreeNode("安徽");

		DefaultMutableTreeNode city3 = new DefaultMutableTreeNode("上海");

		DefaultMutableTreeNode city11 = new DefaultMutableTreeNode("海淀");

		DefaultMutableTreeNode city12 = new DefaultMutableTreeNode("朝阳");

		DefaultMutableTreeNode city21 = new DefaultMutableTreeNode("安庆");

		DefaultMutableTreeNode city22 = new DefaultMutableTreeNode("合肥");

		root.add(city1);
		root.add(city2);
		root.add(city3);
		city1.add(city11);
		city1.add(city12);
		city2.add(city21);
		city2.add(city22);

		TreeModel model = new DefaultTreeModel(root);

		JTree tree = new JTree(model);

		add(new JScrollPane(tree));
	}

}

 要显示这些树,结点绘制器需要绘制三个图标,一个是叶子结点图标,一个闭合的文件图标,还有一个开启的文件夹图标。有时候我们添加一个结点时,根本不知道它是否还有子节点。这时,你可以设置

node.setAllowsChildren(true);然后绘制图标时,告诉模型需要子节点,mode.setAskssetAllowsChildren(true);

 

编辑树和树的路径

JTree能处理的实际上不是树的结点,而是树的路径。TreePath管理树路径情况。

TreePath path =  tree.getSelectionPath();

DefaultMutableTreeNode node = (DefaultMutableTreeNode )path.getLastPathComponent();

现在你拥有了当前结点,那么如果使用node.add(newNode)来编辑结点,是行不通的,因为它只是更新了模型,而视图还没有被更新,所以需要通知视图也要更新。不过有更简单的方法。

public void model.insertNodeInto(MutableTreeNode newChild,  //新结点
                           MutableTreeNode parent,                                //当前结点
                           int index)                                                         //位置

class TreeEditFrame extends JFrame {
	public TreeEditFrame() {
		setTitle("TreeEditTest");
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

		// construct tree

		TreeNode root = makeSampleTree();
		model = new DefaultTreeModel(root);
		tree = new JTree(model);
		tree.setEditable(true);

		// add scroll pane with tree

		JScrollPane scrollPane = new JScrollPane(tree);
		add(scrollPane, BorderLayout.CENTER);

		makeButtons();
	}

	public TreeNode makeSampleTree() {
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("World");
		DefaultMutableTreeNode country = new DefaultMutableTreeNode("USA");
		root.add(country);
		DefaultMutableTreeNode state = new DefaultMutableTreeNode("California");
		country.add(state);
		DefaultMutableTreeNode city = new DefaultMutableTreeNode("San Jose");
		state.add(city);
		city = new DefaultMutableTreeNode("San Diego");
		state.add(city);
		state = new DefaultMutableTreeNode("Michigan");
		country.add(state);
		city = new DefaultMutableTreeNode("Ann Arbor");
		state.add(city);
		country = new DefaultMutableTreeNode("Germany");
		root.add(country);
		state = new DefaultMutableTreeNode("Schleswig-Holstein");
		country.add(state);
		city = new DefaultMutableTreeNode("Kiel");
		state.add(city);
		return root;
	}

	/**
	 * Makes the buttons to add a sibling, add a child, and delete a node.
	 */
	public void makeButtons() {
		JPanel panel = new JPanel();
		JButton addSiblingButton = new JButton("Add Sibling");
		addSiblingButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree
						.getLastSelectedPathComponent();

				if (selectedNode == null)
					return;

				DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode
						.getParent();

				if (parent == null)
					return;

				DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
						"New");

				int selectedIndex = parent.getIndex(selectedNode);
				model.insertNodeInto(newNode, parent, selectedIndex + 1);

				// now display new node

				TreeNode[] nodes = model.getPathToRoot(newNode);
				TreePath path = new TreePath(nodes);
				tree.scrollPathToVisible(path);
			}
		});
		panel.add(addSiblingButton);

		JButton addChildButton = new JButton("Add Child");
		addChildButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree
						.getLastSelectedPathComponent();

				if (selectedNode == null)
					return;

				DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
						"New");
				model.insertNodeInto(newNode, selectedNode, selectedNode
						.getChildCount());

				// now display new node

				TreeNode[] nodes = model.getPathToRoot(newNode);
				TreePath path = new TreePath(nodes);
				tree.scrollPathToVisible(path);
			}
		});
		panel.add(addChildButton);

		JButton deleteButton = new JButton("Delete");
		deleteButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree
						.getLastSelectedPathComponent();

				if (selectedNode != null && selectedNode.getParent() != null)
					model.removeNodeFromParent(selectedNode);
			}
		});
		panel.add(deleteButton);
		add(panel, BorderLayout.SOUTH);
	}

	private DefaultTreeModel model;
	private JTree tree;
	private static final int DEFAULT_WIDTH = 400;
	private static final int DEFAULT_HEIGHT = 200;
}

 

2.2 结点枚举

有时为了查找一个结点,必须遍历树的。DefaultMutableTreeNode可以使用广度优先优先或者深度优先方查询。

深度优先查询也叫后序遍历,先遍历子节点,然后访问父节点。广度优先先枚举父节点,然后才是子节点。

public DefaultMutableTreeNode findUserObject(Object userObject){
   Enumration e = root.breadthFirstEnumration();
   while(e.hasMoreElements()){
       DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement();
       if(node.getUserObject.equals(userObject)){
              return node;
      }
   }
    return null;
}

 2.3 绘制结点

 绘制结点设计到结点的字体以及显示的图标,这些都是由树单元格绘制器来实现的。默认下JTree由DefaultTreeCellRenderer来绘制的。另外它不能绘制外围的展开和关闭的“把手”图标。

 

可以通过以下三种方式来显示外观:

  • 可以使用DefaultTreeCellRenderer改变结点的字体、图标以及北京颜色。适用所有节点。
		
		DefaultTreeCellRenderer render = new DefaultTreeCellRenderer();
		render.setLeafIcon(new ImageIcon("dfa.gif"));
		render.setOpenIcon(new ImageIcon("dfa.gif"));
		tree.setCellRenderer(render);
  • 可以安装一个继承DefaultTreeCellRenderer的类,来改变外观。

           

class MyTreeCellRenderer extends DefaultTreeCellRenderer{
	
	 public Component getTreeCellRendererComponent(JTree tree, Object value,
			  boolean sel,
			  boolean expanded,
			  boolean leaf, int row,
			  boolean hasFocus) {
		 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
		 DefaultMutableTreeNode node  = (DefaultMutableTreeNode)value;
		//look at node.getUserObject();
		// Font font = ...expanded;
		 return this;
	 }
}

  

  • 可以安装一个实现TreeCellRenderer的接口,来改变外观。

2.4 监听树事件

监听树事件实现的是TreeSelectionListener接口。它有一个单一的方法void valueChang(TreeSelectionEvent e)

tree.addTreeSelectionListener(new TreeSelectionListener());

JTree适用TreeSelectionModel来管理结点的选择(单一,多个,连续)。

要找出当前选项集合:TreePath[] selectionPath = tree.getSelectionPaths();

如果限制了智能单项选,择那么:TreePath selectionPath = tree.getSelectionPath();

注意的是TreeSelectionEvent有一个getPaths(),但是这个只是变化的选项集合,不是当前选项集合。

 

 tree.addTreeSelectionListener(new
         TreeSelectionListener()
         {
            public void valueChanged(TreeSelectionEvent event)
            {  
               // the user selected a different node--update description
               TreePath path = tree.getSelectionPath();
               if (path == null) return;
               DefaultMutableTreeNode selectedNode 
                  = (DefaultMutableTreeNode) path.getLastPathComponent();
               Class c = (Class) selectedNode.getUserObject();
               String description = getFieldDescription(c);
               textArea.setText(description);
            }
         });
      int mode = TreeSelectionModel.SINGLE_TREE_SELECTION;
      tree.getSelectionModel().setSelectionMode(mode);

 2.5 定制树模型(省略,以后研究学习)

 

三.表格

3.1 JTable 控件

JTable和树一样,它只是显示外观,数据通过表格模型加载。

Object[][] a={{"1","2"},{"21","22"}};

String name = {"num1","num2"};

JTable jt = new JTable(a,name);

 

3.2 表格模型

AbstractTableModel是表格模型的实现,它仅仅需要三个方法即可:

public int getRowCount();

public int getColumnCount();

public Object getValueAt(int row,int column);

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值