JTable: кнопки на пользовательской панели в ячейке - PullRequest
5 голосов
/ 31 августа 2010

Я хочу иметь JPanel в ячейке с JButton, который выполняет некоторую работу при нажатии.

Я искал инструкции о редакторах ячеек, но во всех примерах рассказывается о замене ячейки другим компонентом (например, замените int на JTextField и т. Д.) Моя ситуация немного отличается:

У меня есть следующий ADT

class MyClass {
  public String title;
  public String url;
  public String path;
  public int annotations;
}

Я создал пользовательскую модель ячейки таблицы, которая имеет 1 столбец, и класс для этого столбца - MyClass. Затем я создал средство визуализации ячеек для этого класса, которое возвращает JPanel, как показано здесь:

MyClass Cell Renderer

Как видите, JPanel содержит кнопку. Я хочу, чтобы эта кнопка запускала JFrame при каждом нажатии. Есть идеи?

Если вы предложите Cell Editor, пожалуйста, будьте немного конкретнее, как это сделать. Если возможно, укажите псевдокод.

Спасибо.

P.S. Я уверен, что заголовок этого вопроса нуждается в доработке. ;)

Ответы [ 3 ]

7 голосов
/ 31 августа 2010

После ответа coding.mof я наконец сделал то, что хотел.Однако я хотел получить более полный ответ на этот вопрос, поэтому я сам предоставлю его.

Итак, средства визуализации ячеек просто рисуют компонент и не допускают никаких взаимодействий внутри него.В то время как сотовые редакторы делают.

Первоначально все ячейки в JTable являются компонентами, которые возвращаются зарегистрированным средством визуализации.Однако при выборе ячейки этот компонент заменяется компонентом, возвращаемым редактором.Эти два могут фактически быть различными компонентами!Я уверен, что вы можете воспользоваться этим и создать несколько прикольных ячеек: P

В любом случае, в этом примере и рендер, и редактор отображают один и тот же компонент, поэтому мы создадим компонент, который будетиспользоваться обоими.

Во-первых, нам нужно создать TableModel, который возвращает нашу ADT:

class MyClassTableModel extends DefaultTableModel {
  List<MyClass> data;

  public MyClassTableModel(List<MyClass> data) {
    this.data = data;
  }

  public Class<?> getColumnClass(int columnIndex) { return MyClass.class; }
  public int getColumnCount() { return 1; }
  public String getColumnName(int columnIndex) { return "MyClass"; }
  public int getRowCount() { return (data == null) ? 0 : data.size(); }
  public Object getValueAt(int rowIndex, int columnIndex) { return data.get(rowIndex); }
  public boolean isCellEditable(int rowIndex, int columnIndex) { return true; }
}

Теперь мы создадим компонент, который будет использоваться совместно с Renderer и Editor:

class MyClassCellComponent extends JPanel() {
  MyClass myClass;

  public MyClassCellComponent() {
    // initialize components (labels, buttons, etc.)
    // add action listeners
  }

  public void updateData(MyClass myClass, boolean isSelected, JTable table) {
    this.myClass = myClass;
    // update buttons, labels etc. accordingly
  }
}

Параметры isSelected и table используются для отображения фона панели и являются необязательными.Вот как рендерер использует наш компонент:

class MyClassCellRenderer implements TableCellRenderer {
  MyClassCellComponent panel;

  public MyClassCellRenderer() {
    panel = new MyClassCellComponent();
  }

  public Component getTableCellRendererComponent(JTable table, Object value,        boolean isSelected, boolean hasFocus, int row, int column) {
    MyClass myClass = (MyClass)value;
    panel.updateData(myClass, isSelected, table);
    return panel;
  }
}

А вот как редактор использует его:

class MyClassCellEditor extends AbstractCellEditor {
  MyClassCellComponent panel;
  public MyClassCellEditor() {
    panel = new MyClassCellComponent();
  }
  public Component getTableCellEditorComponent(JTable table, Object value,      boolean isSelected, int row, int column) {
    MyClass myClass = (MyClass)value;
    panel.updateData(myClass, true, table);
    return panel;
  }
  public Object getCellEditorValue() {
    return null;
  }
}

Вот и все.Теперь мы можем просто создать JTable следующим образом:

JTable myClassTable = new JTable(new MyClassTableModel());
myClassTable.setDefaultRenderer(MyClass.class, new MyClassCellRenderer());
myClassTable.setDefaultEditor(MyClass.class, new MyClassCellEditor());

И мы закончили!

PS Я почти уверен, что мы можем объединить Renderer и Editor в один классон расширяет AbstractCellEditor и реализует TableCellRenderer, но я не уверен насчет производительности.

5 голосов
/ 31 августа 2010
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor { 

JComponent pan = new JPanel();

public MyTableCellEditor () {
  pan.add(btn);
  // add all elments you need to your panel
  btn.addActionListener( /* the listener which will handle the events */ );
}

public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int vColIndex) { 
   btn.setText( /* according to row or whatever*/ );
   // set all elemnts of you panel to the according values
   // or add dynamically an action listener
   return pan;
}
public Object getCellEditorValue() { return new Void(); } 
} 

Таким образом, в вашем слушателе вы должны будете проверить выбор таблицы, чтобы вы могли по-разному отвечать для каждой строки.Если вы хотите сохранить все элементы в одном столбце, вы можете заменить JButton панелью, содержащей все компоненты.Затем JTable будет пересылать все события в эту JPanel.

0 голосов
/ 31 августа 2010

Вы можете создать таблицу с несколькими столбцами, затем вы можете добавить отдельный столбец, содержащий вашу кнопку. Класс Столбец Столбец позволяет легко это сделать.

...