服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

让界面更加绚丽 java se 6.0四种新功能


  在上一篇中我介绍了java se 6在gui上的部分改进。在这篇文章中我接着介绍另外几种新的gui功能。这些功能是:

  ?带有排序和过滤功能的jtable。

  ?增强的jtabbedpane组件

  ?增强的打印功能

  ?增强的拖放功能

  带有排序和过滤功能的jtable

  在java se 6中除了java.awt被更新外,javax.swing同时也有了很大的改进。在c/s程序中我们会经常使用到"表"。如我们可以在查询数据库后将查询结果显示在表格中。在java中显示表格使用的是jtable类。在以前的版本中,jtable只能简单地显示数据,并没有什么附加的处理功能,而在java se 6中的jtable增加了排序和过滤功能。用户可以单击列头进行排序,也可以根据某一列来过滤表中的数据。

  为了使jtable可以对数据进行,必须将rowsorter类和jtable进行关联。rowsorter是一个抽象类,它负责将jtable中的数据映射成可排序的数据。在真正使用时,我们将直接使用rowsorter的子类tablerowsorter。下面的代码显示了如何将tablerowsorter类和jtable相关联。

tablemodel model = new defaulttablemodel(rows, columns);
jtable table = new jtable(model);
rowsorter sorter = new tablerowsorter(model);
table.setrowsorter(sorter);

  上面代码首先建立一个tablemodel,然后将这个tablemodel的实例同时传递给了jtable和rowsorter。下面是一个使用jtable排序的简单的例子。

import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;

public class testsortedtable
{
 public static void main(string args[])
 {
  jframe frame = new jframe("jtable的排序测试");
  frame.setdefaultcloseoperation(jframe.exit_on_close);
  // 表格中显示的数据
  object rows[][] =
   {
   { "王明", "中国", 44 },
   { "姚明", "中国", 25 },
   { "赵子龙", "西蜀", 1234 },
   { "曹操", "北魏", 2112 },
   { "bill gates", "美国", 45 },
   { "mike", "英国", 33 } };
  string columns[] =
   { "姓名", "国籍", "年龄" };
  tablemodel model = new defaulttablemodel(rows, columns);
  jtable table = new jtable(model);
  rowsorter<tablemodel> sorter = new tablerowsorter<tablemodel>(model);
  table.setrowsorter(sorter);
  jscrollpane pane = new jscrollpane(table);
  frame.add(pane, borderlayout.center);
  frame.setsize(300, 150);
  frame.setvisible(true);
 }
}

  图1和图2分别是按"姓名"进行升序和降序排列的显示结果。

让界面更加绚丽 java se 6.0四种新功能(图一)
图1 按"姓名"升序显示
让界面更加绚丽 java se 6.0四种新功能(图二)
图2 按"姓名"降序显示

  图3显示的是按"年龄"进行降序排列。但我们发现一个奇怪的问题,就是"年龄"字段并不是按数值类型进行排序的,而是按字符类型进行排序的。

让界面更加绚丽 java se 6.0四种新功能(图三)
图3 按年龄降序显示

  出现这种情况是因为在默认情况下defaulttablemodal的列是object类型。而要想使jtable按数值进行排序,必须要覆盖defaulttablemodal的getcolumnclass方法。

tablemodel model = new defaulttablemodel(rows, columns)
{
 public class getcolumnclass(int column)
 {
  class returnvalue;
  if ((column >= 0) && (column < getcolumncount()))
  {
   returnvalue = getvalueat(0, column).getclass();
  }
  else
  {
   returnvalue = object.class;
  }
  return returnvalue;
 }
};

  图4显示了按"年龄"进行排序的界面,看看,是不是按数值进行排序了。

让界面更加绚丽 java se 6.0四种新功能(图四)
图4 按数值类型进行排序

  下面让我们来看看来何使用jtable进行过滤。我们可以通过convertrowindextomodel方法进行过滤。下面的代码加在一个按钮中添加事件代码调用jtable的过滤功能。

button.addactionlistener(new actionlistener()
{
 public void actionperformed(actionevent e)
 {
  string text = filtertext.gettext();
  if (text.length() == 0)
  {
   sorter.setrowfilter(null);
  }
  else
  {
   sorter.setrowfilter(rowfilter.regexfilter(text));
  }
 }
});

  上面的代码并没有调用convertrowindextomodel()方法,如果调用它,你就可以在表中进行相应的操作。

  在jtable中通过抽象类rowfilter类对行进行过滤。和排序不同,你可以不建立它们的子类,而使用这个抽象类的6个静态方法。

  ?andfilter
  ?datefilter(rowfilter.comparisontype type, date date, int... indices)
  ?notfilter(rowfilter<m,i> filter)
  ?numberfilter(rowfilter.comparisontype type, number number, int... indices)
  ?orfilter
  ?regexfilter(string regex, int... indices)

  其中andfilter()、orfilter()以及notfilter()方法的功能是将当前的过滤条件和其它的过滤条件进行组合。如在同时比较日期和数值时需要将日期过滤和数值过滤进行组合。这些组合是非常简单的。

  rowfilter的类型比较允许你进行4种关系的比较,等于、不等于、大于或小于。我们可以通过指定某一列进行过滤,也可以对所有的列进行过滤。这其中最为有趣的也许是正则表达式过滤(regular expression filter,或简称为regex filter)。使用这个过滤器可以对表中数据进行更高级的过滤。下面是实现一个简单过滤器的代码。

