如何在 QTableView 中打开 URL
Posted
技术标签:
【中文标题】如何在 QTableView 中打开 URL【英文标题】:How to open an URL in a QTableView 【发布时间】:2010-03-03 23:15:43 【问题描述】:在QTableView
(或QTreeView
、QListView
等...)中显示可点击 URL 的最佳方式是什么
给定一个QStandardItemModel
,其中一些列包含带有 URL 的文本,我希望它们变为可点击,然后使用 QDesktopServices::openURL()
处理点击
我希望有一些简单的方法可以利用 QLabel
的 textInteraction 标志并将它们塞进表格中。我不敢相信没有更简单的方法来处理这个问题。我真的希望我错过了什么。
【问题讨论】:
【参考方案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
并不容易。没有神奇的两行代码可以调用并完成工作。
-
使用委托
将委托设置为表格列
使用
QTextDocument
结合setHTML()
来呈现一个html链接
这意味着你的模型需要提供一个包含a href
的HTML片段
计算链接的几何形状并提供事件处理程序以拦截鼠标
在链接上改变光标
点击链接时执行动作
真是一团糟:(我想要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();
【讨论】:
以上是关于如何在 QTableView 中打开 URL的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据发送到 QTableView/QTableWidget (PyQt)
如何在 QTableView 单元格角落绘制三角形以显示可以从列表中选择的模型数据?