Peindre un widget directement sur QListView avec QStyledItemDelegate :: paint ()

Après des heures de travail, je peux peindre un widget sur QListView . Cependant, la peinture est réalisée via un QPixmap . Le widget apparaît et une barre de progression s’affiche. Cependant, c’est un peu “pixellisé” (en raison de l’utilisation de QPixmap ). Est-il possible de peindre directement en tant que widget normal? C’est ma question.

Voici ce que je fais:

 void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QPaintDevice* original_pdev_ptr = painter->device(); FileQueueListItem* itemWidget = reinterpret_cast(index.data(Qt::UserRole).value()); 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); } 

J’ai appris à faire ce que j’ai fait avec les astuces d’ ici . Là, la peinture est faite directement sur QListView , ce que je cherche à réaliser. Qu’est-ce que je fais mal pour la tentative suivante de ne pas travailler:

 void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { std::cout<<"Painting..."<device(); FileQueueListItem* itemWidget = reinterpret_cast(index.data(Qt::UserRole).value()); 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); } 

La liste rest vide et rien ne se passe. Bien que la sélection soit visible, le widget ne s’affiche pas.

Faisons quelques choses claires:

  1. Vous n’êtes pas censé créer des widgets et les placer dans un modèle. Il y a une très bonne raison pour cela. Les widgets sont impliqués dans la boucle d’événements Qt , ce qui signifie que trop de widgets ralentiront considérablement votre programme.

  2. Les widgets ne sont pas simplement un ensemble de contrôles (ce qui semble être la façon dont vous les voyez). Ils participent à la boucle d’événements. C’est pourquoi vous ne devriez pas avoir un widget qui fasse partie d’un modèle de données.

  3. Si vous utilisez un programme multithread et que votre modèle est séparé de la vue, la gestion de la mémoire deviendra un cauchemar. Qt ne tolérera jamais d’essayer de construire ou de supprimer des widgets d’autres threads (ce qui est logique, car le détachement de threads de la boucle d’événements n’est généralement pas sécurisé pour les threads).

Compte tenu de cette information, quelle est la bonne façon de faire ce que vous essayez de faire? Malheureusement, le seul moyen correct consiste à dessiner les contrôles vous-même. Si votre widget est simple, c’est facile à faire. Si votre widget est compliqué, vous aurez besoin de beaucoup de maths pour calculer les positions de chaque widget.

Dans l’ exemple Qt Torrent , vous verrez comment une barre de progression est dessinée. Tout ce que vous avez à faire pour dessiner vos contrôles consiste à calculer la position et à utiliser la variable membre rect tant que rectangle contenant les contrôles, puis à les dessiner (bien sûr, après avoir défini leurs valeurs). La fonction paint() contient un paramètre option.rect , qui est le rectangle de l’élément entier. Tout ce que vous avez à faire est d’utiliser des calculs pour calculer les positions à l’intérieur de ce rect pour chaque widget.

PS: N’UTILISEZ JAMAIS DE VALEURS ABSOLUES POUR LES POSITIONS. Vous ne réussirez jamais, en particulier pour différents DPI.

Cela permettra de tirer les commandes sans widgets et de garantir la vitesse dont vous avez besoin, même pour des milliers d’éléments.