2015-06-16 3 views
0

Моя задача состоит в том, чтобы реализовать JTable, который один из его колонка имеет этот вид: enter image description hereJTable клеток с несколькими Компонента

она должна содержать 4 элемента:
1. JComboBox, который контролирует включить статус из другие два: они включены для «ручного» состояния и заблокированы для определенных числовых значений для других состояний (назовем другие комбо-состояния: «первым», «вторым», «третьим»).
2. a JTextField, который при включении управляет значением ползунка.
3. JLabel, который читает «%» и ничего не делает.
4. s JSlider, который, когда включен, управляет значением JTextField (может ли этот взаимный контроль даже существовать?).

Я просканировал по всей сети, ища способы реализовать это. Большинство примеров слишком поверхностны, включая такие же question.

У меня была моя доля в Cell Rendering/fireEditingStopped и т. Д., Прежде чем я спросил об этом, но у меня нет простого короткого кода, чтобы показать, к сожалению.

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

+0

ли это быть 'JTable'? –

+0

Вам нужно использовать Swing? Если не направись к Ваадину. –

+0

Да. Это должно быть Swing, и это должно быть JTable. – uzil24

ответ

5

Это один Renderer/редактор для элементов всех клеточных или нескольких Ren «/ Ed» для каждого элемента?

Я не уверен, что проблемы, но вот простой пример извлечения данных из TableCellRenderer и TableCellEditor.

enter image description here

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

