java Jtable 如何动态添加button按钮

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java Jtable 如何动态添加button按钮相关的知识,希望对你有一定的参考价值。

如下图,表格中编辑那一列中的button按钮如何动态添加进去,并且点击删除按钮后,那一整行的数据都被删除了,用java swing 编写。

有时候我们需要在JTable中嵌入JButton,使得点击某个JTable单元格时,用户感觉通过JButton触发了响应事件。下面我们看看为JTable单元格添加按钮效果和响应事件的方法。以下示例实现的效果为:点击jtable中的button,button上的数字自动加1,并将加1后得到的数字正确显示在button上。

一、添加按钮显示效果

JTable中,单元格的数据显示默认是JTable的效果。如果我们想要按钮显示的效果的话,需要实现swing接口:javax.swing.table.TableCellRenderer,来改变单元格默认的渲染方法。

package TableButton;

import 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 TableButton;

import 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 TableButton;

import 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);
    
参考技术A 你可以使用卡片式布局(CardLayout),点击添加按钮后转到另一个卡片,那个卡片里面放置的是另一个JPanel,里面放数个文本框、下拉框、提交按钮之类的东西,然后点击提交后在后台将数据取得然后放入JTable再转到有JTable的卡片,就可以了。 或者是直接在有表的的地方设置一个添加按钮,点击后表增加一行,然后可以直接在表中添加数据。退出编辑状态,点击保存按钮更新数据。

Java-Swing 在 jtable 的单元格中添加多行

【中文标题】Java-Swing 在 jtable 的单元格中添加多行【英文标题】:Java-Swing adding multiple lines in jtable's cell 【发布时间】:2015-09-11 14:28:13 【问题描述】:

我想在 jtable 的同一个单元格中逐行插入多个字符串。这是我将数据添加到 jtable 中的方式

       String Model,Brand,Serial;

       String itemdetails=Model+Brand+Serial

       model.addRow(new Object[]itemdetails,amountText.getText());

问题出在哪里,在单行中获取输出,但我希望在 jtbale 的单元格中像这样输出。

      Model                    //it is string coming from database
      Brand                      //it is string coming from database
      Serial                   //it is string coming from database

我已经尝试过了,但它只能使用双引号内的数据,而不是字符串。

                  "<html>lineOne <br/> lineTwo </html>"   

【问题讨论】:

我认为您需要手动调整行高。考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个示例,它突出了您遇到的问题。这将导致更少的混乱和更好的响应运行示例 是的,在我调整行高之前,我需要在多行中获得输出。先生,我会怎么做。 你添加的 HTML 是质疑 TableModel 中的数据还是使用自定义的 TableCellRederer iam 使用普通的 DefaultTableModel。 好的,但是&lt;html&gt;lineOne &lt;br/&gt; lineTwo &lt;/html&gt; 什么时候生成?当你放入模型或因为你有一个自定义的TableCelLRenderer 这样做? 【参考方案1】:

所以,不用做任何特别的事情,我可以让&lt;html&gt;...&lt;br&gt;...&lt;/html&gt; 工作得很好......

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                try 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                 catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) 
                    ex.printStackTrace();
                

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        public TestPane() 
            DefaultTableModel model = new DefaultTableModel(0, 1);
            model.addRow(new String[]
                "<html>My teacher took my iPod.<br>She said they had a rule;<br>I couldn't bring it into class<br>or even to the school.</html>"
            );
            model.addRow(new String[]
                "<html>She said she would return it;<br>I'd have it back that day.<br>But then she tried my headphones on<br>and gave a click on Play.</html>"
            );
            model.addRow(new String[]
                "<html>She looked a little startled,<br>"
                + "but after just a while<br>"
                + "she made sure we were occupied<br>"
                + "and cracked a wicked smile.<br>"
            );
            model.addRow(new String[]
                "<html>Her body started swaying.<br>"
                + "Her toes began to tap.<br>"
                + "She started grooving in her seat<br>"
                + "and rocking to the rap.</html>"
            );
            model.addRow(new String[]
                "<html>My teacher said she changed her mind.<br>"
                + "She thinks it's now okay<br>"
                + "to bring my iPod into class.<br>"
                + "She takes it every day.</html>"
            );

            setLayout(new GridBagLayout());

            JTable table = new JTable(model);
            table.setRowHeight(75);
            add(new JScrollPane(table));

        

    


也许您的代码中还有其他内容,您没有向我们展示,这导致了问题...

更新了“动态”示例

这超出了最初的问题,但是,TableModel 表示它支持的数据,它为JTable 提供了显示它的结构。

因此,给定一堆“断开”的值,TableModel 将根据您的要求将它们“缝合”在一起。

