Java.swing.JTable

本文转自网易博客:圈圈巷

360地址:http://blog.163.com/zhouyii26@126/

------------原文的分界线--------------------------------

在java桌面级应用系统的开发过程中大部分设计到数据库的软件 我想大部分都会用到JTable这个组建。以下是我在实际操练过程中的一些看法和想法结合参考书籍上的内容所整理的一些东西,希望对初学java的朋友们能有所帮助。

声明:

以下内容为原创,文章参考网络其他代码及文章而作。

 

简单了解

在一般情况下我们都不是在窗口中直接单独使用表格这个组件。而我们常常的做法是将表格这个组件有放在另外一个组件上。这时我们就需要先来了解一下与JTable显示有关的几个类了。

JScrollPane类

DefaultTableModel类

JScrollPane可以产生一个放置表格的组件而且会自动产生竖直方向的滚动条。

用法如下

final JScrollPane scrollPane = new JScrollPane(); no one will only a

       frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

 

       table = new JTable(20,10);

       scrollPane.setViewportView(table);

首先来生成一个JScrollPane的对象然后将该对象添加到窗口的基层面板中以保证可以正常显示这个组件。接下来的两行是给这个组件中添加一个可以显示的20行10列的原始表格。

DefaultTableModel类就相当于一个显示的框架一样来可以用来控制表格显示的样式。以上代码亦可以这样写

final JScrollPane scrollPane = new JScrollPane();

       frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

 

       DefaultTableModel tmd=new DefaultTableModel(20,10);

       table = new JTable(tmd);

       scrollPane.setViewportView(table);

但是我们要对诸多的表格样式控制的话还是借助于DefaultTableModel等不同的model类比较好。

一、表格的初始化 the alongs years and

a)   简单初始化

例如如下程序所示

table = new JTable(20,10);

       scrollPane.setViewportView(table);

第一局中的对象生成是就利用的JTalbe类的构造函数构造出一个20行10列的原始表格来。运行结果如下图所示。

java swing-JTable - 分分点点 - 圈圈巷

我们看到运行的结果中是带有竖直方向的滚动条的。但是并没有我们想看到的表头。二是默认的用A-Z等来表示的象征性的表头。

b)   利用数组

我们知道表格是可以看成一个二维数组的。正好我们可以借助于数组来建立一个N行N列的自定义表格。

例如如下程序所示

String[][] row=new String[20][10];

String[] column={"id","name","eduid","sex","age","birthday","addres","remark"};

      

       DefaultTableModel tmd=new DefaultTableModel(row,column);

       table = new JTable(tmd);

       scrollPane.setViewportView(table);

前面的两行分别定义了一个二维数组和一个以为数组。二维数组用来定义表格的行数和列数。而以为数组则是用来定义表格的表头。(值得注意的是虽然表格最终的列数是由你所定义的表头决定的(如果你定义了两个列的表头不管二维数组中定义的列式多少最终只会显示两列)但是表头的个数一定要不大于二维数组定义的列数)

运行效果如下图所示

  

java swing-JTable - 分分点点 - 圈圈巷
   

可以看到表格中显示了我们定义好的表头。

c)   利用向量

        i.      说说向量

Java类库中提供了一个动态数组类型即vector它可以用来动态的存储数据。且不会造成资源和空间的浪费。常常我们会遇到不知道数据量的大小而无法确定数据存储结构的大小的问题。Vector便可以解决此问题。它会根据你的数据量的大小来自行减小或扩张存储空间。够人性化吧。

       ii.      解决思想

我们可以在设置model类的时候就将model的参数设置为一个vector对象这样一来,就相当于表格中已经被填充了一个向量

我们可以利用向量的特性用一个向量来存储一条记录。

那么有多条记录时。我们便可以利用循环来扩充vector。

最后将记录所在的向量添加到设置model时所产生的向量中(二维向量)。便可以产生一个类似于二维数组的的表格模型。同事根据向量的特性我们对表格数据的操作可以通过对向量的操作来实现。

     iii.      开始

AbstractTableModel类

上面说了不同的model类有不同的用处现在我们来使用AbstractTableModel类

我们首先需要利用AbstractTableModel类类在生产model对象的时候给表格内初始化一个vector对象进去。而AbstractTableModel类本身并没有这个方法的实现所以我们继承AbstractTableModel类来自定义一个类以实现我们需要的功能。则又如下代码

