2013-05-05 4 views
0

Я пытаюсь создать таблицу, которая включает JComboBoxes как компоненты рендеринга и редактора. Это в основном работает отлично, однако есть две вещи, которые я не могу решить.Юзабилити для JComboBox в JTable

  1. использование закладок между клетками должны сделать JComboBox активным
  2. Нажатие на стрелку раскрывающегося списка следует немедленно открыть в список опций

Что касается 1, редактируемого комбо следует поместить фокус в встроенном текстовом поле, фиксированная комбинация должна позволять стрелке вниз открывать список опций.

Что касается 2, я обнаружил, что это иногда работает в зависимости от того, какая другая ячейка в данный момент активна, но в других случаях мне нужно дважды щелкнуть. Я не могу сделать это поведение последовательным.

Для удобства я включил ясный пример, который (я считаю) использует рекомендуемый подход для встраивания JComboBoxes в Jtables.

Благодарим за конструктивный совет.

import java.awt.Component; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.table.*; 

public class TableCombos 
{ 
    public static void main(String[] args) 
    { 
     JFrame frame = new JFrame("Frame"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     AbstractTableModel model = new DefaultTableModel() 
     { 
      String[] columnHeaders = new String[]{"label", "combo-edit", "combo-fixed"}; 
      Class<?>[] columnClasses = new Class<?>[]{String.class, Double.class, Double.class}; 
      List<Object[]> data = new ArrayList<>(); 
      { 
       data.add(new Object[]{"row 1", 1.0d, 2.0d}); 
       data.add(new Object[]{"row 2", 2.0d, 3.0d}); 
      } 

      @Override 
      public int getColumnCount() 
      { 
       return columnHeaders.length; 
      } 

      @Override 
      public boolean isCellEditable(int row, int column) 
      { 
       return column != 0; 
      } 

      @Override 
      public int getRowCount() 
      { 
       if (data == null) // race condition 
        return 0; 
       return data.size(); 
      } 

      @Override 
      public Object getValueAt(int row, int column) 
      { 
       return data.get(row)[column]; 
      } 

      @Override 
      public void setValueAt(Object aValue, int row, int column) 
      { 
       data.get(row)[column] = aValue; 
      } 

      @Override 
      public Class<?> getColumnClass(int column) 
      { 
       return columnClasses[column]; 
      } 

      @Override 
      public String getColumnName(int column) 
      { 
       return columnHeaders[column]; 
      } 
     }; 

     JTable table = new JTable(model); 
     table.setSurrendersFocusOnKeystroke(true); 

     TableColumn c1 = table.getColumnModel().getColumn(1); 
     TableColumn c2 = table.getColumnModel().getColumn(2); 

     JComboBox<Double> editorComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d}); 
     editorComboEditable.setEditable(true); 
     c1.setCellEditor(new DefaultCellEditor(editorComboEditable)); 
     c2.setCellEditor(new DefaultCellEditor(new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d}))); 

     final JComboBox<Double> rendererComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d}); 
     rendererComboEditable.setEditable(true); 
     final JComboBox<Double> rendererComboFixed = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d}); 
     c1.setCellRenderer(new TableCellRenderer() 
     { 
      @Override 
      public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
      { 
       rendererComboEditable.setSelectedItem(value); 
       return rendererComboEditable; 
      } 
     }); 
     c2.setCellRenderer(new TableCellRenderer() 
     { 
      @Override 
      public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
      { 
       rendererComboFixed.setSelectedItem(value); 
       return rendererComboFixed; 
      } 
     }); 

     frame.getContentPane().add(new JScrollPane(table)); 

     frame.pack(); 
     frame.setVisible(true); 
    } 
} 
+2

* «Я включил яркий пример» * Хороший пример. Однако, чтобы быть лучше, хорошо разрешить (включать) импорт. Обычно я обнаружил, что все java.awt, java.awt.event и javax.swing могут быть импортированы без столкновений, так что это всего лишь 3 строки кода, чтобы получить пример графического интерфейса, компилируемый без «ifs» или buts '.. –

+0

благодарит @AndrewThompson, что я старался держать его коротким и простым. включая импорт и класс dec. – pstanton

+0

Hmm .. 'List data = new ArrayList <>();' Это что такое Java 7, где вы можете оставить 2-й тип? НАПРИМЕР. 'List data = new ArrayList ();' компилируется в Java 6. Я получаю 4 ошибки компиляции здесь для 4 операторов более короткой формы. –

ответ

3

Оба ваши вопросы будут решены путем переопределения метода DefaultCellEditor#isCellEditable и возвращение true

Вам может понадобиться установить JTable#setSurrendersFocusOnKeystroke истина, а также

Update

Короткий ответ «Это грязно». Ответ длинный: «Это очень грязно»

Я сделал процесс «непрерывного редактирования» некоторое время назад. В принципе, я переопределял . Введите и Tab привязки клавиш.

Что бы я сделал, это в основном остановить любой редактор активных ячеек, принять к сведению текущую ячейку, а затем попытаться найти следующую редактируемую ячейку, если нужно, вернуться к началу (ячейка 0x0).

Когда я нашел редактируемую ячейку, я позвонил JTable#esitCellAt, чтобы начать редактирование ячейки.

Чтобы получить всплывающее окно, чтобы быть видимым, когда клетка начинает редактирование, вам нужно будет переопределить addNotify метод JComboBox и, используя SwingUtilities#invokeLater установите всплывающее окно видимой

+0

(XxxCell) редактор.setClickCountToStart (2); – mKorbel

+0

@mkorbel Это отличное дополнение, но если ваше возвращение истинно из isCelleEditable, тогда это не имеет значения, так как начнется редактирование любого события с клавиатуры или мыши;) – MadProgrammer

+0

@MadProgrammer спасибо, я дам эту попытку и скоро отправлю сообщение – pstanton

Смежные вопросы