2013-09-30 70 views
1

我想在JTable中顯示JButton。這沒什麼特別的,我發現了很多例子。但是,我總是遇到按鍵通過鍵盤(不通過鼠標)的問題。我期望我可以選擇一個單元格並按下SPACE(無助記符)(也可以直觀地)按下該按鈕。通過鍵盤在JTable內部按JButton

兩個片斷的工作就像一個魅力,除了支持鍵:


http://tips4java.wordpress.com/2009/07/12/table-button-column/

作者聲稱鍵的工作。我相信他們確實做到了,但是並沒有檢查我所有的系統。但是,支持的助記符完美工作。

(張貼在這裏:Adding Jbutton to JTable


http://www.java2s.com/Code/Java/Swing-Components/ButtonTableExample.htm

(張貼在這裏:Adding Jbutton to JTable

在這個例子中,它完美的作品!但是,它不適用於我的桌子。只是禁用行選擇(我不得不使用小區選擇),並通過按鍵按下按鈕不起作用了:

table.setRowSelectionAllowed(false);


我努力搞清楚什麼錯誤或如何解決它,但我失敗了。我唯一的成就是調用按鈕後面的動作,但按鈕沒有按下(我的意思是視覺行爲)。


一些信息說:

我用...(在許多組合)

  • 的Ubuntu 10.04,Windows 7中,Windows 8的
  • 的Java 7u21,JDK 1.6.0_33, OpenJDK運行時環境(IcedTea6 1.8.1)(6b18-1.8.1-0ubuntu1)
  • WindowsLookAndFeel,金屬(跨平臺LAF),Nimbus

0%成功!


TableTest.java

import java.awt.event.ActionEvent; 
import java.util.LinkedList; 
import java.util.List; 

import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.table.AbstractTableModel; 

public class TableTest extends JFrame { 

    public TableTest() { 

     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JTable table = new JTable(new TestModel()); 
     table.setRowSelectionAllowed(false); 
     table.getColumnModel().getColumn(1).setPreferredWidth(3); 
     table.getColumnModel().getColumn(2).setPreferredWidth(3); 
     this.add(new JScrollPane(table)); 
     Action increase = new AbstractAction("+") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JTable table = (JTable) e.getSource(); 
       int row = Integer.valueOf(e.getActionCommand()); 
       TestModel model = (TestModel) table.getModel(); 
       model.increment(row, 0); 
      } 
     }; 
     ButtonColumn inc = new ButtonColumn(table, increase, 1); 
     Action decrease = new AbstractAction("-") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JTable table = (JTable) e.getSource(); 
       int row = Integer.valueOf(e.getActionCommand()); 
       TestModel model = (TestModel) table.getModel(); 
       model.decrement(row, 0); 
      } 
     }; 
     ButtonColumn dec = new ButtonColumn(table, decrease, 2); 
     pack(); 
    } 

    public static void main(String[] args) { 
     new TableTest().setVisible(true); 
    } 
} 

class TestModel extends AbstractTableModel { 

    List<TestRecord> records = new LinkedList<TestRecord>(); 

    private static class TestRecord { 

     private int val = 0; 
    } 

    public void increment(int row, int col) { 
     records.get(row).val++; 
     fireTableCellUpdated(row, 0); 
    } 

    public void decrement(int row, int col) { 
     records.get(row).val--; 
     fireTableCellUpdated(row, 0); 
    } 

    public TestModel() { 
     records.add(new TestRecord()); 
     records.add(new TestRecord()); 
    } 

    @Override 
    public Class<?> getColumnClass(int col) { 
     if (col == 0) { 
      return Integer.class; 
     } else { 
      return ButtonColumn.class; 
     } 
    } 

    @Override 
    public boolean isCellEditable(int row, int col) { 
     return true; 
    } 

    @Override 
    public int getColumnCount() { 
     return 3; 
    } 

    @Override 
    public int getRowCount() { 
     return records.size(); 
    } 

    @Override 
    public Object getValueAt(int row, int col) { 
     if (col == 0) { 
      return records.get(row).val; 
     } else if (col == 1) { 
      return "+"; 
     } else { 
      return "-"; 
     } 
    } 
} 

ButtonColumn.java

import java.awt.Color; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

