2011-11-25 19 views
5

Mi QTreeWidget tiene una sola columna. Sus elementos tienen una casilla de verificación, un icono y texto. Si el usuario hace clic dentro de un elemento, quiero saber si se hizo clic en el icono. ¿Cómo puedo encontrar la posición y el tamaño del icono en un QTreeWidgetItem?Posición del icono en QTreeWidgetItem

Actualizado para añadir: Aquí está el código para mi solución final, tal como lo solicitó webclectic.

Primero, clasifiqué QItemDelegate para poder acceder a las coordenadas de cada parte de un QTreeWidgetItem (casilla de verificación, icono y texto). Aquí está el archivo de cabecera:

#include <QItemDelegate> 

class MyItemDelegate : public QItemDelegate 
    { 
    Q_OBJECT 

public: 
    explicit MyItemDelegate (MyTreeWidget *parent) 
    : QItemDelegate (parent), ParentView (parent) { } 
    ~MyItemDelegate() { } 

    void GetRects (const QModelIndex &index, QRect& CheckBox, QRect& Icon, QRect& Text) const ; 

private: 
    MyTreeWidget* ParentView ; 
    } ; 

Y aquí está el archivo de origen:

void MyItemDelegate::GetRects (const QModelIndex &index, QRect& CheckBox, QRect& Icon, QRect& Text) const 
    { 
    QStyleOptionViewItem option = ParentView -> viewOptions() ; 
    CheckBox = rect (option, index, Qt::CheckStateRole) ; 
    Icon = rect (option, index, Qt::DecorationRole) ; 
    Text = rect (option, index, Qt::DisplayRole) ; 

    doLayout (option, &CheckBox, &Icon, &Text, true) ; 

    QRect VisualRect = ParentView -> visualRect (index) ; 
    CheckBox.translate (VisualRect.topLeft()) ; 
    Icon.translate (VisualRect.topLeft()) ; 
    Text.translate (VisualRect.topLeft()) ; 
    } 

Luego añade un miembro MyItemDelegate*-MyTreeWidget, y configurarlo como delegado de la vista del elemento. En el encabezado:

class MyTreeWidget : public QTreeWidget 
    { 
    ... 
    MyItemDelegate* Delegate ; 
    ... 
    } ; 

en la fuente:

MyTreeWidget::MyTreeWidget (QObject* parent) 
    { 
    ... 
    Delegate = new MyItemDelegate (this) ; 
    setItemDelegate (ItemDelegate) ; 
    } 

Ahora, para obtener las coordenadas de cada parte de un QTreeWidgetItem:

QTreeWidgetItem* item ; 
    ... 
    QModelIndex ModelIndex = indexFromItem (item) ; 
    QRect CheckBoxRect, IconRect, TextRect ; 
    ItemDelegate -> GetRects (ModelIndex, &CheckBoxRect, &IconRect, &TextRect) ; 

Respuesta

2

Desafortunadamente no hay una forma sencilla de lograr Lo que quieras. El problema es que QTreeWidget es responsable de pintar sus elementos para que el elemento en sí no tenga información sobre la posición de sus elementos en la vista.

En primer lugar, tiene que subclase QTreeWidget y vuelva a implementar el mousePressEvent (o mouseReleaseEvent si lo prefiere). Dentro del evento, debe calcular la posición del icono y manejarlo de manera correspondiente.

Código de ejemplo (pero no probado) del siguiente modo:

void mousePressEvent(QMouseEvent *event) 
{ 
    QModelIndex clickedIndex = indexAt(event->pos()); 
    // make sure the event was on a valid item 
    if (clickedIndex.isValid() == false) 
     return; 

    // Get the tree widget's x position 
    int treeX = header()->sectionViewportPosition(0); 

    // Get the x coordinate of the root item. It is required in order to calculate 
    // the identation of the item 
    int rootX = visualRect(rootIndex()).x(); 

    // Get the rectangle of the viewport occupied by the pressed item 
    QRect vrect = visualRect(clickedIndex); 

    // Now we can easily calculate the x coordinate of the item 
    int itemX = treeX + vrect.x() - rootX; 

    // The item is a checkbox, then an icon and finally the text. 

    // 1. Get the rect surrounding the checkbox 
    QRect checkboxRect = QRect(itemX, 
           vrect.y(), 
           style()->pixelMetric(QStyle::PM_IndicatorWidth), 
           vrect.height()); 

    // 2. Get the rect surrounding the icon 
    QRect iconRect = QRect(itemX + checkboxRect.width(), 
          vrect.y(), 
          iconSize().width(), 
          vrect.height()); 

    // 3. Finally get the rect surrounding the text 
    QRect textRect = QRect(itemX + checkboxRect.width() + iconRect.width(), 
          vrect.y(), 
          vrect.width() - checkboxRect.width() - iconRect.width(), 
          vrect.height());  

    // Now check where the press event took place and handle it correspondingly 

    if(checkboxRect.contains(event->pos())) 
    { 
     qDebug() << "Checkbox pressed"; 
     QTreeWidget::mousePressEvent(event); 
     return; 
    } 
    else if (iconRect.contains(event->pos())) 
    { 
     qDebug() << "Icon pressed"; 
     QTreeWidget::mousePressEvent(event); 
     return; 
    } 
    else 
    { 
     qDebug() << "Text pressed"; 
     QTreeWidget::mousePressEvent(event); 
     return; 
    } 
} 

repito que el código no se ha probado, pero se entiende la idea acerca de cómo lograr lo que quiere.

+0

Probé esto, y esa cosa con 'PM_IndicatorWidth' funciona bien. ¡Gracias por eso! Además, 'iconSize()' devuelve (-1, -1), pero si llamo 'setIconSize()' primero, funciona. Parece circular, pero de hecho resolvió mi problema con los íconos que eran más pequeños de lo que quería. – TonyK

+0

Es bueno saber ... :) – pnezis

+0

Después de algunas pruebas, descubrí que esta solución tampoco funciona: ignora los márgenes alrededor de la casilla de verificación y el ícono. Para hacerlo correctamente, tuve que subclasificar QItemDelegate y proporcionar una versión de sizeHint que devuelve las tres partes (casilla de verificación, icono, texto) por separado. Pero me pusiste en el camino correcto. – TonyK