9

クリック可能なURL をQTableView(またはQTreeView、、QListViewなど...)で表示する最良の方法は何ですか?

一部QStandardItemModelの列にURL付きのテキストが含まれている場合、それらをクリック可能にしてから、次を使用してクリックを処理したいと思いますQDesktopServices::openURL()

QLabelの textInteraction フラグを活用してテーブルに詰め込む簡単な方法があることを期待していました。これを処理する簡単な方法がないとは信じられません。何かが足りないことを本当に願っています。

4

3 に答える 3

7

描画を行うデリゲートを作成する必要があります。コードは次のようになります。

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();
}
于 2010-03-03T23:42:56.970 に答える
4

さて、次のようなペイント メソッドを再実装するカスタム デリゲートを使用して、デリゲートを使用して 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 に置き換えます。データの重複を避けるために、モデルの表示ロールを無効にする必要があることに注意してください。

とにかく、デリゲートに基づくより良いソリューションに興味があります。

于 2013-12-13T12:50:03.153 に答える
2

悲しいことに、( を使用するのではなく) を使用QLabelするsetOpenExternalLinks()場合、を でレンダリングするのはそれほど簡単ではありません。呼び出して仕事を完了させる魔法の 2 行のコードはありません。QTableViewQTableWidget

  1. デリゲートを使用する
  2. デリゲートをテーブルの列に設定します
  3. QTextDocumentと組み合わせて使用setHTML()​​して、html リンクをレンダリングします
  4. これは、モデルが次を含む HTML フラグメントを提供する必要があることを意味します。a href
  5. リンクのジオメトリを計算し、マウスをインターセプトするためのイベント ハンドラーを提供する
    • カーソルがリンク上にあるときにカーソルを変更する
    • リンクがクリックされたときにアクションを実行する
  6. なんて混乱します:(欲しい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();
}
于 2016-03-08T13:28:02.983 に答える