28

これが私がやりたいことのスクリーンショットです:

ここに画像の説明を入力してください

JButtonは正しく表示されますが、クリックしても何も起こりません。いくつか検索したところ、Objectによって返されるtable.getValueAt()のはJButtonではなくStringであることがわかりました...

コードは次のとおりです。

tblResult = new JTable(data,cols) {
    public TableCellRenderer getCellRenderer( int row, int column ) {
        return new ClientsTableRenderer();
    }
};

実行時にJTableを設定するためにこれを使用します:(tblResult現在Clients.rblResult

SwingUtilities.invokeLater( new Runnable() {
    public void run() { 

        DefaultTableModel aModel = new DefaultTableModel() {
            //setting the jtable read only
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }               
        };


    String[] cols = {"N°","Société", "TVA", "CP", "Ville", ""};
    aModel.setColumnIdentifiers(cols);

    Object[] temp = new Object[6];
    for(int i=0;i<result.length;i++) {

        temp[0] = result[i].custNumber;
        temp[1] = result[i].name;
        temp[2] = result[i].tva;
        temp[3] = result[i].cp;
        temp[4] = result[i].city;
        temp[5] = "Consulter";

        aModel.addRow(temp);

    }

    Clients.tblResult.setModel(aModel);

    Clients.tblResult.addMouseListener(new JTableButtonMouseListener(Clients.tblResult));
    }}  
); 

ここでClientsTableRendererクラス

public class ClientsTableRenderer extends JPanel implements TableCellRenderer {
    @Override
    public Component getTableCellRendererComponent( final JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setBackground(Color.WHITE);
        if(column < 5) {
            JLabel label =  new JLabel(value.toString());
            JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER,0,9));
            panel.setBackground(Color.WHITE);
            panel.add(label);
            this.add( panel);
        } else {

            JButton button = new JButton(value.toString());
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    System.out.println("Clicked !");
                }
            });
            JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER,0,3));
            panel.setBackground(Color.WHITE);
            panel.add(button);
            this.add(panel);
        }


        return this;
    }


}

そして最後に、JTableButtonMouseListener():

public class JTableButtonMouseListener extends MouseAdapter {
      private final JTable table;

      public JTableButtonMouseListener(JTable table) {
        this.table = table;
      }

      @Override public void mouseClicked(MouseEvent e) {
        int column = table.getColumnModel().getColumnIndexAtX(e.getX());
        int row    = e.getY()/table.getRowHeight(); 
        System.out.println("Col :"+column + "row:"+row);

        if (row < table.getRowCount() && row >= 0 && column < table.getColumnCount() && column >= 0) {
          Object value = table.getValueAt(row, column);
          System.out.println("Value :"+value.getClass().getName());
          if (value instanceof JButton) {
            ((JButton)value).doClick();
          }

        }
      }
    }

私はJavaに不慣れです、助けていただければ幸いです:)

前もって感謝します !

4

6 に答える 6

22

Rob Camick のこのTable Button Columnは、あなたのニーズに合うかもしれません。

于 2012-04-27T09:43:13.313 に答える
12

問題はJButton、テーブルにペイントすると が存在しなくなることです。これらのコンポーネントは、テーブルがレンダリングされるときに「スタンプ」を作成するためにのみ使用されます。実際のボタンはありません。

ボタンをクリックしてテーブルを編集不可のままにする方法はありますが、適切なコードとはほど遠いものです。考えられる解決策の簡単な概要 (現時点では完全なコード例を示す時間はありません)

  • マウス リスナーをテーブルにアタッチする
  • マウス クリックを受け取ったら、マウス クリックが発生したセルを特定します。
  • そのセルのコンポーネントをテーブルレンダラーに要求します
  • マウス クリックの位置を使用して、その特定の位置で前のステップからのボタンがコンポーネントに存在するかどうかを判断します。
  • その場合は、ボタン api (doClickメソッド)をクリックして実行します。

そして、これはコードの汚い部分でさえありません。JButtonあなたのレンダラーは (うまくいけば)毎回新しいものを返さないので、実際にクリックが発生したコンポーネントを追跡するために、 ActionListenerwhich が添付されている必要があります。JButton考えられる解決策は、最後に作成したテーブルモデル値への参照を保持することですJButton(そのため、getCellRendererComponentメソッドで行/列を追跡します) が、これが最善の方法であるかどうかはわかりません。

前述のように、可能な解決策ですが、エレガントにはほど遠いです。

最も簡単な方法は、他の回答で指摘されているように、その1つの列を編集可能にしてエディターを使用することです

于 2012-04-27T09:41:12.270 に答える
9

これを試して:

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();
    }
  }

}
于 2012-04-27T10:23:27.067 に答える
3

この記事では、MouseListeners を追加したり、クリックが実際にボタン上にあるかどうかを計算したりせずに、問題へのより簡単なアプローチを提供します。

http://web.archive.org/web/20100623105810/http://ivolo.mit.edu/post/A-Simple-Pattern-for-Embedding-Components-into-a-Swing-JTable.aspx

于 2012-04-27T09:52:26.700 に答える
0

Table モデルをオーバーロードし、 isCellEditable(int, int) がボタン付きのセルに対して false を返すように設定します。

テーブルに追加された MouseListener でうまく機能します。

于 2015-05-11T21:21:37.737 に答える