2011-11-25 7 views
5

Il mio QTreeWidget ha una singola colonna. I suoi elementi hanno una casella di controllo, un'icona e un testo. Se l'utente fa clic all'interno di un elemento, voglio sapere se l'icona è stata selezionata. Come posso trovare la posizione e la dimensione dell'icona in un QTreeWidgetItem?Posizione dell'icona in QTreeWidgetItem

Aggiornamento aggiornato per aggiungere: Ecco il codice per la mia soluzione finale, come richiesto da webclectic.

In primo luogo, ho sottoclassificato QItemDelegate in modo da poter accedere alle coordinate di ciascuna parte di un QTreeWidgetItem (casella di controllo, icona e testo). Ecco il file di intestazione:

#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 ; 
    } ; 

E qui è il file di origine:

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()) ; 
    } 

poi ho aggiunto un membro MyItemDelegate*-MyTreeWidget, e impostarlo come delegato della vista oggetto. Nell'intestazione:

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

nella fonte:

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

Ora, per ottenere le coordinate di ciascuna parte di un QTreeWidgetItem:

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

risposta

2

Purtroppo non esiste un modo semplice per ottenere ciò che vuoi. Il problema è che QTreeWidget è responsabile della verniciatura dei suoi articoli in modo che l'elemento stesso non abbia informazioni sulla posizione dei suoi elementi nella vista.

Prima di tutto è necessario sottoclasse QTreeWidget e reimplementare il mousePressEvent (o mouseReleaseEvent se si preferisce). All'interno dell'evento è necessario calcolare la posizione dell'icona e gestirla in modo corrispondente.

codice di esempio (ma non testato) segue:

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; 
    } 
} 

Ripeto che il codice non è testato, ma si ottiene l'idea su come ottenere quello che vuoi.

+0

Ho provato questo, e quella cosa con 'PM_IndicatorWidth' funziona bene. Grazie per quello! Inoltre, 'iconSize()' restituisce (-1, -1), ma se chiamo 'setIconSize()' prima funziona. Sembra circolare, ma in realtà ha risolto il mio problema con le icone più piccole di quanto volessi. – TonyK

+0

Buono a sapersi .. :) – pnezis

+0

Dopo alcuni test, ho scoperto che questa soluzione non funziona: ignora i margini attorno alla casella di controllo e all'icona. Per farlo correttamente, ho dovuto sottoclasse QItemDelegate e fornire una versione di sizeHint che restituisce le tre parti (casella di controllo, icona, testo) separatamente. Ma tu mi metti sulla buona strada. – TonyK