Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使JTable中的JButton可单击_Java_Swing_Jtable_Jbutton - Fatal编程技术网

Java 使JTable中的JButton可单击

Java 使JTable中的JButton可单击,java,swing,jtable,jbutton,Java,Swing,Jtable,Jbutton,以下是我想做的截图: 那里发生的事情是JButton正确显示的,但是当我点击它时,什么也没有发生。 经过一些搜索,我发现table.getValueAt()返回的对象是一个字符串,而不是JButton 代码如下: tblResult = new JTable(data,cols) { public TableCellRenderer getCellRenderer( int row, int column ) { return new ClientsTableRende

以下是我想做的截图:

那里发生的事情是JButton正确显示的,但是当我点击它时,什么也没有发生。 经过一些搜索,我发现
table.getValueAt()
返回的
对象是一个字符串,而不是JButton

代码如下:

tblResult = new JTable(data,cols) {
    public TableCellRenderer getCellRenderer( int row, int column ) {
        return new ClientsTableRenderer();
    }
};
我使用它在运行时填充JTable: (
tblResult
现在是
Clients.rblResult

最后,JTableButtonMouseListener()

public类JTableButtonMouseListener扩展了MouseAdapter{
专用最终JTable表;
公共JTableButtonMouseListener(JTable表){
this.table=表格;
}
@覆盖公共无效mouseClicked(MouseEvent e){
int column=table.getColumnModel().getColumnIndexAtX(e.getX());
int row=e.getY()/table.getrowhight();
System.out.println(“列:+列+”行:+行);
if(行=0&&column=0){
对象值=table.getValueAt(行、列);
System.out.println(“值:”+Value.getClass().getName());
if(JButton的值实例){
((JButton)值).doClick();
}
}
}
}
我是Java新手,非常感谢您的帮助:)


提前谢谢

问题是当在表中绘制时,
JButton
不再存在。这些组件仅用于在呈现表时创建“戳记”。没有实际的按钮

有一种方法允许您单击该按钮,但仍然保持表格不可编辑,但这远远不是正确的代码。只是一个可能解决方案的简要概述(我现在没有时间给出完整的代码示例)

  • 将鼠标侦听器附加到表
  • 当收到鼠标单击时,确定鼠标单击发生的单元格
  • 向表格渲染器询问该单元格的组件
  • 使用鼠标单击的位置确定上一步中的某个按钮是否存在于该特定位置的组件中
  • 如果是这样,请通过按钮api执行单击操作(使用
    doClick
    方法)
这甚至不是代码中肮脏的部分。由于渲染器(希望)每次都不会返回新的
JButton
,因此您应该在
ActionListener
中跟踪实际发生单击的组件。一种可能的解决方案是保留对上次为其创建
JButton
的表模型值的引用(因此在
getCellRenderComponent
方法中跟踪行/列),但我不确定这是否是最佳方法

如前所述,这是一个可能的解决方案,但远远不够优雅


最简单的方法是只编辑一列并使用编辑器,正如其他答案中所指出的那样。

Rob Camick的这篇文章可能适合您的需要。

本文提供了一种更简单的方法来解决您的问题,而无需添加鼠标侦听器并计算单击是否确实在按钮上:

试试这个:

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class TableWithButtonDemo
{
  private JFrame frame = new JFrame("Table Demo");
  private String[] columnNames = { "String", "Integer", "Float", "" };
  private Object[][] data = { { "Dummy", new Integer(12), new Float(12.15), "Consulter" } };
  private TableModel model = new DefaultTableModel(data, columnNames)
  {
    private static final long serialVersionUID = 1L;

    public boolean isCellEditable(int row, int column)
    {
      return column == 3;
    }
  };
  private JTable table = new JTable(model);

  public TableWithButtonDemo()
  {
    table.getColumnModel().getColumn(3).setCellRenderer(new ClientsTableButtonRenderer());
    table.getColumnModel().getColumn(3).setCellEditor(new ClientsTableRenderer(new JCheckBox()));
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    table.setShowHorizontalLines(true);
    table.setShowVerticalLines(false);

    JScrollPane scroll = new JScrollPane(table);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(scroll);
    frame.pack();
    frame.setLocation(150, 150);
    frame.setVisible(true);
  }

  public static void main(String[] args) throws Exception
  {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        new TableWithButtonDemo();
      }
    });
  }

  class ClientsTableButtonRenderer extends JButton implements TableCellRenderer
  {
    public ClientsTableButtonRenderer()
    {
      setOpaque(true);
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
      setForeground(Color.black);
      setBackground(UIManager.getColor("Button.background"));
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }
  public class ClientsTableRenderer extends DefaultCellEditor
  {
    private JButton button;
    private String label;
    private boolean clicked;
    private int row, col;
    private JTable table;

    public ClientsTableRenderer(JCheckBox checkBox)
    {
      super(checkBox);
      button = new JButton();
      button.setOpaque(true);
      button.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          fireEditingStopped();
        }
      });
    }
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
    {
      this.table = table;
      this.row = row;
      this.col = column;

      button.setForeground(Color.black);
      button.setBackground(UIManager.getColor("Button.background"));
      label = (value == null) ? "" : value.toString();
      button.setText(label);
      clicked = true;
      return button;
    }
    public Object getCellEditorValue()
    {
      if (clicked)
      {
        JOptionPane.showMessageDialog(button, "Column with Value: "+table.getValueAt(row, 1) + " -  Clicked!");
      }
      clicked = false;
      return new String(label);
    }

    public boolean stopCellEditing()
    {
      clicked = false;
      return super.stopCellEditing();
    }

    protected void fireEditingStopped()
    {
      super.fireEditingStopped();
    }
  }

}