public class MultipleComponentCellTest { 
    private final String[] columnNames = {"Band Type"}; 
    private final Object[][] data = { 
    {new BandType("manual", 50)}, 
    {new BandType("locked", 100)}, 
    {new BandType("manual", 32)}, 
    {new BandType("locked", 0)}, 
    }; 
    private final TableModel model = new DefaultTableModel(data, columnNames) { 
    @Override public Class<?> getColumnClass(int column) { 
     return BandType.class; 
    } 
    }; 
    private final JTable table = new JTable(model); 
    public JComponent makeUI() { 
    table.setRowHeight(42); 
    table.setDefaultRenderer(BandType.class, new BandTypeRenderer()); 
    table.setDefaultEditor(BandType.class, new BandTypeEditor()); 
    return new JScrollPane(table); 
    } 
    public static void main(String... args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 
    public static void createAndShowGUI() { 
    try { 
     for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) { 
     if ("Nimbus".equals(laf.getName())) { 
      UIManager.setLookAndFeel(laf.getClassName()); 
     } 
     } 
    } catch (ClassNotFoundException | InstantiationException 
      | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
     ex.printStackTrace(); 
    } 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new MultipleComponentCellTest().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 

class BandType { 
    public final String state; 
    public final int value; 
    public BandType(String state, int value) { 
    this.state = state; 
    this.value = value; 
    } 
} 

class BandTypePanel extends JPanel { 
    private static String DEFAULT = "0"; 
    public final JSlider slider = new JSlider(0, 100); 
    public final JTextField textField = new JTextField(3); 
    public final JComboBox<String> comboBox = new JComboBox<>(
     new String[] {"manual", "locked"}); 
    public BandTypePanel() { 
    super(new BorderLayout(5, 5)); 
    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

    comboBox.addItemListener(new ItemListener() { 
     @Override public void itemStateChanged(ItemEvent e) { 
     if (e.getStateChange() == ItemEvent.SELECTED) { 
      boolean f = "manual".equals(e.getItem()); 
      slider.setEnabled(f); 
      textField.setEnabled(f); 
     } 
     } 
    }); 

    textField.setEditable(false); 
    textField.setHorizontalAlignment(JTextField.RIGHT); 

    slider.setOpaque(false); 
    slider.setFocusable(false); 
    slider.getModel().addChangeListener(new ChangeListener() { 
     @Override public void stateChanged(ChangeEvent e) { 
     BoundedRangeModel m = (BoundedRangeModel) e.getSource(); 
     textField.setText(Objects.toString(m.getValue(), DEFAULT)); 
     } 
    }); 

    JPanel p = new JPanel(); 
    p.setOpaque(false); 
    p.add(comboBox); 
    p.add(textField); 
    p.add(new JLabel("%")); 

    add(p, BorderLayout.WEST); 
    add(slider); 
    } 
    public void updateValue(BandType bt) { 
    comboBox.setSelectedItem(bt.state); 
    slider.setValue(bt.value); 
    textField.setText(Objects.toString(bt.value, DEFAULT)); 
    } 
} 

class BandTypeRenderer extends BandTypePanel implements TableCellRenderer { 
    public BandTypeRenderer() { 
    super(); 
    setName("Table.cellRenderer"); 
    } 
    @Override public Component getTableCellRendererComponent(
     JTable table, Object value, boolean isSelected, boolean hasFocus, 
     int row, int column) { 
    setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); 
    if (value instanceof BandType) { 
     updateValue((BandType) value); 
    } 
    return this; 
    } 
} 

class BandTypeEditor extends BandTypePanel implements TableCellEditor { 
    protected transient ChangeEvent changeEvent; 
    @Override public Component getTableCellEditorComponent(
    JTable table, Object value, boolean isSelected, int row, int column) { 
    this.setBackground(table.getSelectionBackground()); 
    if (value instanceof BandType) { 
     updateValue((BandType) value); 
    } 
    return this; 
    } 
    @Override public Object getCellEditorValue() { 
    return new BandType(comboBox.getSelectedItem().toString(), slider.getValue()); 
    } 
    //Copied from AbstractCellEditor 
    //protected EventListenerList listenerList = new EventListenerList(); 
    @Override public boolean isCellEditable(EventObject e) { 
    return true; 
    } 
    @Override public boolean shouldSelectCell(EventObject anEvent) { 
    return true; 
    } 
    @Override public boolean stopCellEditing() { 
    fireEditingStopped(); 
    return true; 
    } 
    @Override public void cancelCellEditing() { 
    fireEditingCanceled(); 
    } 
    @Override public void addCellEditorListener(CellEditorListener l) { 
    listenerList.add(CellEditorListener.class, l); 
    } 
    @Override public void removeCellEditorListener(CellEditorListener l) { 
    listenerList.remove(CellEditorListener.class, l); 
    } 
    public CellEditorListener[] getCellEditorListeners() { 
    return listenerList.getListeners(CellEditorListener.class); 
    } 
    protected void fireEditingStopped() { 
    // Guaranteed to return a non-null array 
    Object[] listeners = listenerList.getListenerList(); 
    // Process the listeners last to first, notifying 
    // those that are interested in this event 
    for (int i = listeners.length - 2; i >= 0; i -= 2) { 
     if (listeners[i] == CellEditorListener.class) { 
     // Lazily create the event: 
     if (Objects.isNull(changeEvent)) { 
      changeEvent = new ChangeEvent(this); 
     } 
     ((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent); 
     } 
    } 
    } 
    protected void fireEditingCanceled() { 
    // Guaranteed to return a non-null array 
    Object[] listeners = listenerList.getListenerList(); 
    // Process the listeners last to first, notifying 
    // those that are interested in this event 
    for (int i = listeners.length - 2; i >= 0; i -= 2) { 
     if (listeners[i] == CellEditorListener.class) { 
     // Lazily create the event: 
     if (Objects.isNull(changeEvent)) { 
      changeEvent = new ChangeEvent(this); 
     } 
     ((CellEditorListener) listeners[i + 1]).editingCanceled(changeEvent); 
     } 
    } 
    } 
} 
+1

Мастерство! В этом примере @aterai объединяет компоненты в одну панель таким образом, который аналогичен подходу, используемому в [StatusPanel] mKorbel (http://stackoverflow.com/a/11179669/230513); обратите внимание, как aterai использует расширение, в то время как mKorbel использует композицию. – trashgod

+0

Спасибо! Это именно то, что мне нужно. Решила проблему так изящно. – uzil24

2

Вам нужно bothTableCellRendererиTableCellEditor для любых компонентов, которые доступны для редактирования. Общий пример показан here.

  • по умолчанию средство визуализации будет работать на String, "%", как показано на рисунке here; В качестве альтернативы вы можете отобразить его в средстве визуализации соседнего столбца.

  • по умолчанию рендерер & редактор будет работать для значения модели Double или Float, представляющего процент, как показано here.

  • A DefaultCellEditor будет работать в комбинированном поле, как показано на рисунке here; вы можете украсить рендер, как показано на рисунке here.

  • Пробег: SliderColumn или SpinnerColumn, показаны here, для последней колонки; рассмотрите приведенные примеры here.

+0

Как я могу использовать более одного редактора/рендерера на ячейку? – uzil24

+0

Я не вижу, где вам нужно, но вы можете вызывать 'setDefaultRenderer()' по классу, как показано [здесь] (http://stackoverflow.com/a/11179669/230513) для нескольких компонентов, например. 'StatusEditor'. – trashgod

+0

Возможно, я неправильно понял, но вы написали, что мне понадобится TableCellRenderer и TableCellEditor для каждого из элементов. что один Renderer/Editor для всех элементов ячейки или нескольких Ren '/ Ed' для каждого элемента? – uzil24

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