当每行代表一个元素时,以下示例将前一首诗的每一行简单地拆分为一个数组。

然后将其再次包装,因此诗歌的每个部分都是一系列行...

String data[][] = 
            "My teacher took my iPod.", "She said they had a rule;", "I couldn't bring it into class", "or even to the school.",
            "She said she would return it;", "I'd have it back that day.", "But then she tried my headphones on", "and gave a click on Play.", 
            etc...

然后该示例使用自定义TableModel,当询问单元格的值时,它采用给定的“部分”并从每一行构建一个String,包装成一个基于&lt;html&gt;String .

此外,您需要单击“添加”按钮添加每个新行才能显示

public class TestPane extends JPanel 

    private MyTableModel model;
    private int index = 0;
    public TestPane() 
        String data[][] = 
            "My teacher took my iPod.", "She said they had a rule;", "I couldn't bring it into class", "or even to the school.",
            "She said she would return it;", "I'd have it back that day.", "But then she tried my headphones on", "and gave a click on Play.",
            "She looked a little startled,", "but after just a while", "she made sure we were occupied", "and cracked a wicked smile.", "",
            "Her body started swaying.", "Her toes began to tap.", "She started grooving in her seat", "and rocking to the rap.",
            "My teacher said she changed her mind.", "She thinks it's now okay", "to bring my iPod into class.", "She takes it every day."
        ;

        setLayout(new BorderLayout());

        model = new MyTableModel();

        JTable table = new JTable(model);
        table.setRowHeight(75);
        add(new JScrollPane(table));

        JButton add = new JButton("Add");
        add.addActionListener(new ActionListener() 
            @Override
            public void actionPerformed(ActionEvent e) 
                if (index < data.length) 
                    model.addRow(data[index]);
                
                index++;
                if (index >= data.length) 
                    add.setEnabled(false);
                
            
        );

        add(add, BorderLayout.SOUTH);
    

    public class MyTableModel extends AbstractTableModel 

        private List<String[]> rowData;

        public MyTableModel() 
            rowData = new ArrayList<>(25);
        

        public void addRow(String[] data) 
            rowData.add(data);
            fireTableRowsInserted(rowData.size() - 1, rowData.size() - 1);
        

        @Override
        public int getColumnCount() 
            return 1;
        

        @Override
        public Class<?> getColumnClass(int columnIndex) 
            return String.class;
        

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) 
            Object value = null;
            switch (columnIndex) 
                case 0:
                    String[] data = rowData.get(rowIndex);
                    StringJoiner joiner = new StringJoiner("<br>", "<html>", "</html>");
                    for (String text : data) 
                        joiner.add(text);
                    
                    value = joiner.toString();
                    break;
            
            return value;
        

        @Override
        public int getRowCount() 
            return rowData.size();
        

    


查看How to Use Tables了解更多详情

【讨论】:

是的,这完全正确,但我的变量是非静态的。意味着它会动态变化。当我们在双引号内写一个字符串时,它总是静态的。但是我的模型和品牌可能会随着时间而变化。那我该怎么办。 没什么,不会有任何区别,你可以更改模型的内容或模型本身,不会有任何区别 考虑我的模型=双核处理器和品牌=英特尔,但我不能直接将它们放在双引号内。因为下次它可能会有所不同(这里我正在创建计费系统)。当我们将它们放在双引号内时,我们应该总是改变内容。但我说模型和品牌是两个可能动态变化的变量。 让您的 TableModel 从它所支持的数据中生成单元格的值 一开始没有填满我的 TableModel。考虑在计费系统中我们将做什么,首先我们将搜索产品,然后将其添加到表中以进行打印。如果我们想要第二个项目要添加,我们将像这样添加。【参考方案2】:

您的 for 循环未正确关闭:

    DefaultTableModel model = (DefaultTableModel) jt.getModel();
    int i; 
    for(i=0; i<model.getRowCount(); i++) 
    String itemdetails=model+"\n"+brand; 
    System.out.println(itemdetails);
    jt.setRowHeight(30);
    model.addRow(new Object[]i+1,itemdetails,amountText.getText()); 

【讨论】:

它与 System.out.println(itemdetails); 一起工作。但仍然输出在 jtable 的单元格中的单行。 能否提供包含此代码的主类 DefaultTableModel model = (DefaultTableModel) jt.getModel();诠释我; for(i=0; i

以上是关于java Jtable 如何动态添加button按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何动态添加按钮?

JAVA中怎么把list或map里的值动态添加至JTable

如何完全擦除 Java Swing JTable 列及其数据?

java web 怎么在jtable中添加按钮?

java jtable 清空

使用特定列对 Jtable 项目进行排序 - JAVA