import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;

public class testfilter
{
 public static void main(string args[])
 {
  jframe frame = new jframe("jtable的过滤测试");
  frame.setdefaultcloseoperation(jframe.exit_on_close);
  object rows[][] =
  {
   { "王明", "中国", 44 },
   { "姚明", "中国", 25 },
   { "赵子龙", "西蜀", 1234 },
   { "曹操", "北魏", 2112 },
   { "bill gates", "美国", 45 },
   { "mike", "英国", 33 } };
  string columns[] =
   { "姓名", "国籍", "年龄" };
  tablemodel model = new defaulttablemodel(rows, columns)
  {
   public class getcolumnclass(int column)
   {
    class returnvalue;
    if ((column >= 0) && (column < getcolumncount()))
    {
     returnvalue = getvalueat(0, column).getclass();
    }
    else
    {
     returnvalue = object.class;
    }
    return returnvalue;
   }
  };
  final jtable table = new jtable(model);
  final tablerowsorter<tablemodel> sorter = new tablerowsorter<tablemodel>(model);
  table.setrowsorter(sorter);
  jscrollpane pane = new jscrollpane(table);
  frame.add(pane, borderlayout.center);
  jpanel panel = new jpanel(new borderlayout());
  jlabel label = new jlabel("过滤");
  panel.add(label, borderlayout.west);
  final jtextfield filtertext = new jtextfield("");
  panel.add(filtertext, borderlayout.center);
  frame.add(panel, borderlayout.north);
  jbutton button = new jbutton("过滤");
  button.addactionlistener(new actionlistener()
  {
   public void actionperformed(actionevent e)
   {
    string text = filtertext.gettext();
    if (text.length() == 0)
    {
     sorter.setrowfilter(null);
    }
    else
    {
     sorter.setrowfilter(rowfilter.regexfilter(text));
    }
   }
  });
  frame.add(button, borderlayout.south);
  frame.setsize(300, 250);
  frame.setvisible(true);
 }
}

  图5是上面程序的运行界面。

让界面更加绚丽 java se 6.0四种新功能(图五)
图 5
增强的jtabbedpane组件

  jtabbedpane组件为我们提供了一种非常好的方法在窗体上显示很多的控件。我们可以将不同类别的控件放到不同的tab页上,然后通过需要点击相应的tab页。在传统的tab页上只能防止文本的图标。而在java se 6中使我们可以直接将控件放到tab上。我们可以通过settabcomponentat方法将控件放到tab上。这个方法有两个参数,一个是tab的索引,另一个是要放置的对象。

jtabbedpane pane = new jtabbedpane();
pane.settabcomponentat(1, component);

  在jtabbedpane控件中有3个常用的方法,settabcomponentat(int index, component comp), gettabcomponentat(int index)和indexoftabcomponent(component)。最后一个方法将替换tab上的控件。下面的代码是一个关于jtabbedpane控件的演示。

import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;

public class testtabbedpane
{
 static void addit(jtabbedpane tabbedpane, string text)
 {
  jlabel label = new jlabel(text);
  jbutton button = new jbutton(text);
  jpanel panel = new jpanel();
  panel.add(label);
  panel.add(button);
  tabbedpane.addtab(text, panel);
  if(text.equals("tab4"))
   tabbedpane.settabcomponentat(tabbedpane.gettabcount() - 1,
new jtextfield("插入了文本控件"));
  else
   tabbedpane.settabcomponentat(tabbedpane.gettabcount() - 1,button);
 }
 public static void main(string args[])
 {
  jframe f = new jframe("jtabbedpane演示");
  f.setdefaultcloseoperation(jframe.exit_on_close);
  jtabbedpane tabbedpane = new jtabbedpane();
  addit(tabbedpane, "tab1");
  addit(tabbedpane, "tab2");
  addit(tabbedpane, "tab3");
  addit(tabbedpane, "tab4");
  addit(tabbedpane, "tab5");
  f.add(tabbedpane, borderlayout.center);
  f.setsize(400, 200);
  f.setvisible(true);
 }
}

  图6是显示界面,其中在tab4上插入了一个文本控件,在tab1至tab5上各插入了一个按钮控件。

让界面更加绚丽 java se 6.0四种新功能(图六)
图6 jtabbedpane演示
增强的打印功能

  自从java se 5开始,sun就对控件的打印功能进行了加强。如jtextfield、jtextarea等。在java se 6中sun为打印增加了分页功能。我们只需要调用jtextfield或jtextarea的print方法就可以调用打印对话框。下面是一段测试代码。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;

