有时候我们需要在JTable中嵌入JButton,使得点击某个JTable单元格时,用户感觉通过JButton触发了响应事件。下面我们看看为JTable单元格添加按钮效果和响应事件的方法。以下示例实现的效果为:点击jtable中的button,button上的数字自动加1,并将加1后得到的数字正确显示在button上。
一、添加按钮显示效果
JTable中,单元格的数据显示默认是JTable的效果。如果我们想要按钮显示的效果的话,需要实现swing接口:javax.swing.table.TableCellRenderer,来改变单元格默认的渲染方法。
package TableButtonimport java.awt.BorderLayout
import java.awt.Component
import javax.swing.JButton
import javax.swing.JPanel
import javax.swing.JTable
import javax.swing.table.TableCellRenderer
public class MyButtonRenderer implements TableCellRenderer {
private JPanel panel
private JButton button
private int num
public MyButtonRenderer() {
initButton()
initPanel()
panel.add(button, BorderLayout.CENTER)
}
private void initButton() {
button = new JButton()
}
private void initPanel() {
panel = new JPanel()
panel.setLayout(new BorderLayout())
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
num = (Integer) value
button.setText(value == null ? "" : String.valueOf(value))
return panel
}
}
二、添加按钮响应事件
第1步中我们为表格添加了渲染器,但是渲染器只负责显示效果,要想点击”按钮“之后有响应,还得跟单元格的编辑器有关。点击表格是会触发表格的编辑时间,所以我们按钮的响应事件可以写在编辑器中,我们需要修改表格的默认编辑器实现。
swing中有个类javax.swing.DefaultCellEditor提供对单元格内插入JTextField/JComboBox/JCheckbox这3种控件,但是不提供对JButton的支持(1.7里不支持,不代表以后不会支持),所以我们得用到另外一个类自己写TableCellEditor,这个类是avax.swing.AbstractCellEditor。
package TableButtonimport java.awt.BorderLayout
import java.awt.Component
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import javax.swing.AbstractCellEditor
import javax.swing.JButton
import javax.swing.JOptionPane
import javax.swing.JPanel
import javax.swing.JTable
import javax.swing.table.TableCellEditor
public class MyButtonEditor extends AbstractCellEditor implements
TableCellEditor {
/**
* serialVersionUID
*/
private static final long serialVersionUID = -6546334664166791132L
private JPanel panel
private JButton button
private int num
public MyButtonEditor() {
initButton()
initPanel()
panel.add(this.button, BorderLayout.CENTER)
}
private void initButton() {
button = new JButton()
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int res = JOptionPane.showConfirmDialog(null,
"Do you want to add 1 to it?", "choose one",
JOptionPane.YES_NO_OPTION)
if(res == JOptionPane.YES_OPTION){
num++
}
//stopped!!!!
fireEditingStopped()
}
})
}
private void initPanel() {
panel = new JPanel()
panel.setLayout(new BorderLayout())
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
num = (Integer) value
button.setText(value == null ? "" : String.valueOf(value))
return panel
}
@Override
public Object getCellEditorValue() {
return num
}
}
需要注意的是得重写TableModel的isCellEditable方法,因为只有为重写Editor的列开启了可编辑功能,单元格才能被编辑,也就才能出发按钮单击事件。在下一段代码中有体现。
另外要注意得禁止掉JTable的行选中功能。否则我们再点击按钮时,JTable不知道是响应为”行选中“还是”按钮单击事件“。
三、测试代码
package TableButtonimport java.awt.Color
import java.awt.EventQueue
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JTable
import javax.swing.table.DefaultTableModel
public class TestTable {
private JFrame frame
private JTable table
private Object[][] data = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestTable window = new TestTable()
window.frame.setVisible(true)
} catch (Exception e) {
e.printStackTrace()
}
}
})
}
public TestTable() {
frame = new JFrame()
frame.setBounds(100, 100, 450, 300)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.getContentPane().setLayout(null)
JPanel panel = new JPanel()
panel.setBounds(10, 10, 414, 242)
frame.getContentPane().add(panel)
panel.setLayout(null)
JScrollPane scrollPane = new JScrollPane()
scrollPane.setBounds(10, 10, 394, 222)
panel.add(scrollPane)
table = new JTable()
scrollPane.setViewportView(table)
table.setModel(new DefaultTableModel() {
@Override
public Object getValueAt(int row, int column) {
return data[row][column]
}
@Override
public int getRowCount() {
return 3
}
@Override
public int getColumnCount() {
return 3
}
@Override
public void setValueAt(Object aValue, int row, int column){
data[row][column] = aValue
fireTableCellUpdated(row, column)
}
@Override
public boolean isCellEditable(int row, int column) {
if (column == 2) {
return true
} else {
return false
}
}
})
table.getColumnModel().getColumn(2).setCellEditor(
new MyButtonEditor())
table.getColumnModel().getColumn(2).setCellRenderer(
new MyButtonRenderer())
table.setRowSelectionAllowed(false)
}
}
你要设计的这个单选按钮应该不是说一个表里同时只能选一行吧。。。那你最好还是用checkbox复选框的显示方法替代单选按钮吧。。。因为单选按钮是没有办法点击取消的,一旦选中,就没有办法取消了。。。多蛋疼啊。。。给你一个复选框的例子吧,一样很好用的。
不多说了,直接上代码:
import java.awt.BorderLayout
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Toolkit
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JTable
import javax.swing.table.DefaultTableModel
import javax.swing.table.TableColumn
public class CheckedBoxTabel extends JFrame {
private JTable table
private JScrollPane sPane
private DefaultTableModel model
private JButton button, button2
private JPanel pane
public CheckedBoxTabel() {
// TODO Auto-generated constructor stub
//窗口设置,不用管
this.setSize(400, 400)
Toolkit toolkit = Toolkit.getDefaultToolkit()
Dimension scrnsize
scrnsize = toolkit.getScreenSize()
setLocation(scrnsize.width / 2 - getWidth() / 2, scrnsize.height / 2
- getHeight() / 2)
this.setDefaultCloseOperation(EXIT_ON_CLOSE)
//table的model设置
model = new DefaultTableModel(new Object[][] {}, new String[] { "论文ID",
"论文标题", "是否提交", "论文负责人" })
//table加载model
table = new JTable(model)
//将第三列的显示设为checkbox类型,楼主想设置哪列自己决定
//但是记得该列的值是Boolean型的
TableColumn tc = table.getColumnModel().getColumn(2)
tc.setCellEditor(table.getDefaultEditor(Boolean.class))
tc.setCellRenderer(table.getDefaultRenderer(Boolean.class))
sPane = new JScrollPane()
sPane.setViewportView(table)
//添加增添一行按钮的事件处理
button = new JButton("加一行")
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
model = (DefaultTableModel) table.getModel()
Object[] data = new Object[4]
data[0] = "1"
data[1] = "论文"
data[2] = new Boolean(false)
data[3] = "张三"
model.addRow(data)
/*
//或者也可以用
model.addRow(new Object[]{"1","论文",new Boolean(false),"张三"})
*/
table.setModel(model)
}
})
//添加显示所选行的按钮的事件处理
button2 = new JButton("显示所选行")
button2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
model = (DefaultTableModel) table.getModel()
int count = model.getRowCount()
for (int i = 0i <counti++) {
if (model.getValueAt(i, 2).equals(true)){
//在这里添加你要处理行的方法
System.out.println("第" + (i + 1) + "行被选中")
}
}
}
})
pane = new JPanel()
pane.setLayout(new FlowLayout())
pane.add(button)
pane.add(button2)
this.add(sPane, BorderLayout.CENTER)
this.add(pane, BorderLayout.SOUTH)
}
public static void main(String[] args) {
new CheckedBoxTabel().setVisible(true)
}
}
我设计的测试结果是在控制台输出的,楼主可以自己修改:
第4行被选中
第7行被选中
第8行被选中
第10行被选中
看着应该是LayoutParams乱了,你这里默认都是ActionBar.LayoutParams,那不对。TableRow的LayoutParams应该是TableRow.LayoutParams
bn.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT))
像这行,应该
bn.setLayoutParams(new TableRow.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT))
tr.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT))
需要
tr.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT))
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)