class Table_Model extends AbstractTableModel {

           private Vector content = null;

                   public Table_Model() {

           content = new Vector();

    }

           ..

}

以上代码实现了我们自定义的model类

在这个自定义的model类中我们还会定义一系列的用于对数据操作的方法以实现对表格中数据的操作(增删改查等)

如下代码

public void addRow(String name, boolean sex, String age) {

       Vector v = new Vector();

       v.add(0, new Integer(content.size()));

       v.add(1, name);

       v.add(2, new Boolean(sex));

       v.add(3, age);

       content.add(v);

   }

 

   public void removeRow(int row) {

       content.remove(row);

   }

   public void removeRows(int row, int count) {

       for (int i = 0; i < count; i++) {

          if (content.size() > row) {

              content.remove(row);

          }

       }

   }

..

以上代码中的解释了对表格中的数据添加和删除的操作,而删除中又有单行删除和多行删除。

值得注意的是在AbstractTableModel类中需要通过重写AbstractTableModel类中的getColumnCount和getColumnName方法来实现表头的自定义代码如下

private String[] title_name = { "ID", "姓名", "性别", "年龄" };


public String getColumnName(int col) {

       return title_name[col];

   }

 

   public int getColumnCount() {

       return title_name.length;

   }

效果如下图所示

                     java swing-JTable - 分分点点 - 圈圈巷

以上是填入数据后的效果

java swing-JTable - 分分点点 - 圈圈巷

以上是清除数据后的效果

二、列宽及字体显示样式

a)   相关类

        i.      DefaultTableCellRenderer类 设置单元格中的字体显示方式

       ii.      TableColumn类  设置列宽

b)   使用方法

        i.      重写JTable中的getDefaultRenderer方法来实现对单元格内容显示样式的控制。

       ii.      利用TableColumn的对象可以获取到表格的某一行然后对其宽的进行设置

c)   示例

        i.      设置单元格样式的示例

@Override

   public TableCellRenderer getDefaultRenderer(Class<?> columnClass) {

       DefaultTableCellRenderer tableRenderer = (DefaultTableCellRenderer) super

              .getDefaultRenderer(columnClass);

       // 设置单元格内容居中显示

       tableRenderer.setHorizontalAlignment(DefaultTableCellRenderer.CENTER);//注意这个的CENTER这个系统变量

       return tableRenderer;

   }

以上代码实现了文本居中的操作。

       ii.      设置列宽的示例

public void setAllColumnWidth(int width) {

       int columnCount = getColumnCount();

       for (int i = 0; i < columnCount; i++) {

          TableColumn tableColumn = getColumnModel().getColumn(i);

          tableColumn.setPreferredWidth(width);

       }

   }

以上代码中利用循环对所有列的宽度进行同一的再设置。

三、单元格的可编辑性

要实现此功能需要重新JTable中的isCellEditable方法

这个方法需要一个boolean类型的返回值。我们要做的是将此返回值按照需求设置为true或false即可

如以下示例所示

public boolean isCellEditable(int rowIndex, int columnIndex) {

       if (columnIndex == 0) {

          return false;

       }

       return true;

   }

以上代码实现了处第一列外其他列可编辑的功能。

四、给表格赋值

a)   数组形式的表格赋值

若是数组形式的表格赋值我们需要利用JTable中的setValueAt(Value, row, column)方法。这个方法里有三个参数分别是value为要赋的值,row要赋值的行,column为要赋值的列。

配合循环便可以给多个单元格赋值。

还有一种方法,我们清楚因为表格是由一个二维数组和一个一维数组定义而成。所以我们可以想到是否可以通过对其构成的数组进行赋值已达到对表格赋值的效果。答案是肯定的。我们知道一维数组是用来设置表格表头用的。所以我们只能通过对二维数组进行赋值以达到效果了。

值得注意的是在对表格利用上述方法赋值完毕后又是会出现所赋的值不出现的情况。这时就告诉我们在赋值完毕后最好再次将以下三句代码调用一次已达到表格内容更新的效果从而显示出我们新赋的值。

DefaultTableModel tmd=new DefaultTableModel(row,column);

   table.setModel(tmd);

   scrollPane.setViewportView(table);

b)   Vector形式的表格赋值

根据上面的思想我们不难想到既然利用vector来定义的表格我们自然可以利用对vector里面值进行改变而达到表格的值更新的效果。是的我们确实可以这样。

