2011-08-08 2 views
2

У меня есть требование визуализации выделенных/сфокусированных ячеек в JTable с JComboBox, если рассматриваемый столбец использует комбо в качестве редактора. Цель этого - дать подсказку пользователям о том, что ячейки в столбце редактируются с помощью комбо, а не JTextField.Render TableCell с JComboBox и фоном выбора

Моя проблема в том, что для других LookAndFeels, чем Металл, невозможно установить выделение фона таблицы в поле со списком. Если щелкнуть или перейти с клавиатуры на «комбинированный столбец», выбранная ячейка будет отображаться комбо с фоном по умолчанию.

Metal L & F работает так, как я хочу, но это не вариант, так как наши клиенты используют либо вещество/Nimbus/Windows L & F, и это не работает ни для одного из них.

Надеюсь, что я был достаточно ясен, любая помощь приветствуется!

Выберите ячейки в «Combo колонке» этого SSCCE, чтобы увидеть, что я имею в виду:

import java.awt.Component; 

import javax.swing.DefaultCellEditor; 
import javax.swing.DefaultComboBoxModel; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.ListSelectionModel; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableModel; 

import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel; 


public class RenderSelectedCellWithComboSSCCE extends JFrame 
{ 
    RenderSelectedCellWithComboSSCCE() 
    { 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     add(new JScrollPane(createTable())); 
     pack(); 
    } 

    private JTable createTable() 
    { 
     TableModel model = new DefaultTableModel(
       new Object [][] {{"A", "Item 0"}, 
           {"B", "Item 1"}, 
           {"C", "Item 2"}, 
           {"D", "Item 3"}, 
           {"E", "Item 4"}}, 
       new String [] {"TextField", "Combo"}); 
     JTable table = new JTable(model); 
     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     DefaultCellEditor editor = new DefaultCellEditor(new JComboBox(new Object[]{"Item 0", "Item 1", "Item 2", "Item 3", "Item 4"})); 
     editor.setClickCountToStart(2); 
     table.getColumnModel().getColumn(1).setCellEditor(editor); 
     table.getColumnModel().getColumn(1).setCellRenderer(new ComboCellRenderer()); 
     return table; 
    } 

    /** 
    * Renderer that demonstrates problem rendering selected cells with a combo with selection background. 
    */ 
    private static class ComboCellRenderer implements TableCellRenderer 
    { 
     final TableCellRenderer defaultRenderer; 
     final JComboBox combo; 

     ComboCellRenderer() 
     { 
      defaultRenderer = new DefaultTableCellRenderer(); 
      combo = new JComboBox(); 
     } 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
     { 
      if (hasFocus && table != null && table.isCellEditable(row, column)) 
      { 
       combo.setModel(new DefaultComboBoxModel(new Object[]{value})); 
       combo.setSelectedItem(value); 
       combo.setBackground(table.getSelectionBackground()); // This only have desired effect for Metal L&F 
       return combo; 
      } 
      else 
      { 
       return defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
      } 
     } 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       setLookAndFeel(); 
       new RenderSelectedCellWithComboSSCCE().setVisible(true); 
      } 

      private void setLookAndFeel() 
      { 
       try 
       { 
        //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());  // Metal works fine 
        UIManager.setLookAndFeel(new NimbusLookAndFeel()); 
        //UIManager.setLookAndFeel(new WindowsLookAndFeel()); 
        //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        //UIManager.setLookAndFeel("org.jvnet.substance.SubstanceLookAndFeel"); 
       } 
       catch (Exception e) 
       { 
        throw new RuntimeException("Failed to set LookAndFeel", e); 
       } 
      } 
     }); 
    } 
} 

ответ

3

Реализация ComboBox создает проблемы, обычно у LAF есть особые идеи о том, как они хотят показать комбо, многие из них стилизованы, имеют закругленные углы ... для него это невозможно сделать правильно. Во время игры немного с предложением Стани, я побежал во все неприятные (и быстро забытых деталей :-), как

  • Windows, отключает прозрачность при визуализации комбо, так вот это помогло бы обернуть визуализатор в комбо в один который устанавливает непрозрачность true после вызова super
  • Nimbus игнорирует фон компонента, который был настроен сам, вне зависимости от непрозрачности: ваш рендерер работал бы так, как ожидалось (все в порядке, почти, по модулю неожиданные изменения цвета :-), если вы установите выделение цвет (на столе), который отличается от значения по умолчанию
  • ...

С другой стороны, вам не нужен полностью функциональный JComboBox, все, что вам нужно, - это визуальный ключ к открытию. Таким образом, вы можете уйти с пользовательским компонентом - в простейшем случае в JLabel с некоторыми стрелками - насмешливо на JComboBox, что-то вроде:

public static class MockCombo extends JLabel { 

    private JButton arrow; 

    public MockCombo() { 
     JComboBox box = new JComboBox(); 
     box.setEditable(true); 
     arrow = (JButton) box.getComponent(0); 
     setLayout(new BorderLayout()); 
     add(arrow, BorderLayout.LINE_END); 
     setOpaque(true); 
    } 

} 

Тем не менее должно быть доработано с помощью LAF, но гораздо более простая задача, чем настроить a JComboBox

+0

hmmmm, just question -> why setOpaque (true); для извлеченных JComponents для TableCellRenderer, может быть, я ошибаюсь, но если TableCell содержит другой JComponet в качестве JLabel, тогда я добавляю для Nimbus L & F всюду setOpaque (false); +1 – mKorbel

+0

+1 Возможно, некоторые проблемы с границами будут исправлены – StanislavL

2

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

+0

Я уже пробовал, но это не сработало. У вас есть код для предоставления? – Uhlen

+1

удалил мой предыдущий комментарий - забыл на самом деле установить рендеринг комбо ;-) Так что да, это возможно, но потенциально уродливо, если не специализировано для ЛАФ .. – kleopatra

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