Как вставить значок в определенный подэлемент строки в ListView? [Дубликат]

Ах, это один из моих любимых предметов. Существует два способа загрузки ресурса через путь к классам:

Class.getResourceAsStream(resource)

и

ClassLoader.getResourceAsStream(resource)

(существуют другие способы, связанные с получением URL-адреса ресурса в аналогичным образом, затем открывая соединение с ним, но это два прямых способа).

Первый метод на самом деле делегирует второй, после изменения имени ресурса. Существует, по существу, два типа имен ресурсов: абсолютный (например, «/ path / to / resource / resource») и относительный (например, «ресурс»). Абсолютные пути начинаются с «/».

Вот пример, который следует проиллюстрировать. Рассмотрим класс com.example.A. Рассмотрим два ресурса, один из которых находится в / com / example / nested, другой в / top, в пути к классам. Следующая программа показывает девять возможных способов доступа к двум ресурсам:

package com.example;

public class A {

    public static void main(String args[]) {

        // Class.getResourceAsStream
        Object resource = A.class.getResourceAsStream("nested");
        System.out.println("1: A.class nested=" + resource);

        resource = A.class.getResourceAsStream("/com/example/nested");
        System.out.println("2: A.class /com/example/nested=" + resource);

        resource = A.class.getResourceAsStream("top");
        System.out.println("3: A.class top=" + resource);

        resource = A.class.getResourceAsStream("/top");
        System.out.println("4: A.class /top=" + resource);

        // ClassLoader.getResourceAsStream
        ClassLoader cl = A.class.getClassLoader();
        resource = cl.getResourceAsStream("nested");        
        System.out.println("5: cl nested=" + resource);

        resource = cl.getResourceAsStream("/com/example/nested");
        System.out.println("6: cl /com/example/nested=" + resource);
        resource = cl.getResourceAsStream("com/example/nested");
        System.out.println("7: cl com/example/nested=" + resource);

        resource = cl.getResourceAsStream("top");
        System.out.println("8: cl top=" + resource);

        resource = cl.getResourceAsStream("/top");
        System.out.println("9: cl /top=" + resource);
    }

}

Выход из программы:

1: A.class nested=java.io.BufferedInputStream@19821f
2: A.class /com/example/nested=java.io.BufferedInputStream@addbf1
3: A.class top=null
4: A.class /top=java.io.BufferedInputStream@42e816
5: cl nested=null
6: cl /com/example/nested=null
7: cl com/example/nested=java.io.BufferedInputStream@9304b1
8: cl top=java.io.BufferedInputStream@190d11
9: cl /top=null

В основном все делает то, что вы ожидаете. Случай-3 выходит из строя из-за относительного разрешения класса относительно класса, поэтому «top» означает «/ com / example / top», но «/ top» означает то, что он говорит.

Случай-5 не работает поскольку относительное разрешение класса loader относится к загрузчику классов. Но неожиданно Case-6 также терпит неудачу: можно было бы ожидать, что «/ com / example / nested» будет корректно разрешаться. Чтобы получить доступ к вложенному ресурсу через загрузчик классов, вам необходимо использовать Case-7, то есть вложенный путь относится к корню загрузчика классов. Аналогично, случай-9 выходит из строя, но Case-8 проходит.

Помните: для java.lang.Class getResourceAsStream () делегирует загрузчик классов:

     public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }

, поэтому он поведение resolveName () важно.

Наконец, поскольку поведение загрузчика классов загружает класс, который по существу управляет getResourceAsStream (), а загрузчик классов часто является пользовательским загрузчиком, тогда правила загрузки ресурсов могут быть еще более сложными. например для веб-приложений, загрузки с WEB-INF / classes или WEB-INF / lib в контексте веб-приложения, но не из других изолированных веб-приложений. Кроме того, хорошо управляемые загрузчики классов передают родителям, так что дублированные ресурсы в пути к классам могут быть недоступны с помощью этого механизма.

1
задан tecnotalk 2 April 2009 в 16:31
поделиться

3 ответа

После того, как вы попробовали решение Gamecat, есть серьезные проблемы с обработкой события перерисовывания после изменения размера компонента, поэтому в конце я придумал два возможных обходных пути:

  1. Поскольку подэлементы - это строки, которые я обрабатывал чтобы изменить семейство шрифтов и использовать Wingdings, я использовал символ, похожий на треугольник, тогда я просто изменил цвет шрифта, чтобы он выглядел как глиф. (Я знаю, он не очень чист, но он работал для меня с точки зрения времени и усилий).
  2. Используйте TDataGrid с самого начала, он знает концепцию ячеек, и мы можем добавлять практически все и без нужно беспокоиться о событиях перерисовки. (Бесполезный для меня, потому что на существующем компоненте уже было много функциональности).
1
ответ дан tecnotalk 19 August 2018 в 15:11
поделиться

Используйте компонент TImageList, чтобы удерживать изображения, назначить его свойству SmallImages listviews и установить ImageIndex подэлемента.

2
ответ дан Ondrej Kelle 19 August 2018 в 15:11
поделиться
  • 1
    Он говорит о представлении LIST, а не о представлении TREE. Подпрограммы «Список представлений» образуют другие столбцы данных, а в представлении списка Windows принимаются только значки в основном столбце. – Rob Kennedy 2 April 2009 в 18:10
  • 2
    Я только что попробовал это, чтобы подтвердить. Он работает в Delphi 2007. – Ondrej Kelle 2 April 2009 в 18:52
  • 3
    Спасибо за ваши ответы. Поскольку Тондрей говорит, что я использую компонент TListView, небольшое ограничение состоит в том, что я должен сделать это на Delphi 4. И да, он уже существует! :) – tecnotalk 6 April 2009 в 10:43

Вы можете использовать событие CustomDrawSubItem.

В приведенном ниже примере игнорируется текст и рисуется прямоугольник. К сожалению, это немного хлопот, чтобы получить прямоугольник для правой колонки, но этот подход работает:

procedure TForm.ListViewCustomDrawSubItem(Sender: TCustomListView;
  Item: TListItem; SubItem: Integer; State: TCustomDrawState;
  var DefaultDraw: Boolean);
var
  r : TRect;
  i : Integer;
begin
  r := Item.DisplayRect(drBounds);
  for i := 0 to SubItem-1 do begin
    r.Left := r.Left + ListView.Columns.Items[i].Width;
    r.Right := r.Left  + ListView.Columns.Items[i+1].Width;
  end;
  case SubItem of
     1 : ListView.Canvas.Pen.Color := clRed;
  else
    ListView.Canvas.Pen.Color := clBlue;
  end;

  ListView.Canvas.Rectangle(r.Left, r.Top, r.Right, r.Bottom);
  DefaultDraw := False;
end;
5
ответ дан Toon Krijthe 19 August 2018 в 15:11
поделиться
  • 1
    Спасибо, я попробовал, и это сработало частично. Внутри подтипа можно нарисовать что-либо, но после этого возникает проблема рисования столбца после изменения размера или перемещения компонента (TListView). – tecnotalk 6 April 2009 в 10:58
Другие вопросы по тегам:

Похожие вопросы: