Swing 使用 JTable詳解
示例 1 : 基本表格
顯示一個(gè)Table需要兩組數(shù)據(jù)
- 一維數(shù)組: String[]columnNames 表示表格的標(biāo)題
- 二維數(shù)組: String[][] heros 表格中的內(nèi)容
默認(rèn)情況下拒课,表格的標(biāo)題是不會(huì)顯示出來了孕豹,除非使用了JScrollPane
package gui;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTable;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
// 表格上的title
String[] columnNames = new String[] { "id", "name", "hp", "damage" };
// 表格中的內(nèi)容喉脖,是一個(gè)二維數(shù)組
String[][] heros = new String[][] { { "1", "蓋倫", "616", "100" },
{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };
JTable t = new JTable(heros, columnNames);
f.add(t, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 2 : JScrollPane
JScrollPane: 帶滾動(dòng)條的Panel
把table放進(jìn)去就可以看到table的title
同樣的把textarea放進(jìn)去,并且textarea內(nèi)容夠長(zhǎng)的話,就會(huì)看到滾動(dòng)條
package gui;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
String[] columnNames = new String[] { "id", "name", "hp", "damage" };
String[][] heros = new String[][] { { "1", "蓋倫", "616", "100" },
{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };
JTable t = new JTable(heros, columnNames);
// 根據(jù)t創(chuàng)建 JScrollPane
JScrollPane sp = new JScrollPane(t);
//或則創(chuàng)建一個(gè)空的JScrollPane卫键,再通過setViewportView把table放在JScrollPane中
// JScrollPane sp = new JScrollPane(t);
// sp.setViewportView(t);
// 把sp而非JTable加入到JFrame上,
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 3 : 列寬
設(shè)置列寬度
package gui;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
String[] columnNames = new String[] { "id", "name", "hp", "damage" };
String[][] heros = new String[][] { { "1", "蓋倫", "616", "100" },
{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };
JTable t = new JTable(heros, columnNames);
JScrollPane sp = new JScrollPane(t);
// 設(shè)置列寬度
t.getColumnModel().getColumn(0).setPreferredWidth(10);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 4 : TableModel
首先說下TableModel的設(shè)計(jì)思想,在Model這種思想的指導(dǎo)下嗽测,數(shù)據(jù)和顯示分離開來了。 比如對(duì)于JTable而言肿孵,有數(shù)據(jù)部分唠粥,也有顯示部分(比如列寬等信息)。 數(shù)據(jù)部分停做,專門做一個(gè)類晤愧,叫做TableModel,就用于存放要顯示的數(shù)據(jù)蛉腌。
使用TableModel的方式存放Table需要顯示的數(shù)據(jù)
HeroTableModel 繼承AbstractTableModel 官份,進(jìn)而實(shí)現(xiàn)了接口TableModel
在HeroTableModel 中提供一個(gè)table顯示需要的所有信息
- getRowCount 返回一共有多少行
- getColumnCount 返回一共有多少列
- getColumnName 每一列的名字
- isCellEditable 單元格是否可以修改
- getValueAt 每一個(gè)單元格里的值
當(dāng)圖形界面需要渲染第一個(gè)單元格的數(shù)據(jù)的時(shí)候,就會(huì)調(diào)用方法TabelModel的getValueAt(0,0) 烙丛,把返回值拿到并顯示
package gui;
import javax.swing.table.AbstractTableModel;
public class HeroTableModel extends AbstractTableModel {
String[] columnNames = new String[] { "id", "name", "hp", "damage" };
String[][] heros = new String[][] { { "1", "蓋倫", "616", "100" },
{ "2", "提莫", "512", "102" }, { "3", "奎因", "832", "200" } };
// 返回一共有多少行
public int getRowCount() {
// TODO Auto-generated method stub
return heros.length;
}
// 返回一共有多少列
public int getColumnCount() {
// TODO Auto-generated method stub
return columnNames.length;
}
// 獲取每一列的名稱
public String getColumnName(int columnIndex) {
// TODO Auto-generated method stub
return columnNames[columnIndex];
}
// 單元格是否可以修改
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
// 每一個(gè)單元格里的值
public Object getValueAt(int rowIndex, int columnIndex) {
// TODO Auto-generated method stub
return heros[rowIndex][columnIndex];
}
}
.
package gui;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
//創(chuàng)建一個(gè)TableModel
HeroTableModel htm= new HeroTableModel();
//根據(jù) TableModel來創(chuàng)建 Table
JTable t = new JTable(htm);
JScrollPane sp = new JScrollPane(t);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 5 : 進(jìn)一步理解TableModel
在使用TableModel之前舅巷,是使用
String[] columnNames =。河咽。钠右。
String[][] heros = 。忘蟹。飒房。
JTable t = new JTable(heros, columnNames);
這樣的風(fēng)格創(chuàng)建一個(gè)JTable的
所以實(shí)際上調(diào)用的是如下的構(gòu)造方法:
JTable(Object[][] rowData, Object[] columnNames)
如圖所示搁凸,在JTable的的源代碼中,它就會(huì)根據(jù)rowData和columnNames去創(chuàng)建一個(gè)TableModel對(duì)象
示例 6 : TableModel 與DAO結(jié)合
通過TableModel與DAO結(jié)合顯示數(shù)據(jù)庫中Hero信息狠毯。
DAO使用HeroDAO
在TableModel中坪仇,使用從DAO返回的List作為TableModel的數(shù)據(jù)
只需要修改HeroTableModel,無需修改TestGUI垃你。 這正好演繹了Model設(shè)計(jì)思想中的數(shù)據(jù)分離的好處椅文,當(dāng)只需要數(shù)據(jù)發(fā)生變化的時(shí)候,修改Model即可惜颇,界面GUI部分皆刺,不需要做任何改動(dòng)
package gui;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import jdbc.HeroDAO;
import charactor.Hero;
public class HeroTableModel extends AbstractTableModel {
String[] columnNames = new String[] { "id", "name", "hp", "damage" };
// 使用從DAO返回的List作為TableModel的數(shù)據(jù)
public List<Hero> heros = new HeroDAO().list();
// heros.size返回一共有多少行
public int getRowCount() {
// TODO Auto-generated method stub
return heros.size();
}
public int getColumnCount() {
// TODO Auto-generated method stub
return columnNames.length;
}
public String getColumnName(int columnIndex) {
// TODO Auto-generated method stub
return columnNames[columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
// 先通過heros.get(rowIndex)獲取行對(duì)應(yīng)的Hero對(duì)象
// 然后根據(jù)columnIndex返回對(duì)應(yīng)的屬性
public Object getValueAt(int rowIndex, int columnIndex) {
Hero h = heros.get(rowIndex);
if (0 == columnIndex)
return h.id;
if (1 == columnIndex)
return h.name;
if (2 == columnIndex)
return h.hp;
if (3 == columnIndex)
return h.damage;
return null;
}
}
示例 7 : TableSelectionModel
通過table可以獲取一個(gè) TableSelectionModel,專門用于監(jiān)聽jtable選中項(xiàng)的變化
package gui;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import charactor.Hero;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
final HeroTableModel htm = new HeroTableModel();
final JTable t = new JTable(htm);
// 準(zhǔn)備一個(gè)Panel上面放一個(gè)Label用于顯示哪條被選中了
JPanel p = new JPanel();
final JLabel l = new JLabel("暫時(shí)未選中條目");
p.add(l);
JScrollPane sp = new JScrollPane(t);
// 使用selection監(jiān)聽器來監(jiān)聽table的哪個(gè)條目被選中
t.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
// 當(dāng)選擇了某一行的時(shí)候觸發(fā)該事件
public void valueChanged(ListSelectionEvent e) {
// 獲取哪一行被選中了
int row = t.getSelectedRow();
// 根據(jù)選中的行凌摄,到HeroTableModel中獲取對(duì)應(yīng)的對(duì)象
Hero h = htm.heros.get(row);
// 更新標(biāo)簽內(nèi)容
l.setText("當(dāng)前選中的英雄是: " + h.name);
}
});
f.add(p, BorderLayout.NORTH);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 8 : 更新Table
以新增數(shù)據(jù)到數(shù)據(jù)庫中羡蛾,然后更新Table為例
package gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import jdbc.HeroDAO;
import charactor.Hero;
public class TestGUI {
public static void main(String[] args) {
JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
final HeroTableModel htm = new HeroTableModel();
final JTable t = new JTable(htm);
// 增加 一個(gè) panel用于放置名稱,血量輸入框和增加 按鈕
JPanel p = new JPanel();
final JLabel lName = new JLabel("名稱");
final JTextField tfName = new JTextField("");
final JLabel lHp = new JLabel("血量");
final JTextField tfHp = new JTextField("");
JButton bAdd = new JButton("增加");
tfName.setPreferredSize(new Dimension(80, 30));
tfHp.setPreferredSize(new Dimension(80, 30));
p.add(lName);
p.add(tfName);
p.add(lHp);
p.add(tfHp);
p.add(bAdd);
// 為增加按鈕添加監(jiān)聽
bAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HeroDAO dao = new HeroDAO();
// 根據(jù)輸入框數(shù)據(jù)創(chuàng)建一個(gè)Hero對(duì)象
Hero h = new Hero();
h.name = tfName.getText();
h.hp = Integer.parseInt(tfHp.getText());
// 通過dao把該對(duì)象加入到數(shù)據(jù)庫
dao.add(h);
// 通過dao更新tablemodel中的數(shù)據(jù)
htm.heros = dao.list();
// 調(diào)用JTable的updateUI锨亏,刷新界面痴怨。
// 刷新界面的時(shí)候,會(huì)到tablemodel中去取最新的數(shù)據(jù)
// 就能看到新加進(jìn)去的數(shù)據(jù)了
t.updateUI();
}
});
JScrollPane sp = new JScrollPane(t);
f.add(p, BorderLayout.NORTH);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 9 : 輸入項(xiàng)驗(yàn)證
如果用戶輸入的名稱為空器予,或者血量不是小數(shù)浪藻,在提交數(shù)據(jù)的時(shí)候都會(huì)報(bào)錯(cuò)。
“感覺上” 界面就卡住了乾翔。 這是不友好的人機(jī)交互行為爱葵。
所以需要加上輸入項(xiàng)的驗(yàn)證,如果輸入的數(shù)據(jù)不合格反浓,應(yīng)該彈出對(duì)話框提示用戶具體原因萌丈。
package gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import jdbc.HeroDAO;
import charactor.Hero;
public class TestGUI {
public static void main(String[] args) {
final JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
final HeroTableModel htm = new HeroTableModel();
final JTable t = new JTable(htm);
JPanel p = new JPanel();
final JLabel lName = new JLabel("名稱");
final JTextField tfName = new JTextField("");
final JLabel lHp = new JLabel("血量");
final JTextField tfHp = new JTextField("");
JButton bAdd = new JButton("增加");
tfName.setPreferredSize(new Dimension(80, 30));
tfHp.setPreferredSize(new Dimension(80, 30));
p.add(lName);
p.add(tfName);
p.add(lHp);
p.add(tfHp);
p.add(bAdd);
bAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HeroDAO dao = new HeroDAO();
Hero h = new Hero();
String name = tfName.getText();
// 通過name長(zhǎng)度判斷 名稱是否為空
if (name.length() == 0) {
// 彈出對(duì)話框提示用戶
JOptionPane.showMessageDialog(f, "名稱不能為空");
// 名稱輸入框獲取焦點(diǎn)
tfName.grabFocus();
return;
}
String hp = tfHp.getText().trim();
try {
// 把hp轉(zhuǎn)換為浮點(diǎn)型,如果出現(xiàn)異常NumberFormatException表示不是浮點(diǎn)型格式
Float.parseFloat(hp);
} catch (NumberFormatException e1) {
JOptionPane.showMessageDialog(f, "血量只能是小數(shù) ");
tfHp.grabFocus();
return;
}
h.name = name;
h.hp = Float.parseFloat(hp);
dao.add(h);
htm.heros = dao.list();
t.updateUI();
}
});
JScrollPane sp = new JScrollPane(t);
f.add(p, BorderLayout.NORTH);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
示例 10 : 選中指定行
- table初始化后雷则,應(yīng)該默認(rèn)選中第一行
- 增加數(shù)據(jù)后辆雾,也應(yīng)該選中新增的這一條
package gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import jdbc.HeroDAO;
import charactor.Hero;
public class TestGUI {
public static void main(String[] args) {
final JFrame f = new JFrame("LoL");
f.setSize(400, 300);
f.setLocation(200, 200);
f.setLayout(new BorderLayout());
final HeroTableModel htm = new HeroTableModel();
final JTable t = new JTable(htm);
// 設(shè)置選擇模式為 只能選中一行
t.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// 選中第一行 (基本0)
t.getSelectionModel().setSelectionInterval(0, 0);
JPanel p = new JPanel();
final JLabel lName = new JLabel("名稱");
final JTextField tfName = new JTextField("");
final JLabel lHp = new JLabel("血量");
final JTextField tfHp = new JTextField("");
JButton bAdd = new JButton("增加");
tfName.setPreferredSize(new Dimension(80, 30));
tfHp.setPreferredSize(new Dimension(80, 30));
p.add(lName);
p.add(tfName);
p.add(lHp);
p.add(tfHp);
p.add(bAdd);
bAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HeroDAO dao = new HeroDAO();
Hero h = new Hero();
String name = tfName.getText();
if (name.length() == 0) {
JOptionPane.showMessageDialog(f, "名稱不能為空");
tfName.grabFocus();
return;
}
String hp = tfHp.getText().trim();
try {
Float.parseFloat(hp);
} catch (NumberFormatException e1) {
JOptionPane.showMessageDialog(f, "血量只能是小數(shù) ");
tfHp.grabFocus();
return;
}
h.name = name;
h.hp = Float.parseFloat(hp);
dao.add(h);
htm.heros = dao.list();
t.updateUI();
// 選中 第一行 ,因?yàn)?DAO是按照 ID倒排序查詢月劈,所以第一行就是新加入的數(shù)據(jù)
t.getSelectionModel().setSelectionInterval(0, 0);
}
});
JScrollPane sp = new JScrollPane(t);
f.add(p, BorderLayout.NORTH);
f.add(sp, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
更多內(nèi)容度迂,點(diǎn)擊了解: Swing 使用 JTable詳解