2010-03-03 50 views
6

什麼是呈現點擊網址的最佳途徑QTableView(或QTreeViewQListView,等...)如何在QTableView中

打開一個URL給定一個QStandardItemModel,其中一些列包含帶有URL的文本我希望它們變得可點擊,然後使用QDesktopServices::openURL()

我希望有一些簡單的方法可以利用QLabel的textInteraction標誌並將它們塞進表中。我不敢相信沒有更簡單的方法來處理這個問題。我真的很希望我錯過了一些東西。

回答

5

您需要創建一個委託來完成繪畫。代碼應該是這個樣子:

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

卡萊布,這是在tableview中繪製超鏈接的唯一方法,topicstarter希望瞭解如何在那裏創建可點擊的鏈接,而不需要將QTextBrowser放入每個單元格中。 – 2012-11-11 17:49:41

+0

我非常擔心,如果您知道方式,請告訴我們,怎麼樣才能做到這一點。 – 2012-11-11 17:50:24

+0

然後,您將重新實現QAbstractItemDelegate :: editorEvent()以接收鼠標點擊,並且如果點擊位於鏈接上,請使用QDesktopServices :: openUrl()打開URL。 – 2015-06-09 21:20:02

2

那麼,你可以使用委託與定製代表重新實現paint方法,如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()); 
} 

然而,不會使超鏈接可點擊。

爲此,您可以使用以下hack。重新實現table/list視圖的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列。請注意,您需要取消模型中的顯示角色以避免重疊數據。

無論如何,我會對基於代表的更好的解決方案感興趣。

0

不幸的是,當使用QTableView(而不是使用QTableWidget)時,使用setOpenExternalLinks()呈現QLabel並不容易。沒有什麼神奇的兩行代碼可以調用並完成工作。

  1. 使用委託
  2. 設置委託到表格的列
  3. 使用QTextDocument與​​組合以呈現的HTML鏈接
  4. 這意味着模型需要提供含有a href
  5. 一個HTML片段
  6. 計算鏈接的幾何形狀並提供事件處理程序以攔截鼠標
    • 改變光標當它是在鏈路
    • 鏈接被點擊
  7. 時執行的操作,我想什麼亂七八糟:(painter->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(); 
}