如何在QTableView中打开URL

时间:2010-03-03 23:15:43

标签: c++ qt url qt4 qtableview

QTableView(或QTreeViewQListView等)中提供可点击网址的最佳方式是什么?)< / b>

给定QStandardItemModel,其中某些列包含带有网址的文字,我希望它们可以点击,然后使用QDesktopServices::openURL()

处理点击

我希望能有一些简单的方法来利用QLabel的textInteraction标志并将它们塞进表中。我无法相信没有更简单的方法来处理这个问题。我真的希望我错过了什么。

3 个答案:

答案 0 :(得分:6)

您需要创建一个委托来进行绘画。代码看起来像这样:

void RenderLinkDelegate::paint(
           QPainter *painter,
           const QStyleOptionViewItem &option,
           const QModelIndex &index
           ) const
{
    QString text = index.data(Qt::DisplayRole).toString();
    if (text.isEmpty())
        return;

    painter->save();

    // I only wanted it for mouse over, but you'll probably want to remove
    // this condition
    if (option.state & QStyle::State_MouseOver)
    {
        QFont font = option.font;
        font.setUnderline(true);
        painter->setFont(font);
        painter->setPen(option.palette.link().color());
    }
    painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, text);

    painter->restore();
}

答案 1 :(得分:5)

好吧,您可以使用委托在qtableview中呈现富文本,并使用自定义委托重新实现paint方法,例如:

void CHtmlDelegate::paint(QPainter *painter,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
{
    QStyleOptionViewItemV4 opt(option);

    QLabel *label = new QLabel;
    label->setText(index.data().toString());
    label->setTextFormat(Qt::RichText);
    label->setGeometry(option.rect);
    label->setStyleSheet("QLabel { background-color : transparent; }");

    painter->translate(option.rect.topLeft());
    label->render(painter);
    painter->translate(-option.rect.topLeft());
}

但是,它不会使超链接可以点击。

为此,您可以使用以下hack。重新实现表/列表视图的setModel方法并使用setIndexWidget。

void MyView::setModel(QAbstractItemModel *m)
{
  if (!m)
    return;

  QTableView::setModel(m);

  const int rows = model()->rowCount();
  for (int i = 0; i < rows; ++i)
    {
      QModelIndex idx = model()->index(i, 1);

      QLabel *label = new QLabel;
      label->setTextFormat(Qt::RichText);
      label->setText(model()->data(idx, CTableModel::HtmlRole).toString());
      label->setOpenExternalLinks(true);

      setIndexWidget(idx, label);
    }
}

在上面的例子中,我用qlabels替换了第1列。请注意,您需要使模型中的显示角色无效,以避免重叠数据。

无论如何,我会对基于代表的更好的解决方案感兴趣。

答案 2 :(得分:1)

遗憾的是,使用QLabel(而不是使用setOpenExternalLinks())时,使用QTableView呈现QTableWidget并不容易。没有神奇的两行代码可以调用并完成工作。

  1. 使用代理
  2. 将代理设置为表格的列
  3. 使用QTextDocumentsetHTML()相结合来呈现html链接
  4. 这意味着您的模型需要提供包含a href
  5. 的HTML片段
  6. 计算链接的几何形状,并提供拦截鼠标的事件处理程序
    • 当光标位于链接上时更改光标
    • 单击链接时执行操作
  7. 多么糟糕:(我想要painter->setWidgetToCell()
  8. -

    void LabelColumnItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    
        if( option.state & QStyle::State_Selected )
            painter->fillRect( option.rect, option.palette.highlight() );
    
    
        painter->save();
    
        QTextDocument document;                         // <---- RichText 
        document.setTextWidth(option.rect.width());
    
        QVariant value = index.data(Qt::DisplayRole);
        if (value.isValid() && !value.isNull())
        {
            document.setHtml(value.toString());        // <---- make sure model contains html
    
            painter->translate(option.rect.topLeft());
            document.drawContents(painter);        
        }
    
        painter->restore();
    }