Este artículo aborda la personalización de la apariencia de QTreeView en Qt, un widget de vista de árbol, mediante la sobreescritura de eventos de dibujado y el uso de QPainter. Aunque las hojas de estilo de Qt ofrecen algunas opciones, a menudo es necesario un control más detallado para lograr efectos visuales específicos. A continuación, se descirben los pasos clave para implementar un diseño único, incluyendo el color de fondo, el estilo de las celdas y la gestión de interacciones con el ratón.
Establecer el Color de Fondo del Widget
Se comienza sobrescribeindo el evento de pintura para dibujar un fondo personalizado y manejar estados vacíos.
void CustomTreeView::paintEvent(QPaintEvent* paintEvent)
{
QPainter renderer(viewport());
renderer.setPen(Qt::NoPen);
renderer.setBrush(QColor(35, 40, 48));
renderer.drawRect(viewport()->rect());
int totalItems = dataModel->rowCount(rootIndex());
if (totalItems == 0) {
QFont displayFont("Segoe UI");
displayFont.setPointSize(10);
renderer.setFont(displayFont);
renderer.setPen(QColor(140, 145, 155));
renderer.drawText(viewport()->width() / 2 - 80, viewport()->height() / 2, 160, 30, Qt::AlignCenter, "Sin elementos disponibles");
return;
}
QTreeView::paintEvent(paintEvent);
}
Dibujar el Estilo de las Celdas
Cada fila se dibuja personalizadamente mediante la sobrescritura del método drawRow, gestionando diferentes estados visuales.
void CustomTreeView::drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
{
if (!modelIndex.isValid())
return;
painter->save();
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
QString itemPath = dataModel->filePath(modelIndex);
QFileInfo fileInfo(itemPath);
QRect cellRect = option.rect;
bool isActive = false, isHighlighted = false, isNormal = true;
if (itemPath == selectedFilePath) {
isHighlighted = true;
isNormal = false;
} else if (modelIndex == currentIndex()) {
isActive = true;
isNormal = false;
}
int baseIndentation = calculateIndentation(modelIndex);
if (isNormal) {
painter->setBrush(QColor(35, 40, 48));
painter->setPen(Qt::NoPen);
painter->drawRect(cellRect);
} else if (isHighlighted && !fileInfo.isDir()) {
painter->setBrush(QColor(45, 50, 58));
painter->setPen(Qt::NoPen);
painter->drawRect(cellRect);
} else if (isActive) {
painter->setBrush(QColor(40, 45, 53));
painter->setPen(Qt::NoPen);
painter->drawRect(cellRect);
}
drawIcon(painter, cellRect, modelIndex, baseIndentation, fileInfo);
drawTextContent(painter, cellRect, modelIndex, baseIndentation);
drawExpansionIndicator(painter, cellRect, modelIndex, fileInfo);
painter->restore();
}
Las funciones auxiliares como calculateIndentation, drawIcon, drawTextContent y drawExpansionIndicator encapsulan la lógica específica para mayor claridad.
Gestionar Eventos del Ratón para Interacción
Se sobrescriben los eventos de clic y doble clic para controlar la selección y la expansión de nodos.
void CustomTreeView::mousePressEvent(QMouseEvent* mouseEvent)
{
QTreeView::mousePressEvent(mouseEvent);
QModelIndex clickedIndex = indexAt(mouseEvent->pos());
if (!clickedIndex.isValid())
return;
QString clickedPath = dataModel->filePath(clickedIndex);
QFileInfo info(clickedPath);
if (!info.isDir())
return;
QRect expandArea(10, 0, 16, rowHeight(clickedIndex));
if (!expandArea.contains(mouseEvent->pos().x(), mouseEvent->pos().y() % rowHeight(clickedIndex)))
return;
QDir directory(clickedPath);
if (directory.isEmpty())
return;
if (isExpanded(clickedIndex))
collapse(clickedIndex);
else
expand(clickedIndex);
}
void CustomTreeView::mouseDoubleClickEvent(QMouseEvent* mouseEvent)
{
QModelIndex indexUnderMouse = indexAt(mouseEvent->pos());
if (indexUnderMouse != currentIndex())
return;
QString path = dataModel->filePath(indexUnderMouse);
if (!dataModel->isDir(indexUnderMouse)) {
selectedFilePath = path;
}
update();
QTreeView::mouseDoubleClickEvent(mouseEvent);
}
Estas implementaciones permiten una interacción personalizada, como selecccionar archivos con doble clic y expandir carpetas con clic en áreas específicas.
Al combinar estas técnicas, se logra un control completo sobre la apariencia y el comportamiento de QTreeView, adaptándolo a requisitos visuales avanzados sin depender únicamente de las hojas de estilo estándar.