2011-06-23 6 views
7

QListViewでカスタムウィジェットレンダリングを実装するのが難しいです。 現在QListViewにというカスタムモデルが表示されています(QAbstractListModel)。QListViewのQWidgetDelegateのpaint()メソッドでQWidgetをレンダリングする

これは単純なテキストでうまくいきましたが、各要素のカスタムウィジェットを表示したいと思います。 だから私はこのようなpaintメソッドを実装するQStyledItemDelegateをサブクラス化:

void QueueableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    if (option.state & QStyle::State_Selected) 
     painter->fillRect(option.rect, option.palette.highlight()); 
    QWidget *widget = new QPushButton("bonjour"); 
    widget->render(painter); 
} 

選択の背景が正しく描画されているが、何のウィジェットが表示されません。私はQtの例のように、簡単なQPainterコマンドで試してみましたが、これは正常に動作している:

  • は、レンダリングの周りpainter->save()painter->restore()を追加QItemDelegate
  • QStyledItemDelegateを変更する:
    void QueueableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
    { 
        if (option.state & QStyle::State_Selected) 
         painter->fillRect(option.rect, option.palette.highlight()); 
        if (option.state & QStyle::State_Selected) 
         painter->setPen(option.palette.highlightedText().color()); 
        painter->setFont(QFont("Arial", 10)); 
        painter->drawText(option.rect, Qt::AlignCenter, "Custom drawing"); 
    } 
    

    だから私のようないくつかの変更を試してみました
  • ウィジェットジオメトリを使用可能なサイズに設定する

しかし、私はちょっと立ち往生していますが、インターネット上でしばらく検索しましたが、私がしたいことをやっている例は見つからず、ウィジェットを編集するのが大変簡単です。 (プログレスバーのように定義済みのもの)。 しかし、ここで私が作成したカスタムウィジェットが必要です。いくつかのレイアウト、ラベル&ピクスマップが含まれています。 ご協力いただきありがとうございます!

私はUbuntu 11.04でGCCにQt 4.7.3を使用しています。

答えて

3

私は最終的に私が望むことをする方法を考え出しました。ここに私がやったことです:

  1. QListView::indexWidget()
  2. ハンドルをチェックして設定するときに何のウィジェットが既に存在していないことを確認したウィジェット
  3. を設定するために、私のモデルのdata()方法で委譲クラス
  4. コールQListView::setIndexWidget()をドロップQt::SizeHintRole役割はQt::DisplayRole役割
ためのブランクQVariantウィジェットのサイズヒント
  • リターンを返します

    このようにして、私のカスタムウィジェットをQListViewに表示させ、それらを適切に遅延ロードします(これがモデル/ビューパターンを使用した理由です)。しかし、私は表示されていないときに私はそれらをアンロードすることができます表示されません、もう一つの問題です。

  • +0

    荷降ろしをどのように行うのが最適か分かりましたか? – lyschoening

    +0

    ノップ私はしていませんでした:( –

    0

    Hereはあなたのための例です。 QStylePainterを使用する必要があるようですが、これは実際のボタンのようには動作しないことを理解している限り描画用です。

    +0

    うん、私はこの方法を見ましたが、それカスタムウィジェットではなく、定義済みのコントロールを描画するためにのみ機能します。ちなみに、私は実際のプッシュボタンは必要ありませんが、これは例を単純化するためのものでした。私のウィジェットはかなり静的なので、可能であれば描画するだけで問題ありません。 –

    11

    さらに画像全体を完成させるだけです。さらに、代理人を使ってQWidgetをQListViewアイテムとして管理するコードを見つけることができます。

    最後に、QStyledItemDelegateのサブクラスでpaint(...)メソッドを使用する方法を見出しました。

    以前の解決方法よりもパフォーマンスが向上しているようですが、作成したQWidgetでsetIndexWidget()を実行するかどうかを検証する必要があります。

    だから、最終的には、ここでのコードは次のとおりです。

    class PackageListItemWidget: public QWidget 
    

    .....

    class PackageListItemDelegate: public QStyledItemDelegate 
    

    .....

    void PackageListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
    { 
    
    // here we have active painter provided by caller 
    
    // by the way - we can't use painter->save() and painter->restore() 
    // methods cause we have to call painter->end() method before painting 
    // the QWidget, and painter->end() method deletes 
    // the saved parameters of painter 
    
    // we have to save paint device of the provided painter to restore the painter 
    // after drawing QWidget 
    QPaintDevice* original_pdev_ptr = painter->device(); 
    
    // example of simple drawing (selection) before widget 
    if (option.state & QStyle::State_Selected) 
        painter->fillRect(option.rect, option.palette.highlight()); 
    
    // creating local QWidget (that's why i think it should be fasted, cause we 
    // don't touch the heap and don't deal with a QWidget except painting) 
    PackageListItemWidget item_widget; 
    
    // Setting some parameters for widget for example 
        // spec. params 
    item_widget.SetPackageName(index.data(Qt::DisplayRole).toString());  
        // geometry 
    item_widget.setGeometry(option.rect); 
    
    // here we have to finish the painting of provided painter, cause 
    //  1) QWidget::render(QPainter *,...) doesn't work with provided external painter 
    //   and we have to use QWidget::render(QPaintDevice *,...) 
    //   which creates its own painter 
    //  2) two painters can't work with the same QPaintDevice at the same time 
    painter->end(); 
    
    // rendering of QWidget itself 
    item_widget.render(painter->device(), QPoint(option.rect.x(), option.rect.y()), QRegion(0, 0, option.rect.width(), option.rect.height()), QWidget::RenderFlag::DrawChildren); 
    
    // starting (in fact just continuing) painting with external painter, provided 
    // by caller 
    painter->begin(original_pdev_ptr); 
    
    // example of simple painting after widget 
    painter->drawEllipse(0,0, 10,10); 
    }; 
    
    +1

    これをちょっと説明した後、オフセットポイントにdeviceTransform()を手動で適用して整列させる必要があることがわかりました。 'painter-> end();' QWidget :: render()の2番目の引数としてmappedoriginを渡したところ、QPoint mappedorigin = painter-> deviceTransform()。map(QPoint(option.rect.x()、option.rect.y()))この関数でウィジェットを作成した場合はこれは必要ではないかもしれませんが、親ウィジェットの一部として作成しました –

    +0

    これは唯一の仕事です。ありがとうございます。@AndrewDomaszekのマッピングを追加する必要がありました –

    関連する問題