После нескольких часов работы я могу нарисовать виджет на QListView
, Тем не менее, картина делается через QPixmap
, Появляется виджет, и я вижу индикатор выполнения. Тем не менее, это немного «неровной» (из-за использования QPixmap
). Можно ли рисовать напрямую как обычный виджет? Это мой вопрос.
Вот что я делаю:
void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QPaintDevice* original_pdev_ptr = painter->device();
FileQueueListItem* itemWidget = reinterpret_cast<FileQueueListItem*>(index.data(Qt::UserRole).value<void*>());
itemWidget->setGeometry(option.rect);
painter->end();
QPixmap pixmap(itemWidget->size());
if (option.state & QStyle::State_Selected)
pixmap.fill(option.palette.highlight().color());
else
pixmap.fill(option.palette.background().color());
itemWidget->render(&pixmap,QPoint(),QRegion(),QWidget::RenderFlag::DrawChildren);
painter->begin(original_pdev_ptr);
painter->drawPixmap(option.rect, pixmap);
}
Я узнал, как сделать то, что я сделал с подсказками Вот. Там картина делается прямо на QListView
Это то, чего я хочу достичь. Что я делаю не так для следующей попытки не работать:
void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
std::cout<<"Painting..."<<std::endl;
QPaintDevice* original_pdev_ptr = painter->device();
FileQueueListItem* itemWidget = reinterpret_cast<FileQueueListItem*>(index.data(Qt::UserRole).value<void*>());
itemWidget->setGeometry(option.rect);
painter->end();
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
else
painter->fillRect(option.rect, option.palette.background());
itemWidget->render(painter->device(),
QPoint(option.rect.x(), option.rect.y()),
QRegion(0, 0, option.rect.width(), option.rect.height()),
QWidget::RenderFlag::DrawChildren);
painter->begin(original_pdev_ptr);
}
Список просто остается пустым, и ничего не происходит. Хотя выбор можно увидеть, но виджет не отображается.
Давайте проясним несколько вещей:
Вы не должны создавать виджеты и помещать их в модель. Для этого есть очень веская причина. Виджеты участвуют в Цикл событий Qt, Это означает, что слишком большое количество виджетов значительно замедлит вашу программу.
Виджеты — это не просто набор элементов управления (кажется, как вы их видите). Они принимают участие в цикле событий, поэтому у вас не должно быть виджета, который является частью модели данных.
Если вы используете многопоточную программу, и наша модель отделена от представления, управление памятью станет кошмаром. Qt никогда не потерпит попыток создать или удалить какие-либо виджеты из других потоков (что имеет смысл, поскольку отсоединение потоков от цикла обработки событий обычно не является потокобезопасным).
Учитывая эту информацию, как правильно делать то, что вы пытаетесь сделать? К сожалению, единственный правильный способ — нарисовать элементы управления самостоятельно. Если ваш виджет прост, это легко сделать. Если ваш виджет сложный, вам понадобится много математики для расчета позиций каждого виджета.
в Пример Qt Torrent, Вы увидите, как нарисован индикатор выполнения. Все, что вам нужно сделать, чтобы нарисовать свои элементы управления, это рассчитать положение и использовать rect
Переменная-член в качестве содержащего прямоугольника элементов управления, а затем нарисовать их (конечно, после установки их значений). Функция paint()
имеет option.rect
параметр в нем, который является прямоугольником всего элемента. Все, что вам нужно сделать, это использовать некоторую математику, чтобы вычислить позиции внутри этого прямоугольника для каждого виджета.
PS: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ АБСОЛЮТНЫЕ ЗНАЧЕНИЯ ДЛЯ ПОЗИЦИЙ. Вы никогда не поймете это правильно, особенно для разных точек на дюйм.
Это нарисует элементы управления без виджетов и гарантирует необходимую скорость даже для тысяч элементов.
Других решений пока нет …