带有自定义项和自定义项窗口小部件的QListView/QListWidget

Dan*_*aab 31 qt pyqt qlistwidget qlistview qitemdelegate

我正在编写PyQt应用程序,但在创建自定义列表视图时遇到了一些麻烦.我希望列表包含任意小部件(特别是一个自定义小部件).我该怎么做?

似乎替代方案是创建一个包含在滚动条中的表格或网格视图.但是,我希望能够利用模型/视图方法以及嵌入(树视图)支持内置函数句柄.

为了澄清,自定义小部件是交互式的(包含按钮),因此解决方案不仅仅需要绘制小部件.

Ida*_*n K 30

我认为你需要继承QItemDelegate.

QItemDelegate可用于为基于QAbstractItemView子类的项视图提供自定义显示功能和编辑器小部件.为此目的使用委托允许独立于模型和视图定制和开发显示和编辑机制.

此代码取自Qt的示例,即torrent应用程序.

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

基本上,您可以看到它检查要绘制的列是否具有特定索引,如果是,则绘制进度条.我认为你可以调整一下,而不是使用QStyleOption,你可以使用自己的小部件.

编辑:不要忘记使用setItemDelegate使用QListView设置项目委托.

在调查你的问题时,我偶然发现了这个线程,它详细说明了如何使用QItemDelegate绘制自定义窗口小部件,我相信它具有您可能需要的所有信息.

  • 好吧,我不需要为自己辩护,但我有理由想要这样做.控件不是_edit_数据,而是基于它生成动作.有许多优秀的UI这样做的例子......在浏览器中打开"下载"窗口. (4认同)

Ove*_*ivr 7

如果我正确理解了您的问题,则需要以下内容:

在此处输入图片说明

每行包含一组自定义的小部件。

为此,需要两个步骤。

使用自定义小部件实现该行

首先,实现一个自定义窗口小部件,其中包含每个列表行所需的所有窗口小部件。

在这里,我正在使用一个标签和每行两个按钮,它们具有水平布局。

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)
Run Code Online (Sandbox Code Playgroud)

在列表中添加行

实例化多行只是创建一个窗口小部件项目,并将自定义窗口小部件关联到该项目的行。

# 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)
Run Code Online (Sandbox Code Playgroud)


sas*_*alm 5

@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);
    }
};
Run Code Online (Sandbox Code Playgroud)

然后你只需要为列表小部件设置它:

ui->listWidget->setItemDelegate(new ItemDelegate(ui->listWidget));
Run Code Online (Sandbox Code Playgroud)