import javax.swing.AbstractCellEditor; 
import javax.swing.Action; 
import javax.swing.Icon; 
import javax.swing.JButton; 
import javax.swing.JTable; 
import javax.swing.UIManager; 
import javax.swing.border.Border; 
import javax.swing.border.LineBorder; 
import javax.swing.table.TableCellEditor; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumnModel; 

/** 
* The ButtonColumn class provides a renderer and an editor that looks like a 
* JButton. The renderer and editor will then be used for a specified column in 
* the table. The TableModel will contain the String to be displayed on the 
* button. 
* 
* The button can be invoked by a mouse click or by pressing the space bar when 
* the cell has focus. Optionally a mnemonic can be set to invoke the button. 
* When the button is invoked the provided Action is invoked. The source of the 
* Action will be the table. The action command will contain the model row 
* number of the button that was clicked. 
* 
*/ 
public class ButtonColumn extends AbstractCellEditor implements 
     TableCellRenderer, TableCellEditor, ActionListener, MouseListener { 
    private JTable table; 
    private Action action; 
    private int mnemonic; 
    private Border originalBorder; 
    private Border focusBorder; 

    private JButton renderButton; 
    private JButton editButton; 
    private Object editorValue; 
    private boolean isButtonColumnEditor; 

    /** 
    * Create the ButtonColumn to be used as a renderer and editor. The renderer 
    * and editor will automatically be installed on the TableColumn of the 
    * specified column. 
    * 
    * @param table 
    *   the table containing the button renderer/editor 
    * @param action 
    *   the Action to be invoked when the button is invoked 
    * @param column 
    *   the column to which the button renderer/editor is added 
    */ 
    public ButtonColumn(JTable table, Action action, int column) { 
     this.table = table; 
     this.action = action; 

     renderButton = new JButton(); 
     editButton = new JButton(); 
     editButton.setFocusPainted(false); 
     editButton.addActionListener(this); 
     originalBorder = editButton.getBorder(); 
     setFocusBorder(new LineBorder(Color.BLUE)); 

     TableColumnModel columnModel = table.getColumnModel(); 
     columnModel.getColumn(column).setCellRenderer(this); 
     columnModel.getColumn(column).setCellEditor(this); 
     table.addMouseListener(this); 
    } 

    /** 
    * Get foreground color of the button when the cell has focus 
    * 
    * @return the foreground color 
    */ 
    public Border getFocusBorder() { 
     return focusBorder; 
    } 

    /** 
    * The foreground color of the button when the cell has focus 
    * 
    * @param focusBorder 
    *   the foreground color 
    */ 
    public void setFocusBorder(Border focusBorder) { 
     this.focusBorder = focusBorder; 
     editButton.setBorder(focusBorder); 
    } 

    public int getMnemonic() { 
     return mnemonic; 
    } 

    /** 
    * The mnemonic to activate the button when the cell has focus 
    * 
    * @param mnemonic 
    *   the mnemonic 
    */ 
    public void setMnemonic(int mnemonic) { 
     this.mnemonic = mnemonic; 
     renderButton.setMnemonic(mnemonic); 
     editButton.setMnemonic(mnemonic); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, 
      boolean isSelected, int row, int column) { 
     if (value == null) { 
      editButton.setText(""); 
      editButton.setIcon(null); 
     } else if (value instanceof Icon) { 
      editButton.setText(""); 
      editButton.setIcon((Icon) value); 
     } else { 
      editButton.setText(value.toString()); 
      editButton.setIcon(null); 
     } 

     this.editorValue = value; 
     return editButton; 
    } 

    @Override 
    public Object getCellEditorValue() { 
     return editorValue; 
    } 

    // 
    // Implement TableCellRenderer interface 
    // 
    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 
     if (isSelected) { 
      renderButton.setForeground(table.getSelectionForeground()); 
      renderButton.setBackground(table.getSelectionBackground()); 
     } else { 
      renderButton.setForeground(table.getForeground()); 
      renderButton.setBackground(UIManager.getColor("Button.background")); 
     } 

     if (hasFocus) { 
      renderButton.setBorder(focusBorder); 
     } else { 
      renderButton.setBorder(originalBorder); 
     } 

     // renderButton.setText((value == null) ? "" : value.toString()); 
     if (value == null) { 
      renderButton.setText(""); 
      renderButton.setIcon(null); 
     } else if (value instanceof Icon) { 
      renderButton.setText(""); 
      renderButton.setIcon((Icon) value); 
     } else { 
      renderButton.setText(value.toString()); 
      renderButton.setIcon(null); 
     } 

     return renderButton; 
    } 

    // 
    // Implement ActionListener interface 
    // 
    /* 
    * The button has been pressed. Stop editing and invoke the custom Action 
    */ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     int row = table.convertRowIndexToModel(table.getEditingRow()); 
     fireEditingStopped(); 

     // Invoke the Action 

     ActionEvent event = new ActionEvent(table, 
       ActionEvent.ACTION_PERFORMED, "" + row); 
     action.actionPerformed(event); 
    } 

    // 
    // Implement MouseListener interface 
    // 
    /* 
    * When the mouse is pressed the editor is invoked. If you then then drag 
    * the mouse to another cell before releasing it, the editor is still 
    * active. Make sure editing is stopped when the mouse is released. 
    */ 
    @Override 
    public void mousePressed(MouseEvent e) { 
     if (table.isEditing() && table.getCellEditor() == this) 
      isButtonColumnEditor = true; 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     if (isButtonColumnEditor && table.isEditing()) 
      table.getCellEditor().stopCellEditing(); 

     isButtonColumnEditor = false; 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) { 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
    } 
} 
+0

