【问题标题】:Position of icon in QTreeWidgetItemQTreeWidgetItem 中图标的位置
【发布时间】:2011-11-25 20:55:40
【问题描述】:

我的QTreeWidget 有一个列。它的项目有一个复选框、一个图标和文本。如果用户在一个项目内单击,我想知道该图标是否被单击。如何在QTreeWidgetItem 中找到图标的位置和大小?

更新添加:这是我最终解决方案的代码,应 webclectic 的要求。

首先,我对QItemDelegate 进行了子分类,以便我可以访问QTreeWidgetItem(复选框、图标和文本)的每个部分的坐标。这是头文件:

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

这里是源文件:

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

然后我向MyTreeWidget 添加了一个MyItemDelegate* 成员,并将其设置为项目视图的委托。在标题中:

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

在源码中:

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

现在,获取QTreeWidgetItem的每个部分的坐标:

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

【问题讨论】:

    标签: qt


    【解决方案1】:

    不幸的是,没有简单的方法可以实现您想要的。问题是QTreeWidget 负责绘制其项目,因此项目本身没有关于其元素在视图中的位置的信息。

    首先,您必须继承QTreeWidget 并重新实现mousePressEvent(或mouseReleaseEvent,如果您愿意)。在事件内部,您应该计算图标的位置并进行相应的处理。

    示例代码(但未经测试)如下:

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

    我再说一遍,代码未经测试,但您知道如何实现您想要的。

    【讨论】:

    • 我试过了,PM_IndicatorWidth 的那个东西很好用。感谢那!此外,iconSize() 返回 (-1,-1),但如果我首先调用 setIconSize(),它会起作用。这看起来是圆形的,但实际上它解决了我的问题,即图标比我想要的要小。
    • 经过一些测试,我发现这个解决方案也不起作用——它忽略了复选框和图标周围的边距。为了正确地做到这一点,我必须继承 QItemDelegate 并提供一个 sizeHint 版本,它分别返回三个部分(复选框、图标、文本)。但你让我走上了正轨。
    • 您能否发布一些工作代码,作为您问题中的编辑,以供将来参考?
    • 完成。好吧,不工作的代码,确切地说——我不得不修剪太多。
    • @TonyK 查看 QItemDelegate 的源代码,您会得到style()-&gt;pixelMetric( QStyle::PM_FocusFrameHMargin ) + 1 的优势。神奇的 +1 虽然不是很容易解释,但它的效果相对较好,虽然 +2 似乎更好,但出于某种我不明白的原因,但那是头发分裂。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 2013-12-18
    • 2018-05-20
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    相关资源
    最近更新 更多