Пользовательский рендерер Java JComboBox и GTK

У меня есть список Customer объектов, которые мне нужно выбрать из JComboBox. Из того, что я прочитал, мне нужно реализовать собственный рендерер, чтобы поля, которые я хочу, отображались в списке.

Я хочу, чтобы в моем JComboBox записи были отформатированы следующим образом:

+----------------------------------------------+
|  Customer Name - Contact - City, State    V  |
+==============================================+
|  Customer #2 Name - Contact - City, State    |
|  Customer #3 Name - Contact - City, State    |
|  Customer #4 Name - Contact - City, State    |
|  Customer #5 Name - Contact - City, State    |
+----------------------------------------------+

Я использовал этот код:

открытый класс CustomerListCellRenderer расширяет DefaultListCellRenderer {

@Override
public Component getListCellRendererComponent(
        JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    if (value instanceof Customer) {
        Customer c = (Customer) value;

        StringBuffer sb = new StringBuffer();
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getCompany());
        }
        sb.append(" - ");
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getContact());
        }
        sb.append(" - ");
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getCity());
            sb.append(", ");
        }            
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getState());
        }

        setText(sb.toString());
    }
    return this;
  }
}

Это не работает корректно в Solaris/Unix/Linux с использованием системы GTKLookAndFeel. Фон области ввода выпадающего списка не рисуется, и вокруг него не рисуется граница. (См. скриншот ниже). Есть ли другой способ добиться этого, который будет правильно работать на трех основных платформах (Win/Mac/GTK)? Могу ли я сделать конвертер для этого и манипулировать только данными, а не графическим интерфейсом?

Мой текущий обходной путь — переопределить toString() в моем объекте Customer, чтобы отображать каждую запись в нужном мне формате, но ищу другие идеи.

альтернативный текст

Ник


person Nicholas Hirras    schedule 25.06.2009    source источник
comment
Я не вижу причин, по которым вам может понадобиться специальный рендерер для этого примера.   -  person Erich Kitzmueller    schedule 25.06.2009
comment
@ammoQ: вам это нужно, потому что вы хотите сохранить Customer в своей ComboBoxModel, а не в String. Итак, когда вы делаете: getSelectedItem(), вы получаете Customer, а не String.   -  person Laurent K    schedule 26.06.2009


Ответы (3)


Та же проблема, я сделал это, чтобы настроить отображение значков:

private static class CustomComboBoxRenderer extends DefaultListCellRenderer
{
    private final ListCellRenderer backend;

    public CustomComboBoxRenderer(ListCellRenderer backend)
    {
        this.backend = backend;
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
    {
        Component component = backend.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if(component instanceof JLabel == false)
            component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        JLabel label = (JLabel)component;
        label.setIcon(Icons.COMPONENT);
        return label;
    }
}

Затем назначил рендерер следующим образом:

comboBox.setRenderer(new CustomComboBoxRenderer(comboBox.getRenderer()));

Это работало хорошо для меня, до сих пор.

person Martin    schedule 12.08.2010

Попробуй это:

public Component getListCellRendererComponent(
        JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    if (value instanceof Customer) {
        Customer c = (Customer) value;

        StringBuffer sb = new StringBuffer();
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getCompany());
        }
        sb.append(" - ");
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getContact());
        }
        sb.append(" - ");
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getCity());
            sb.append(", ");
        }            
        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getState());
        }

        value = sb.toString();
    } 
    return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
  }
}

Также используйте StringBuilder, а не StringBuffer (это однопоточная ситуация).

Также похоже, что вы вырезали и вставляли ошибки в коде, например:

        if (c.getCompany() != null && c.getCompany().length() > 0) {
            sb.append(c.getState());
        }

Проверяет члена компании и использует члена государства.

person Tom    schedule 27.06.2009

DefaultListCellRenderer расширяет JLabel и выглядит как JLabel. Если у вас есть нередактируемый ComboBox, то Renderer, возвращенный через getRenderer, используется для рисования области раскрывающегося списка, а также для области «ввода». Попробуйте поиграть с настройками границы/переднего плана/фона для ComboBox и рендерера.

person Rastislav Komara    schedule 27.06.2009