'卻沒有關於我所有的系統我checked.' - 系統有哪些?也許其他使用這些系統的人可以檢查行爲。使用空格鍵單擊按鈕可以取決於LAF。單擊不在表中顯示的常規JButton是否會導致被調用的Action? – camickr

+0

信息添加...當然,點擊(通過鍵盤)一個常規按鈕的作品。在某些示例中,同時單擊(通過鍵盤)行選擇允許「true」。 –

回答

2

問題不是編輯器。 SPACE鍵擊不會被轉發到第一列中的默認編輯器。

問題是,JTable爲SPACE鍵定義了一個Action,因此在它有機會被傳遞給編輯器之前被攔截。在我的博客搜索Key Bindings條目,您將找到一個列出JTable的所有默認鍵綁定的程序。被調用的Action稱爲「addToSelection」,所以我不確定爲什麼它的工作方式有所不同,具體取決於行選擇。

反正一個解決方法是刪除此操作:

InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
KeyStroke space = KeyStroke.getKeyStroke("SPACE"); 
im.put(space, "none"); 
+0

啊哈! Mac OS X沒有用於「addToSelection」的鍵綁定。 – trashgod

+0

當我嘗試修復時,我也想開始修改空間的鍵綁定。但是,我完全失敗了,因爲我試圖調用標準行爲(不知道這是什麼)*並*將它發送給編輯器。你知道一個可行的可能性嗎?我有一個不好的感覺,如果我只是刪除一些預定義的綁定。否則,你是完全正確的,並按下按鈕與你的添加。 –

+0

@StefeKlauou'我有一個不好的感覺,如果我只是刪除一些預定義的綁定。「 - 你的表不反正使用選擇。因此,刪除與選擇相關的操作不應引起問題。 – camickr

2

兩個TableTest,它採用ButtonColumn,並TablePopupEditor是正常工作完整的例子當空間關鍵我按下選定的按鈕單元格。既沒有表現出典型的ButtonModel-定義的獨立按鈕外觀,但您可以根據需要提供自己的視覺隊列。這個相關的example使用彩色邊框。

+0

這兩個示例都不適用於我的初始文章中所述的setRowSelectionAllowed(false)。 –

+0

這兩個都適用於Java 6的'setRowSelectionAllowed(false)';請修改您的問題以包含顯示問題的[sscce](http://sscce.org/)。 – trashgod

+0

不,不起作用。我只是使用你發佈的代碼,包括'setRowSelectionAllowed(false)'。不過,我會編輯我的帖子,包括一切。我還將包括我嘗試過的所有系統/版本/ LAF。如果它真的在你的系統上工作,請添加有關使用的操作系統,LAF,確切版本,按鍵(重現步驟)等信息。我真的嘗試了很多東西,但成功率爲0%! –