【问题标题】:How to open an URL in a QTableView如何在 QTableView 中打开 URL
【发布时间】:2010-03-03 23:15:43
【问题描述】:

QTableView(或QTreeViewQListView 等...)中显示可点击 URL 的最佳方式是什么

给定一个QStandardItemModel,其中一些列包含带有 URL 的文本,我希望它们变为可点击,然后使用 QDesktopServices::openURL() 处理点击

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

【问题讨论】:

    标签: c++ qt url qt4 qtableview


    【解决方案1】:

    您需要创建一个委托来进行绘制。代码应如下所示:

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

    【讨论】:

    • Kaleb,这是在 tableview 中绘制超链接的唯一方法,并且 topicstarter 想要实现,如何在其中制作可点击的链接,而无需将 QTextBrowser 放入每个单元格。
    • 我很担心,我也可以,如果你知道方法,请告诉我们,怎么做。
    【解决方案2】:

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

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

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

    为此,您可以使用以下技巧。重新实现表格/列表视图的 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);
        }
    }
    

    在上面的示例中,我将第 1 列替换为 qlabels。请注意,您需要取消模型中的显示角色以避免重叠数据。

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

    【讨论】:

    • 什么是CTableModel :: HtmlRole? 'CTableModel' 尚未声明
    • 前一种方法中new QLabel 的内存泄漏怎么办?
    【解决方案3】:

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

    1. 使用委托
    2. 将委托设置为表格列
    3. 使用QTextDocument结合setHTML()来呈现一个html链接
    4. 这意味着你的模型需要提供一个包含a href的HTML片段
    5. 计算链接的几何形状并提供事件处理程序以拦截鼠标
      • 在链接上改变光标
      • 点击链接时执行动作
    6. 真是一团糟:(我想要painter-&gt;setWidgetToCell()

    --

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 2021-12-30
      • 2014-04-25
      • 2017-02-20
      • 2017-01-25
      相关资源
      最近更新 更多