public class textprint
{
 public static void main(final string args[])
 {
  jframe frame = new jframe("打印测试");
  frame.setdefaultcloseoperation(jframe.exit_on_close);
  final jtextarea textarea = new jtextarea();
  jscrollpane pane = new jscrollpane(textarea);
  frame.add(pane, borderlayout.center);
  textarea.settext("打印内容.../r/n可以分页!" );
  jbutton button = new jbutton("打印");
  frame.add(button, borderlayout.south);
  actionlistener listener = new actionlistener()
  {
   public void actionperformed(actionevent e)
   {
    try
    {
     textarea.print();
    }
    catch (printerexception pe)
    {
     system.err.println("打印失败...");
    }
   }
  };
  button.addactionlistener(listener);
  frame.setsize(250, 150);
  frame.setvisible(true);
 }
}

  图7和图8分别是打印对话框和设置对话框,点击"打印"按钮后弹出如图8的对话框。

让界面更加绚丽 java se 6.0四种新功能(图七)
图7 打印界面
让界面更加绚丽 java se 6.0四种新功能(图八)
图8 设置对话框

  虽然提供了打印设置对话框,但我们并无法设置如页眉(角)等信息,幸运的是print的一个重载为我们提供了这个功能。下面是这个方法的参数。

public boolean print(messageformat headerformat,
messageformat footerformat,
boolean showprintdialog,
printservice service,
printrequestattributeset attributes,
boolean interactive)
增强的拖放功能

  在java se 6中的拖放功能得到了增强,这主要表现在两个方面。

  ?可以定制拖放模式。

  可以在拖放的过程中加入其它的辅助信息。 首先需要通过jlist、jtable等控件的setdropmode()方法来设置一个拖动模式。所有的控件都可以使用user_selection模式。这个模式在以前的java se版本中就有。这也是默认的拖放模式。

  jlist、jtable和jlist都支持on模式,这个模式允许你将对象拖到其它项的上方。而insert模式允许将一个对象插入在其它项之间。而on_or_insert模式是前3种模式的组合。下面的代码将演示一个拖动的例子。

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.tree.*;

public class testdrapdrop
{
 public static void main(string args[])
 {
  jframe f = new jframe("拖放测试");
  f.setdefaultcloseoperation(jframe.exit_on_close);
  jpanel top = new jpanel(new borderlayout());
  jlabel draglabel = new jlabel("拖我:");
  jtextfield text = new jtextfield();
  text.setdragenabled(true);
  top.add(draglabel, borderlayout.west);
  top.add(text, borderlayout.center);
  f.add(top, borderlayout.north);
  final jtree tree = new jtree();
  final defaulttreemodel model = (defaulttreemodel) tree.getmodel();
  tree.settransferhandler(new transferhandler()
  {
   public boolean canimport(transferhandler.transfersupport support)
   {
    if (!support.isdataflavorsupported(dataflavor.stringflavor) || !support.isdrop())
    {
     return false;
    }
    jtree.droplocation droplocation = (jtree.droplocation) suppor.getdroplocation();
    return droplocation.getpath() != null;
   }
   public boolean importdata(transferhandler.transfersupport support)
   {
    if (!canimport(support))
    {
     return false;
    }
    jtree.droplocation droplocation = (jtree.droplocation) support.getdroplocation();
    treepath path = droplocation.getpath();
    transferable transferable = support.gettransferable();
    string transferdata;
    try
    {
     transferdata = (string) transferable .gettransferdata(dataflavor.stringflavor);
    }
    catch (ioexception e)
    {
     return false;
    }
    catch (unsupportedflavorexception e)
    {
     return false;
    }
    int childindex = droplocation.getchildindex();
    if (childindex == -1)
    {
     childindex = model.getchildcount(path.getlastpathcomponent());
    }
    defaultmutabletreenode newnode = new defaultmutabletreenode( transferdata);
    defaultmutabletreenode parentnode = (defaultmutabletreenode) path.getlastpathcomponent();
    model.insertnodeinto(newnode, parentnode, childindex);
    treepath newpath = path.pathbyaddingchild(newnode);
    tree.makevisible(newpath);
    tree.scrollrecttovisible(tree.getpathbounds(newpath));
    return true;
   }
  });
  jscrollpane pane = new jscrollpane(tree);
  f.add(pane, borderlayout.center);
  jpanel bottom = new jpanel();
  jlabel combolabel = new jlabel("dropmode");
  string options[] ={ "use_selection", "on", "insert", "on_or_insert" };
  final dropmode mode[] =
   {dropmode.use_selection, dropmode.on, dropmode.insert, dropmode.on_or_insert };
  final jcombobox combo = new jcombobox(options);
  combo.addactionlistener(new actionlistener()
  {
   public void actionperformed(actionevent e)
   {
    int selectedindex = combo.getselectedindex();
    tree.setdropmode(mode[selectedindex]);
   }
  });
  bottom.add(combolabel);
  bottom.add(combo);
  f.add(bottom, borderlayout.south);
  f.setsize(300, 400);
  f.setvisible(true);
 }

  图9为拖动程序的运行界面。在上面的文本框里输入相应的文本,然后将其选择再拖动到下方的树中。

让界面更加绚丽 java se 6.0四种新功能(图九)
图9 拖动界面

扫描关注微信公众号