关于vector的操作可自行参考其他资料。这个类的方法都挺人性化的。

同样在赋值完毕后页需要更新的。table.updateUI();这句就可以。

五、给表格添加事件

a)   先说说

虽然说这个点我们平时很少用到但还是简单说明一下。以备不时之需。

b)   单击事件

直接添加表格鼠标事件table.addMouseListener();就可以了。

c)   双击事件

添加表格鼠标事件后同时监听鼠标单击的次数如下所示

table.addMouseListener(new MouseAdapter() {

              public void mouseClicked(final MouseEvent e) {// 处理出库单的鼠标双击事件

                 if (e.getClickCount() == 2) {

..

       以上代码就可以处理双击事件了。

d)   右击事件

        i.      方法一

table.addMouseListener(new MouseAdapter() {

              public void mouseClicked(final MouseEvent e) {

                 if (e.isMetaDown()) {

..

以上代码就可以处理右击事件。是通过对事件e的类型判别而区分的。

       ii.      方法二

table.addMouseListener(new MouseAdapter() {

              public void mouseClicked(final MouseEvent e) {

                 if (e.getButton() == MouseEvent.BUTTON3) {

..

以上代码也可以实现表格的右击事件。我们注意到方法一中通过对鼠标事件的类判别来区分出右键事件的。而方法二中则是通过对获取到的按键事件的类型判别来区分出右键事件的。应该说方法二的判别更为精确。并且方法二也更为灵敏一些。我个人推荐方法二。

值得注意的是。右键之前要手动选中要右键的行。当然我们可以在右键事件处理中也可以加上这个选中行的处理过程。这个以后再议。

六、给单元格中添加组件

a)   添加下拉列表框JCombobox

这个组件式比较常用的

String[] age = { "16", "17", "18", "19", "20", "21", "22" };

JComboBox com = new JComboBox(age);

TableColumnModel tcm = table.getColumnModel();

tcm.getColumn(3).setCellEditor(new DefaultCellEditor(com));

以上代码实现了在表格的第四列添加了一个以age为选项的列表框。

我们看到,首先是定义要添加的列表框对象。然后利用TableColumnModel生成此类的对象。核心便是利用TableColumnModel类中的setCellEditor方法将列表框添加到表格的列中去。

b)   添加按钮JButton

TableColumn dtc = table.getColumnModel().getColumn(

                 setTableColumn().length - 1);

ButtonColumn del = new ButtonColumn(dtc, "删除");

以上代码实现了在表格的倒数第一列中添加一个删除按钮的功能。

我们看到代码的核心是利用TableColumn类的对象获取到要添加组件的列。然后利用ButtonColumn类将button对象添加到指定列中去。

当然我们也可以将添加JCombobox是的方法变通一下用来添加一个button或其他的组件到表格中去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你提供一个简单的Java.Swing万年历示例代码,如下所示: ```java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class CalendarApp extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; JLabel lblMonth, lblYear; JButton btnPrev, btnNext, btnExit; JTable tblCalendar; JComboBox<String> cmbYear; DefaultTableModel modelCalendar; public CalendarApp() { setTitle("Java Calendar"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(420, 320); lblMonth = new JLabel(); lblYear = new JLabel(); cmbYear = new JComboBox<String>(); btnPrev = new JButton("<<"); btnNext = new JButton(">>"); btnExit = new JButton("Exit"); modelCalendar = new DefaultTableModel() { private static final long serialVersionUID = 1L; public boolean isCellEditable(int rowIndex, int mColIndex) { return false; } }; tblCalendar = new JTable(modelCalendar); tblCalendar.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { int row = tblCalendar.getSelectedRow(); int col = tblCalendar.getSelectedColumn(); int year = Integer.parseInt(cmbYear.getSelectedItem().toString()); int month = lblMonth.getText().equalsIgnoreCase("January") ? 0 : lblMonth.getText().equalsIgnoreCase("February") ? 1 : lblMonth.getText().equalsIgnoreCase("March") ? 2 : lblMonth.getText().equalsIgnoreCase("April") ? 3 : lblMonth.getText().equalsIgnoreCase("May") ? 4 : lblMonth.getText().equalsIgnoreCase("June") ? 5 : lblMonth.getText().equalsIgnoreCase("July") ? 6 : lblMonth.getText() .equalsIgnoreCase("August") ? 7 : lblMonth.getText() .equalsIgnoreCase("September") ? 8 : lblMonth.getText() .equalsIgnoreCase("October") ? 9 : lblMonth .getText() .equalsIgnoreCase( "November") ? 10 : 11; if (evt.getClickCount() == 2) { int day = (int) modelCalendar.getValueAt(row, col); new DayApp(day, month, year); } } }); JScrollPane paneCalendar = new JScrollPane(tblCalendar); paneCalendar.setPreferredSize(new Dimension(300, 200)); JPanel pnlCalendar = new JPanel(null); pnlCalendar.setBorder(BorderFactory.createTitledBorder("Calendar")); btnPrev.addActionListener(this); btnNext.addActionListener(this); cmbYear.addActionListener(this); btnExit.addActionListener(this); pnlCalendar.add(lblMonth); pnlCalendar.add(lblYear); pnlCalendar.add(cmbYear); pnlCalendar.add(btnPrev); pnlCalendar.add(btnNext); pnlCalendar.add(paneCalendar); pnlCalendar.add(btnExit); lblMonth.setBounds(160 - lblMonth.getPreferredSize().width / 2, 25, 100, 25); lblYear.setBounds(10, 225, 80, 20); cmbYear.setBounds(230, 225, 80, 20); btnPrev.setBounds(10, 25, 50, 25); btnNext.setBounds(300, 25, 50, 25); paneCalendar.setBounds(10, 50, 380, 160); btnExit.setBounds(160 - btnExit.getPreferredSize().width / 2, 250, 100, 25); GregorianCalendar cal = new GregorianCalendar(); int year = cal.get(GregorianCalendar.YEAR); int month = cal.get(GregorianCalendar.MONTH); int day = cal.get(GregorianCalendar.DAY_OF_MONTH); lblMonth.setText(String.format("%tB", cal)); lblYear.setText(String.format("%s", year)); for (int i = year - 100; i <= year + 100; i++) { cmbYear.addItem(String.format("%s", i)); } cmbYear.setSelectedItem(String.format("%s", year)); tblCalendar.getParent().setBackground(tblCalendar.getBackground()); tblCalendar.getTableHeader().setResizingAllowed(false); tblCalendar.getTableHeader().setReorderingAllowed(false); tblCalendar.setColumnSelectionAllowed(true); tblCalendar.setRowSelectionAllowed(true); tblCalendar.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); for (int i = 0; i < 7; i++) { modelCalendar.addColumn(new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }[i]); } tblCalendar.setRowHeight(38); modelCalendar.setColumnCount(7); modelCalendar.setRowCount(6); for (int i = year - 100; i <= year + 100; i++) { cmbYear.addItem(String.format("%s", i)); } refreshCalendar(month, year); add(pnlCalendar, BorderLayout.CENTER); setVisible(true); } public void refreshCalendar(int month, int year) { String[] months = new String[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; int nod, som; btnPrev.setEnabled(true); btnNext.setEnabled(true); if (month == 0 && year <= Calendar.getInstance().get(Calendar.YEAR) - 100) { btnPrev.setEnabled(false); } if (month == 11 && year >= Calendar.getInstance().get(Calendar.YEAR) + 100) { btnNext.setEnabled(false); } lblMonth.setText(months[month]); lblMonth.setBounds(160 - lblMonth.getPreferredSize().width / 2, 25, 100, 25); cmbYear.setSelectedItem(String.format("%s", year)); GregorianCalendar cal = new GregorianCalendar(year, month, 1); nod = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH); som = cal.get(GregorianCalendar.DAY_OF_WEEK); for (int i = 0; i < 6; i++) { for (int j = 0; j < 7; j++) { modelCalendar.setValueAt(null, i, j); } } for (int i = 1; i <= nod; i++) { int row = new Integer((i + som - 2) / 7); int column = (i + som - 2) % 7; modelCalendar.setValueAt(i, row, column); } } public static void main(String[] args) { new CalendarApp(); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(btnPrev)) { int year = Integer.parseInt(cmbYear.getSelectedItem().toString()); int month = lblMonth.getText().equalsIgnoreCase("January") ? 11 : lblMonth.getText().equalsIgnoreCase("February") ? 0 : lblMonth.getText().equalsIgnoreCase("March") ? 1 : lblMonth.getText().equalsIgnoreCase("April") ? 2 : lblMonth.getText().equalsIgnoreCase("May") ? 3 : lblMonth.getText().equalsIgnoreCase("June") ? 4 : lblMonth.getText().equalsIgnoreCase("July") ? 5 : lblMonth.getText() .equalsIgnoreCase("August") ? 6 : lblMonth.getText() .equalsIgnoreCase("September") ? 7 : lblMonth.getText() .equalsIgnoreCase("October") ? 8 : lblMonth.getText() .equalsIgnoreCase( "November") ? 9 : 10; if (month == 0) { month = 11; year--; } else { month--; } refreshCalendar(month, year); } else if (e.getSource().equals(btnNext)) { int year = Integer.parseInt(cmbYear.getSelectedItem().toString()); int month = lblMonth.getText().equalsIgnoreCase("January") ? 11 : lblMonth.getText().equalsIgnoreCase("February") ? 0 : lblMonth.getText().equalsIgnoreCase("March") ? 1 : lblMonth.getText().equalsIgnoreCase("April") ? 2 : lblMonth.getText().equalsIgnoreCase("May") ? 3 : lblMonth.getText().equalsIgnoreCase("June") ? 4 : lblMonth.getText().equalsIgnoreCase("July") ? 5 : lblMonth.getText() .equalsIgnoreCase("August") ? 6 : lblMonth.getText() .equalsIgnoreCase("September") ? 7 : lblMonth.getText() .equalsIgnoreCase("October") ? 8 : lblMonth.getText() .equalsIgnoreCase( "November") ? 9 : 10; if (month == 11) { month = 0; year++; } else { month++; } refreshCalendar(month, year); } else if (e.getSource().equals(cmbYear)) { int year = Integer.parseInt(cmbYear.getSelectedItem().toString()); int month = lblMonth.getText().equalsIgnoreCase("January") ? 11 : lblMonth.getText().equalsIgnoreCase("February") ? 0 : lblMonth.getText().equalsIgnoreCase("March") ? 1 : lblMonth.getText().equalsIgnoreCase("April") ? 2 : lblMonth.getText().equalsIgnoreCase("May") ? 3 : lblMonth.getText().equalsIgnoreCase("June") ? 4 : lblMonth.getText().equalsIgnoreCase("July") ? 5 : lblMonth.getText() .equalsIgnoreCase("August") ? 6 : lblMonth.getText() .equalsIgnoreCase("September") ? 7 : lblMonth.getText() .equalsIgnoreCase("October") ? 8 : lblMonth.getText() .equalsIgnoreCase( "November") ? 9 : 10; refreshCalendar(month, year); } else if (e.getSource().equals(btnExit)) { System.exit(0); } } } class DayApp extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; JLabel lblDay, lblMonth, lblYear; JButton btnSave, btnCancel; JTextArea txtEvent; JPanel pnlDay; public DayApp(int day, int month, int year) { setTitle("Day Event"); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setSize(300, 200); setLocationRelativeTo(null); lblDay = new JLabel(String.format("%s", day)); lblMonth = new JLabel(String.format("%tB", new GregorianCalendar(year, month, 1))); lblYear = new JLabel(String.format("%s", year)); txtEvent = new JTextArea(); pnlDay = new JPanel(null); pnlDay.setBorder(BorderFactory.createTitledBorder("Event")); btnSave = new JButton("Save"); btnCancel = new JButton("Cancel"); btnSave.addActionListener(this); btnCancel.addActionListener(this); lblDay.setBounds(140 - lblDay.getPreferredSize().width / 2, 25, 100, 25); lblMonth.setBounds(10, 60, 100, 25); lblYear.setBounds(230, 60, 50, 25); txtEvent.setBounds(20, 90, 250, 50); btnSave.setBounds(50, 150, 80, 25); btnCancel.setBounds(160, 150, 80, 25); pnlDay.add(lblDay); pnlDay.add(lblMonth); pnlDay.add(lblYear); pnlDay.add(txtEvent); pnlDay.add(btnSave); pnlDay.add(btnCancel); add(pnlDay); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(btnSave)) { JOptionPane.showMessageDialog(this, "Event saved successfully!"); dispose(); } else if (e.getSource().equals(btnCancel)) { dispose(); } } } ``` 运行这个代码,你会看到一个简单的Java.Swing万年历。你可以选择年份和月份,然后浏览日历中的日期。你还可以双击一个日期来创建一个事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值