重载表模型,并为带有按钮的单元格设置isCellEditable(int,int)return false

在桌子上加一个鼠标听筒时,它的效果非常好。

这是我的解决方案

ButtonEditor.java

public abstract class ButtonEditor extends DefaultCellEditor implements ActionListener {
private static final long serialVersionUID = 1L;

/** The cell's row. */
protected int row;

/** The cell's column. */
protected int column;

/** The cell's column. */
protected JTable table;

/** The button we are editing. */
protected JButton button;

/** The panel used when editing. */
protected JPanel panel = new JPanel(new GridBagLayout());

/** Constructor */
public ButtonEditor() {super(new JCheckBox());}

/**
 * This method is called when the user try to modify a cell. 
 * In this case it will be called whenever the user click on the cell.
 * @param table
 * @param value
 * @param isSelected
 * @param row
 * @param column
 * @return JPanel The JPanel returned contains a JButton with an ActionListener. 
 */
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
    this.row = row;
    this.column = column;
    this.table = table;
    button = (JButton) value;

    //prevent to add the action listener everytime the user click on the cell.
    if(button.getActionListeners().length == 0) button.addActionListener(this); 

    panel.add(button);
    panel.setBackground(table.getGridColor());
    return panel;
}

/**
 * Return a renderer for JButtons. The result is a button centered in the table's cell.
 * @return
 */
public static TableCellRenderer getRenderer() {
    return new TableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            JPanel panel = new JPanel(new GridBagLayout());
            panel.add((JButton) value);
            panel.setBackground(table.getGridColor());
            return panel;
        }
    };
}
    table.setDefaultRenderer(JButton.class, ButtonEditor.getRenderer()); 
    table.setDefaultEditor(JButton.class, new ButtonEditor() {
        @Override
        public void actionPerformed(ActionEvent e) {

            //handle clicks here. for example:   
            if(column == 5) {
                System.out.Println(row);
                button.setFocusPainted(false);                  
            }
        }
    });
}

下面是如何使用它:

Demo.java

public abstract class ButtonEditor extends DefaultCellEditor implements ActionListener {
private static final long serialVersionUID = 1L;

/** The cell's row. */
protected int row;

/** The cell's column. */
protected int column;

/** The cell's column. */
protected JTable table;

/** The button we are editing. */
protected JButton button;

/** The panel used when editing. */
protected JPanel panel = new JPanel(new GridBagLayout());

/** Constructor */
public ButtonEditor() {super(new JCheckBox());}

/**
 * This method is called when the user try to modify a cell. 
 * In this case it will be called whenever the user click on the cell.
 * @param table
 * @param value
 * @param isSelected
 * @param row
 * @param column
 * @return JPanel The JPanel returned contains a JButton with an ActionListener. 
 */
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
    this.row = row;
    this.column = column;
    this.table = table;
    button = (JButton) value;

    //prevent to add the action listener everytime the user click on the cell.
    if(button.getActionListeners().length == 0) button.addActionListener(this); 

    panel.add(button);
    panel.setBackground(table.getGridColor());
    return panel;
}

/**
 * Return a renderer for JButtons. The result is a button centered in the table's cell.
 * @return
 */
public static TableCellRenderer getRenderer() {
    return new TableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            JPanel panel = new JPanel(new GridBagLayout());
            panel.add((JButton) value);
            panel.setBackground(table.getGridColor());
            return panel;
        }
    };
}
    table.setDefaultRenderer(JButton.class, ButtonEditor.getRenderer()); 
    table.setDefaultEditor(JButton.class, new ButtonEditor() {
        @Override
        public void actionPerformed(ActionEvent e) {

            //handle clicks here. for example:   
            if(column == 5) {
                System.out.Println(row);
                button.setFocusPainted(false);                  
            }
        }
    });

value.getClass()?它还返回“java.lang.String”CellRenderer仅用于“绘制”表,它们未设置为“活动组件”。getValueAt返回TableModel的一个值,而不是一个组件,所以它可能会返回“Consulter”,这就是我的想法。不过,有没有办法解决这个问题?谢谢你抽出时间。嗯,它并不像预期的那么性感,但它可能是一个解决方案。如果我周末有时间,我可能会尝试添加一些代码。我知道上面的解决方案适用于
JTree
,因为我在那里使用了它
    table.setDefaultRenderer(JButton.class, ButtonEditor.getRenderer()); 
    table.setDefaultEditor(JButton.class, new ButtonEditor() {
        @Override
        public void actionPerformed(ActionEvent e) {

            //handle clicks here. for example:   
            if(column == 5) {
                System.out.Println(row);
                button.setFocusPainted(false);                  
            }
        }
    });