web-dev-qa-db-ja.com

カスタムアイテムとカスタムアイテムウィジェットを持つQListView / QListWidget

PyQtアプリケーションを作成していて、カスタムリストビューの作成に問題があります。リストに任意のウィジェット(特に1つのカスタムウィジェット)を含めたい。これについてどうすればいいですか?

代替案は、スクロールバーにラップされたテーブルまたはグリッドビューを作成することです。ただし、組み込みのハンドルをサポートする入れ子(ツリービュー)だけでなく、モデル/ビューのアプローチを利用できるようにしたいと思います。

明確にするために、カスタムウィジェットはインタラクティブ(ボタンを含む)であるため、ソリューションにはウィジェットの描画以上のものが必要です。

30
Daniel Naab

QItemDelegate をサブクラス化する必要があると思います。

QItemDelegateを使用して、QAbstractItemViewサブクラスに基づくアイテムビューにカスタム表示機能とエディターウィジェットを提供できます。この目的でデリゲートを使用すると、モデルとビューから独立して、表示および編集メカニズムをカスタマイズおよび開発できます。

このコードは、Qtの例、急流アプリケーションから取得されます。

class TorrentViewDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {}

    inline void Paint(QPainter *Painter, const QStyleOptionViewItem &option,
                      const QModelIndex &index ) const
    {
        if (index.column() != 2) {
            QItemDelegate::Paint(Painter, option, index);
            return;
        }

        // Set up a QStyleOptionProgressBar to precisely mimic the
        // environment of a progress bar.
        QStyleOptionProgressBar progressBarOption;
        progressBarOption.state = QStyle::State_Enabled;
        progressBarOption.direction = QApplication::layoutDirection();
        progressBarOption.rect = option.rect;
        progressBarOption.fontMetrics = QApplication::fontMetrics();
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.textAlignment = Qt::AlignCenter;
        progressBarOption.textVisible = true;

        // Set the progress and text values of the style option.
        int progress = qobject_cast<MainWindow *>(parent())->clientForRow(index.row())->progress();
        progressBarOption.progress = progress < 0 ? 0 : progress;
        progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress);

        // Draw the progress bar onto the view.
        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, Painter);
    }
};

基本的には、表示されるように、描画される列が特定のインデックスのものであるかどうかをチェックし、そうである場合は進行状況バーを描画します。少し調整して、QStyleOptionを使用する代わりに、独自のウィジェットを使用することもできます。

編集: setItemDelegate を使用して、QListViewで項目デリゲートを設定することを忘れないでください。

QItemDelegateを使用してカスタムウィジェットをペイントする方法を詳しく説明する this スレッドを偶然見つけた質問を調査しているときに、必要なすべての情報が含まれていると思います。

28
Idan K

私があなたの質問を正しく理解しているなら、あなたはこのようなものが欲しいです:

enter image description here

各行にはウィジェットのカスタムセットが含まれています。

これを実現するには、2つのステップがあります。

カスタムウィジェットを使用して行を実装する

まず、リストの行ごとに必要なすべてのウィジェットを含むカスタムウィジェットを実装します。

ここでは、水平レイアウトのラベルと1行あたり2つのボタンを使用しています。

class MyCustomWidget(QWidget):
    def __init__(self, name, parent=None):
        super(MyCustomWidget, self).__init__(parent)

        self.row = QHBoxLayout()

        self.row.addWidget(QLabel(name))
        self.row.addWidget(QPushButton("view"))
        self.row.addWidget(QPushButton("select"))

        self.setLayout(self.row)

リストに行を追加する

複数の行をインスタンス化するには、ウィジェットアイテムを作成し、カスタムウィジェットをアイテムの行に関連付けるだけです。

# Create the list
mylist = QListWidget()

# Add to list a new item (item is simply an entry in your list)
item = QListWidgetItem(mylist)
mylist.addItem(item)

# Instanciate a custom widget 
row = MyCustomWidget()
item.setSizeHint(row.minimumSizeHint())

# Associate the custom widget to the list entry
mylist.setItemWidget(item, row)
4
Overdrivr

@Idanの答えはうまくいきますが、私が思いついた簡単な例を投稿します。このアイテムデリゲートは、各アイテムに黒い四角形を描画するだけです。

class ItemDelegate : public QItemDelegate
{
public:
    explicit ItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {}
    void Paint(QPainter *Painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        Painter->fillRect(option.rect.adjusted(1, 1, -1, -1), Qt::SolidPattern);
    }
};

そして、それをリストウィジェットに設定するだけです:

ui->listWidget->setItemDelegate(new ItemDelegate(ui->listWidget));
3
sashoalm

アシストは言う、

void QTableWidget::setCellWidget (int row, int column, QWidget * widget)  

特定のウィジェットを特定の行と列のセルに表示するように設定し、ウィジェットの所有権をテーブルに渡します。セルウィジェットAをセルウィジェットBに置き換えると、セルウィジェットAが削除されます。

また、QAbstractItemViewのほとんどの子孫には、このメソッドに類似したものがあります。

EditTriggerを押したときにのみエディターウィジェットをViewに表示させたい場合にのみQ *** Delegateをサブクラス化し、消えてデリゲートに何らかの方法でビューアイテムをレンダリングさせます。

私が正しければ、常にアイテムビューにコントロールを表示し、編集モードに入り、デリゲートがエディターを作成してその状態を設定するまで待機せずにコントロールをヒットできるようにしたいので、特定のデリゲートを作成する必要はありません。ウィジェットをビューのアイテムに設定します。

2
Maxim Popravko

listWidgetにカスタムアイテムを追加できる別の方法。このためには、新しいクラスを追加する必要があります。好きなように名前を付けて、「myList」とだけ付けてください。プロジェクトに新しい項目を追加する方法を知っているといいですね。 :)

次に、この新しいフレームに、必要な数だけコントロールを追加します。 QLabels、QlineEditなど

次に、メインクラスで、リストウィジェット名リストを追加するか、必要に応じて次のコードを記述します。

MyList *myList = new MyList();
QListWidgetItem *item = new QListWidgetItem();
ui->list->insertItem(ui->list->size().height(),item);
item->setSizeHint(QSize(50,30));
ui->list->setItemWidget(item,myList);

後者のuは、信号/スロットを使用してアイテムのプロパティを変更することもできます。

その助けを願っています..!

1