установить значок JList с помощью DefaultListCellRenderer? - PullRequest
2 голосов
/ 25 сентября 2011

Предполагается, что приведенный ниже код получает значок каталога по умолчанию из JFileChooser, а затем использует этот значок в моем пользовательском списке «Недавние каталоги», который предоставляется в качестве аксессуара для диалога JFileChooser.Может кто-нибудь объяснить, почему приведенный ниже код не работает (в частности, почему setIcon в DefaultListRenderer не работает), и скажите, как поместить значок рядом с каждым элементом в JList?Я бы предпочел избегать реализации моего собственного ListCellRenderer, если только это не единственный способ сделать эту работу.

import java.awt.*;
import java.io.File;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class Chooser extends JPanel {
   private static final String[] BUTTON_TEXTS = { "Hello", "Goodbye",
         "Hello Goodbye", "Adios", "This is a long String for WTF", "Hello",
         "Goodbye", "Hello Goodbye", "Adios", "This string WTF" };

   public Chooser(Icon icon) {
      this.setLayout(new BorderLayout());

      JPanel labelPanel = new JPanel(new BorderLayout());
      JLabel label = new JLabel("Recent Directories:");
      labelPanel.add(label, BorderLayout.LINE_START);
      labelPanel.setBackground(Color.LIGHT_GRAY);
      labelPanel.setBorder(new EmptyBorder(5, 10, 5, 0));

      DefaultListModel model = new DefaultListModel();
      JList list = new JList(model);
      DefaultListCellRenderer renderer = (DefaultListCellRenderer)list.getCellRenderer();
      renderer.setIcon(icon);

      for (String s : BUTTON_TEXTS) model.addElement(s);

      list.setBorder(new EmptyBorder(0, 5, 5, 0));
      list.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
            // respond to selection here
         }
      });

      add(labelPanel, BorderLayout.PAGE_START);
      // add(new JScrollPane(buttonPanel), BorderLayout.CENTER);
      add(new JScrollPane(list), BorderLayout.CENTER);
   }

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      JFileChooser fileChooser = new JFileChooser();
      Icon icon = fileChooser.getIcon(new File("."));

      /*JFrame frame = new JFrame();
      frame.setSize(100,100);
      JPanel temp = new JPanel();
      JLabel tlbl = new JLabel("picture");
      tlbl.setIcon(icon);
      temp.add(tlbl);
      frame.add(temp);
      frame.setVisible(true);*/

      Chooser c = new Chooser(icon);

      fileChooser.setAccessory(c);
      fileChooser.showOpenDialog(null);
   }

}

Ответы [ 2 ]

7 голосов
/ 25 сентября 2011

DefaultListCellRenderer очищает значок всякий раз, когда вызывается его метод getListCellRendererComponent.

Вместо этого вы можете помешать методу рендерера, создав подкласс DefaultListCellRenderer следующим образом:

list.setCellRenderer(new DefaultListCellRenderer() {
    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        label.setIcon(icon);
        return label;
    }
});
4 голосов
/ 25 сентября 2011

Chooser

Совет по использованию настраиваемого средства визуализации ячеек, расширенный для включения нескольких других советов, относящихся к работе с File и Icon объектами в JList.

import java.awt.*;
import java.io.File;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileSystemView;

public class Chooser extends JPanel {
    private static final File[] RECENT_DIRECTORIES = File.listRoots();

    public Chooser() {
        this.setLayout(new BorderLayout());

        JPanel labelPanel = new JPanel(new BorderLayout());
        JLabel label = new JLabel("Recent Directories:");
        labelPanel.add(label, BorderLayout.LINE_START);
        labelPanel.setBackground(Color.LIGHT_GRAY);
        labelPanel.setBorder(new EmptyBorder(5, 10, 5, 0));

        JList list = new JList(RECENT_DIRECTORIES);
        list.setCellRenderer(new DefaultListCellRenderer() {
            FileSystemView fsv = FileSystemView.getFileSystemView();
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (value instanceof File) {
                    label.setIcon(fsv.getSystemIcon((File)value));
                }
                return label;
            }
        });

        list.setBorder(new EmptyBorder(0, 5, 5, 0));
        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                // respond to selection here
            }
        });

        add(labelPanel, BorderLayout.PAGE_START);
        add(new JScrollPane(list), BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFileChooser fileChooser = new JFileChooser();

                Chooser c = new Chooser();

                fileChooser.setAccessory(c);
                fileChooser.showOpenDialog(null);
            }
        });
    }
}

Резюме

В целом, эти советы:

  • Использование пользовательского средства визуализации ячеек (как упомянуто Говардом)
  • Не используйте String объекты в JList для представления File объектов. Используйте File.
  • Используйте значимые имена для атрибутов класса. НАПРИМЕР. BUTTON_TEXTS -> RECENT_DIRECTORIES
  • Укажите File[] для конструктора Jlist - нет необходимости повторять массив и добавлять каждый элемент.
  • Используйте FileSystemView.getSystemIcon(File), чтобы обойти скучные значки, выплевываемые каждым PLAF. Экземпляры Icon в списке выглядят странно рядом со значками, использованными в исходной левой панели (начиная с «1 носителя» и т. Д.). Они соответствовали бы, если бы PLAF был установлен в систему PLAF. Дело в том, что FSV обеспечит более хорошее Icon независимо от PLAF.
  • Запустите графический интерфейс на EDT.

Еще больше советов (это чаевые!), См. Графический интерфейс браузера файлов .

image


Я не понял подсказки о "PLAF" (я также не знаю, что означает PLAF).

Повезло, что Google это делает. Попробуйте выполнить поиск по нему и выберите первую ссылку, в которой упоминается «Java» (здесь это вторая ссылка).

Я заметил, что значок папки, полученный в результате использования вашего кода, отличается от значка папки / каталога в JFileChooser. Значок JFC синий и выглядит больше как java-y. Вызов getIcon (), который я использовал в своем исходном коде, работает, но я не уверен, как тот же значок с вызовом, похожим на ваш (FileSystemView.getSystemIcon () или аналогичный)

Все значки, отображаемые в графическом интерфейсе File Browser (FileBro) , были сделаны с использованием метода выбора файлов getIcon(), но они выглядят так, как в вашем примере, были произведены FSV, верно? Причина, по которой они выглядят как значки FSV, показанные на скриншоте Metal, заключается в том, что PLAF был системной настройкой по умолчанию для FileBro (PLAF «Windows»). Когда GUI использует «родной» PLAF для этой ОС, значки, возвращаемые для средства выбора файлов, соответствуют значкам, возвращаемым FSV.

Если вам нужны более конкретные ответы после некоторого исследования и внимательного изучения main() FileBro, чтобы увидеть, как он устанавливает PLAF, задайте более конкретные вопросы.

...