QT——使用QListWidget、QListWidgetItem、QWidget实现自定义管理列表

作者:小 琛
欢迎转载,请标明出处

文章目录

    • 需求场景
    • 思路描述
    • Qt模块
      • QListWidget
      • QListWidgetItem
      • 自定义QWidget配合QListWidget
    • 例子:实现一个json文件管理窗口

需求场景

因工作需要,开发一个文件管理窗口,要让使用者可以对若干文件进行一系列操作。本文着重讲述ui实现,如何作出一个漂亮的列表

思路描述

这里仅描述思路,如果你对Qt并不熟悉,大致了解一下即可,后文会描述具体用法

  1. 利用Qt提供的类:QListWidget、QListWidgetItem,其中QListWidget为列表类,QListWidgetItem可以理解为每一项的数据类
  2. 原生的QListWidget一定不能满足我们的需求,因此我们构建一个类继承自QListWidget,在子类中重新定义ui风格
  3. 在2中,我们做到了自定义列表,但列表内的具体每一项内容仍然是原生的,因此我们可以自定义一个QWidget,这个widget可以根据我们具体的场景绘制,在插入的时候,使用我们的自定义QWidget作为每一项内容
  4. QListWidgetItem是列表插入必不可少的,并且我们制作列表时,一定会用到一些数据,也可以用它来存储
    在这里插入图片描述

Qt模块

QListWidget

QListWidget是一个列表控件,可以显示一个可滚动的列表,列表项可以是纯文本、图标或者自定义控件。QListWidget使用QListWidgetItem来表示列表项,每个QListWidgetItem可以设置列表项的文本、图标和状态。

下面是一些QListWidget的常见用法:

  1. 添加列表项

可以使用addItem()方法添加一个列表项,可以设置列表项的文本和图标:

QListWidget *listWidget = new QListWidget(this);

// 添加纯文本列表项
listWidget->addItem("Item 1");

// 添加带图标的列表项
QListWidgetItem *item2 = new QListWidgetItem(QIcon(":/images/icon.png"), "Item 2");
listWidget->addItem(item2);

// 添加自定义控件
QLabel *label = new QLabel("Item 3");
QListWidgetItem *item3 = new QListWidgetItem();
listWidget->addItem(item3);
listWidget->setItemWidget(item3, label);
  1. 获取当前选中的列表项

可以使用currentItem()方法获取当前选中的列表项:

QListWidgetItem *item = listWidget->currentItem();
if (item) {
    qDebug() << "Selected item: " << item->text();
}
  1. 设置列表项的状态

可以使用setCheckState()方法设置列表项的状态,使得列表项可以被选中或未选中:

QListWidgetItem *item = new QListWidgetItem("Item 1");
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // 开启用户可选中的标志
item->setCheckState(Qt::Unchecked); // 初始为未选中状态

listWidget->addItem(item);
  1. 删除列表项

可以使用takeItem()方法删除一个列表项:

QListWidgetItem *item = listWidget->currentItem();
if (item) {
    listWidget->takeItem(listWidget->row(item)); // 删除当前选中的列表项
}

QListWidgetItem

QListWidgetItem是QListWidget中的列表项,每个QListWidget中的列表项都是一个QListWidgetItem对象。QListWidgetItem包含了列表项的文本、图标、状态等信息,可以通过QListWidgetItem的方法来设置和获取这些信息。

下面是一些常见的QListWidgetItem的用法:

  1. 设置列表项的文本和图标

可以使用setText()方法和setIcon()方法设置列表项的文本和图标:

QListWidgetItem *item = new QListWidgetItem();
item->setText("Item 1");
item->setIcon(QIcon(":/images/icon.png"));
listWidget->addItem(item);
  1. 获取列表项的文本和图标

可以使用text()方法和icon()方法获取列表项的文本和图标:

QListWidgetItem *item = listWidget->currentItem();
if (item) {
    QString text = item->text();
    QIcon icon = item->icon();
}
  1. 设置列表项的状态

可以使用setCheckState()方法设置列表项的状态,使得列表项可以被选中或未选中:

QListWidgetItem *item = new QListWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // 开启用户可选中的标志
item->setCheckState(Qt::Unchecked); // 初始为未选中状态
listWidget->addItem(item);
  1. 获取列表项的状态

可以使用checkState()方法获取列表项的状态,返回值为Qt::CheckState枚举类型,表示列表项的选中状态:

QListWidgetItem *item = listWidget->currentItem();
if (item) {
    Qt::CheckState state = item->checkState();
}
  1. 自定义列表项

可以使用QListWidgetItem的方法setItemWidget()方法设置自定义控件作为列表项:

QLabel *label = new QLabel("Custom Item");
QListWidgetItem *item = new QListWidgetItem();
listWidget->addItem(item);
listWidget->setItemWidget(item, label);

自定义QWidget配合QListWidget

在使用QListWidget时,有时需要自定义列表项的内容,此时可以使用QWidget作为列表项的内容。QWidget可以是任何自定义控件,例如QPushButton、QLabel等。也就是说,你可以自定义一个任意构建的widget,将其作为列表的每一项内容。

例子:实现一个json文件管理窗口

文件构造:
JsonListWidget.h+JsonListWidget.cpp
JsonListWidgetItem.h+JsonListWidgetItem.cpp
JsonItemWidget.h+JsonItemWidget.cpp

注意的点:

  1. 下面的例子,并不能直接运行,因为包含了很多我自定义的控件,仅限于了解整个结构
  2. 整个设计:JsonItemWidget是我的自定义widget,里面包含了我定义每一项的具体内容,其中的控件被触发时绑定信号,JsonItemWidget再绑定widget中的信号,实现事件的抛;JsonListWidget是列表项,修改了很多属性来实现我想要的ui效果;JsonListWidgetItem是自定义的Item,其中预留了operate >,该接口可以完成自定义排序功能;插入的时候,调用setItemWidget接口完成

JsonListWidget.h

#pragma once

#include <QListWidget>
#include "JsonItemDataDef.h"

class JsonListItem;
class QListWidgetItem;
class JsonListWidget : public QListWidget {
    Q_OBJECT
public:
    explicit JsonListWidget(QWidget* parent);
    ~JsonListWidget();
    
    void addJson(const JsonItemData& JsonData);
    void addJsonWithFlicker(const JsonItemData& JsonData);
    void updateJsonName(const QString& oldName, const QString& newName);
    void updateJsonInfo(const QString& name, const JsonItemData& data);
    void deleteJsonWithName(const QString& name);
    bool haveJsonByName(const QString& name);
    
private:
    QListWidgetItem* findWidgetItemByName(const QString& name);

signals:
    void sigOpenJsonFileFolder();
    void sigJsonRun(const QString& name);
    void sigItemNameChanged(const QString& oldName, const QString& newName);
    void sigItemDelete(const QString& name);
    void sigItemSetting(const QString& name);

protected:
    virtual bool eventFilter(QObject* object, QEvent* event) override;

};

JsonListWidget.cpp

#include "JsonListWidget.h"
#include "JsonListItem.h"
#include "NemuColor.h"
#include "AppUtil.h"
#include <QPainter>
#include <QDateTime>
#include <QEvent>
#include <QTimer>

enum ItemRole {
    kRoleIndex = Qt::UserRole + 1,
    kRoleName,
    kRoleDate,
    kRoleTime,
    kRoleScreen,
};

JsonListWidget::JsonListWidget(QWidget *parent) : QListWidget(parent) {
    setFrameShape(QFrame::NoFrame);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    viewport()->setContentsMargins(0, 0, 0, 0);

    setStyleSheet(
        QString("QListWidget{background-color:%1;border: 1px solid %2; border-bottom-left-radius: %3px; "
                "border-bottom-right-radius: %4px; outline:0px;}"
                "QListWidget::item:hover{background-color:%5;}"
                "QListWidget::item:selected{border:none;}"
                "QScrollBar:vertical{width:4px; background:transparent; padding:0px; border:0px;}"
                "QScrollBar::handle:vertical:hover,QScrollBar::handle:vertical:pressed{background:%7;}"
                "QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:transparent;border:0px;}"
                "QScrollBar::add-line:vertical,QScrollBar::sub-line:vertical{background:transparent;border:0px;}")
            .arg(NemuUiLib::NemuColor::getGrey8().name(QColor::HexArgb))
            .arg(AppUtil::isWin11() ? "#44464b" : "#192027")
            .arg(AppUtil::isWin11() ? 8 : 0)
            .arg(AppUtil::isWin11() ? 8 : 0)
            .arg(NemuUiLib::NemuColor::getFill1().name(QColor::HexArgb))
            .arg(NemuUiLib::NemuColor::getFill2().name(QColor::HexArgb))
            .arg(NemuUiLib::NemuColor::getGrey3().name(QColor::HexArgb)));

    if (auto widget = findChild<QWidget *>("qt_scrollarea_vcontainer")) {
        widget->installEventFilter(this);
    }
    setViewMode(ListMode);
}

JsonListWidget::~JsonListWidget() {}

void JsonListWidget::addJson(const JsonItemData &JsonData) {
    if (haveJsonByName(JsonData.name_)) {
        return;
    }
    JsonListItem *item = new JsonListItem(this);
    connect(item, &JsonListItem::sigItemOpenJsonFileFolder, this, &JsonListWidget::sigOpenJsonFileFolder);
    connect(item, &JsonListItem::sigItemJsonRun, this, &JsonListWidget::sigJsonRun);
    connect(item, &JsonListItem::sigNameChanged, this, &JsonListWidget::sigItemNameChanged);
    connect(item, &JsonListItem::sigDeleteButtonClicked, this, &JsonListWidget::sigItemDelete);
    connect(item, &JsonListItem::sigSettingButtonClicked, this, &JsonListWidget::sigItemSetting);

    item->setJsonName(JsonData.name_);
    item->setJsonTime(JsonData.time_);
    item->setJsonDate(JsonData.date_);
    item->setJsonScreen(JsonData.screen_);

    auto listItem = new QListWidgetItem(this);
    listItem->setData(kRoleIndex, JsonData.index_);
    listItem->setData(kRoleName, JsonData.name_);
    listItem->setData(kRoleScreen, JsonData.screen_);
    listItem->setData(kRoleTime, JsonData.time_);
    listItem->setData(kRoleDate, JsonData.date_);
    listItem->setSizeHint(item->size());
    insertItem(0, listItem);
    setItemWidget(listItem, item);
}

void JsonListWidget::addJsonWithFlicker(const JsonItemData &JsonData) {
    if (haveJsonByName(JsonData.name_)) {
        return;
    }
    JsonListItem *item = new JsonListItem(this);
    connect(item, &JsonListItem::sigItemOpenJsonFileFolder, this, &JsonListWidget::sigOpenJsonFileFolder);
    connect(item, &JsonListItem::sigItemJsonRun, this, &JsonListWidget::sigJsonRun);
    connect(item, &JsonListItem::sigNameChanged, this, &JsonListWidget::sigItemNameChanged);
    connect(item, &JsonListItem::sigDeleteButtonClicked, this, &JsonListWidget::sigItemDelete);
    connect(item, &JsonListItem::sigSettingButtonClicked, this, &JsonListWidget::sigItemSetting);

    item->setJsonName(JsonData.name_);
    item->setJsonTime(JsonData.time_);
    item->setJsonDate(JsonData.date_);
    item->setJsonScreen(JsonData.screen_);

    auto listItem = new QListWidgetItem();
    listItem->setData(kRoleIndex, JsonData.index_);
    listItem->setData(kRoleName, JsonData.name_);
    listItem->setData(kRoleScreen, JsonData.screen_);
    listItem->setData(kRoleTime, JsonData.time_);
    listItem->setData(kRoleDate, JsonData.date_);
    listItem->setSizeHint(item->size());
    insertItem(0, listItem);
    setItemWidget(listItem, item);
    update();
    listItem->setBackgroundColor(NemuUiLib::NemuColor::getFill1());
    QTimer::singleShot(1000, [listItem]() { listItem->setBackgroundColor(NemuUiLib::NemuColor::getGrey8()); });
}

bool JsonListWidget::haveJsonByName(const QString& name) {
    bool ret = false;
    for (int row = 0; row < count(); ++row) {
        auto widgetItem = item(row);
        if (!widgetItem) {
            continue;
        }

        if (name != widgetItem->data(kRoleName).toString()) {
            continue;
        }

        ret = true;
        break;
    }
    return ret;
}


void JsonListWidget::deleteJsonWithName(const QString& name) {
    int listCount = count();
    for (int row = 0; row < listCount; ++row) {
        auto widgetItem = item(row);
        if (!widgetItem) {
            continue;
        }

        if (name != widgetItem->data(kRoleName).toString()) {
            continue;
        }

        takeItem(row);
        break;
    }
}

void JsonListWidget::updateJsonName(const QString &oldName, const QString &newName) {
    if (auto widgeItem = findWidgetItemByName(oldName)) {
        widgeItem->setData(kRoleName, newName);

        if (auto widget = qobject_cast<JsonListItem *>(itemWidget(widgeItem))) {
            widget->setJsonName(newName);
        }
    }
}

void JsonListWidget::updateJsonInfo(const QString &name, const JsonItemData &data) {
    if (auto widgeItem = findWidgetItemByName(name)) {
        widgeItem->setData(kRoleIndex, data.index_);
        widgeItem->setData(kRoleName, name);
        widgeItem->setData(kRoleDate, data.date_);
        widgeItem->setData(kRoleTime, data.time_);
        widgeItem->setData(kRoleTime, data.screen_);

        if (auto widget = qobject_cast<JsonListItem *>(itemWidget(widgeItem))) {
            widget->setIndex(data.index_);
            widget->setJsonName(name);
            widget->setJsonDate(data.date_);
            widget->setJsonTime(data.time_);
            widget->setJsonScreen(data.screen_);
        }
    }
}

QListWidgetItem *JsonListWidget::findWidgetItemByName(const QString &name) {
    int listCount = count();
    for (int row = 0; row < listCount; ++row) {
        auto widgetItem = item(row);
        if (!widgetItem) {
            continue;
        }

        if (name != widgetItem->data(kRoleName).toString()) {
            continue;
        }

        return widgetItem;
    }
    return nullptr;
}

bool JsonListWidget::eventFilter(QObject *object, QEvent *event) {
    // scrollbar设置位置的时机比较多,无法全面覆盖,只能在产生move事件之后再进行调整
    auto widget = findChild<QWidget *>("qt_scrollarea_vcontainer");
    if (widget && widget == object && event->type() == QEvent::Move) {
        QPoint pos = widget->pos();
        if (pos.x() && (pos.x() == rect().width() - widget->width())) {
            QRect rc1 = widget->geometry();
            pos -= QPoint(4, 0);
            widget->move(pos);
        }
    }

    return QListWidget::eventFilter(object, event);
}

JsonItemWidget.h

#pragma once

#include <QWidget>
#include "JsonItemDataDef.h"

class QStackedWidget;
class QStackedLayout;
class QLabel;
class QLineEdit;
class QVBoxLayout;
class QPushButton;
class RecorderPushButton18;
class RecorderTextLabel;
class JsonListItem : public QWidget {
    Q_OBJECT
public:
    explicit JsonListItem(QWidget* parent);
    ~JsonListItem();

    void setIndex(const QString& index);

    void setScriptName(const QString& name);

    void setScriptDate(const QString& date);
    void setScriptTime(const QString& time);

    void setScriptScreen(const QString& screen);

    void setModifyTime(quint64 time);

signals:
    void sigCheckStateChanged(const QString& index, Qt::CheckState state);
    void sigItemOpenScriptFileFolder();
    void sigItemScriptRun(const QString& name);
    void sigNameChanged(const QString& oldName, const QString& newName);
    void sigDeleteButtonClicked(const QString& name);
    void sigSettingButtonClicked(const QString& name);

protected:
    virtual void enterEvent(QEvent* event) override;
    virtual void leaveEvent(QEvent* event) override;
    virtual void focusOutEvent(QFocusEvent* event) override;
    bool eventFilter(QObject* object, QEvent* event) override;

private:
    QWidget* initLeftInfoWidget();
    QWidget* initRightButtonWidget();
    void ensureRenameEdit();
    void elidedName(NemuUiLib::NemuRichText1* label, const QString& name);
    void showNameLabel();
    void showRenameEdit();

private:
    QString index_;
    QString name_;
    QString time_;
    QString screen_;
    QLable* nameLabel_;
    QLable* dateLabel_;
    QLabel* timeLabel_;
    QLbale* screenLabel_;
    QLineEdit* renameEdit_;
    QPushButton* openFolderButton_;
    QPushButton* settingButton_;
    QPushButton* deleteButton_;
    QVBoxLayout* centerLayout_;
    bool mouseEntered_;

    QPushButton* operatorButton_;

};

JsonItemWidget.cpp

#include "JsonListItem.h"
#include "../../common/RecorderPushButton.h"
#include "../../common/RecorderTextLabel.h"
#include "nemu-ui-lib/control/NemuImage.h"
#include "nemu-ui-lib/control/NemuRichText.h"
#include "nemu-ui-lib/control/NemuCheckBox.h"
#include "nemu-ui-lib/control/NemuLine.h"
#include "nemu-ui-lib/control/NemuLineEdit.h"
#include "nemu-ui-lib/font/NemuFont.h"
#include "nemu-ui-lib/color/NemuColor.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QStackedWidget>
#include <QStackedLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QValidator>
#include <QRegularExpression>

JsonListItem::JsonListItem(QWidget* parent)
    : QWidget(parent),
      nameLabel_(nullptr),
      renameEdit_(nullptr),
      openFolderButton_(nullptr),
      settingButton_(nullptr),
      deleteButton_(nullptr),
      operatorButton_(nullptr),
      mouseEntered_(false) {
    setFixedSize(800, 80);
    centerLayout_ = new QVBoxLayout(this);
    centerLayout_->setAlignment(Qt::AlignCenter);
    centerLayout_->setSpacing(0);
    centerLayout_->setContentsMargins(0, 0, 0, 0);

    auto mainLayout = new QHBoxLayout();
    mainLayout->setContentsMargins(40, 18, 40, 16);
    mainLayout->setAlignment(Qt::AlignCenter);
    mainLayout->setSpacing(0);

    installEventFilter(this);
    mainLayout->addWidget(initLeftInfoWidget());
    mainLayout->addWidget(initRightButtonWidget(), 0, Qt::AlignVCenter);

    const auto line = new Line2({720, 1}, {40, 0, 40, 0}, this); 

    //centerLayout_->addStretch();
    centerLayout_->addLayout(mainLayout);
    //centerLayout_->addStretch();

    centerLayout_->addWidget(line, 0, Qt::AlignBottom);
    adjustSize();
}

JsonListItem::~JsonListItem() {
    if (renameEdit_) {
        renameEdit_->removeEventFilter(this);
    }
    removeEventFilter(this);
}

QWidget* JsonListItem::initLeftInfoWidget() {
    auto widget = new QWidget(this);

    auto centerLayout = new QVBoxLayout(widget);
    centerLayout->setAlignment(Qt::AlignTop);
    centerLayout->setSpacing(0);
    centerLayout->setContentsMargins(0, 0, 0, 0);

    nameLabel_ = new NemuUiLib::NemuRichText1(300, getFont14(), QString(), widget);
    //nameLabel_->installEventFilter(this);
    nameLabel_->setFixedHeight(24);
    nameLabel_->document()->setDocumentMargin(0);
    nameLabel_->setStyleSheet(
        QString("QTextBrowser{color: %1; border: none; background-color: transparent}").arg(getWhite1().name(QColor::HexArgb)));
    centerLayout->addWidget(nameLabel_, 0, Qt::AlignTop | Qt::AlignLeft);
    QSpacerItem* spacer = new QSpacerItem(0, 4, QSizePolicy::Expanding, QSizePolicy::Fixed);
    centerLayout->addItem(spacer);

    auto dateAndScrenLayout = new QHBoxLayout();
    dateAndScrenLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    dateAndScrenLayout->setSpacing(0);
    dateAndScrenLayout->setContentsMargins(0, 0, 0, 0);

    auto dataImage = new Image1(QSize(16, 16), ":/resources/images/ic_calendar.svg", widget);
    dateAndScrenLayout->addWidget(dataImage);
    dateAndScrenLayout->addSpacing(2);

    dateLabel_ = new RichText2(QString(), getFont12(), widget);

    dateAndScrenLayout->addWidget(dateLabel_);

    dateAndScrenLayout->addSpacing(4);

    timeLabel_ = new Text2(QString(), getFont12(), widget);

    dateAndScrenLayout->addWidget(timeLabel_);

    dateAndScrenLayout->addSpacing(16);

    auto screenImage = new NemuImage1(QSize(16, 16), ":/resources/images/ic_resolution.svg", widget);
    dateAndScrenLayout->addWidget(screenImage);

    dateAndScrenLayout->addSpacing(2);

    screenLabel_ = new RichText2(QString(), getFont12(), widget);
    screenLabel_->setFixedWidth(55);
    dateAndScrenLayout->addWidget(screenLabel_);

    centerLayout->addLayout(dateAndScrenLayout);
    return widget;
}

QWidget* JsonListItem::initRightButtonWidget() {
    auto operatorWidget = new QWidget(this);

    auto operatorLayout = new QHBoxLayout(operatorWidget);
    operatorLayout->setContentsMargins(6, 0, 0, 0);
    operatorLayout->setSpacing(20);

    openFolderButton_ = new QPushButton(this);
    openFolderButton_->setFixedSize(16, 16);
    openFolderButton_->setToolTip(tr("File location"));
    openFolderButton_->setStyleSheet(
        QString("QPushButton{border-image: url(:/resources/images/ic_folder location_normal.svg);}\
                     QPushButton:hover{border-image: url(:/resources/images/ic_folder location_hover.svg);}\
                     QPushButton:pressed{border-image: url(:/resources/images/ic_folder location_press.svg);}\
                     QPushButton:disabled{border-image: url(:/resources/images/ic_folder location_disable.svg);}"
                "QToolTip {"
                "color: %1;"
                "background-color: %2;"
                "qproperty-shadow: none;"
                "border: 0px solid #2A82DA;"
                "}")
            .arg(getWhite1().name(QColor::HexArgb))
            .arg(getGrey10().name(QColor::HexArgb)));
    connect(openFolderButton_, &QPushButton::clicked, this, [this]() { 
        emit sigItemOpenJsonFileFolder(); 
        });
    operatorLayout->addWidget(openFolderButton_);

    settingButton_ = new QPushButton(this);
    settingButton_->setFixedSize(16, 16);
    settingButton_->setToolTip(tr("execution setting"));
    settingButton_->setStyleSheet(QString("QPushButton{border-image: url(:/resources/images/ic_setting_normal.svg);}\
                     QPushButton:hover{border-image: url(:/resources/images/ic_setting_hover.svg);}\
                     QPushButton:pressed{border-image: url(:/resources/images/ic_setting_pressed.svg);}\
                     QPushButton:disabled{border-image: url(:/resources/images/ic_setting_disabled.svg);}"
                                          "QToolTip {"
                                          "qproperty-shadow: none;"
                                          "color: %1;"
                                          "background-color: %2;"
                                          "border: 0px solid #2A82DA;"
                                          "}")
                                      .arg(getWhite1().name(QColor::HexArgb))
                                      .arg(getGrey10().name(QColor::HexArgb)));
    connect(settingButton_, &QPushButton::clicked, this, [this]() { emit sigSettingButtonClicked(name_); });
    operatorLayout->addWidget(settingButton_);

    deleteButton_ = new QPushButton(this);
    deleteButton_->setFixedSize(16, 16);
    deleteButton_->setToolTip(tr("delete"));
    deleteButton_->setStyleSheet(QString("QPushButton{border-image: url(:/resources/images/ic_delete_normal.svg);}\
                     QPushButton:hover{border-image: url(:/resources/images/ic_delete_hover.svg);}\
                     QPushButton:pressed{border-image: url(:/resources/images/ic_delete_pressed.svg);}\
                     QPushButton:disabled{border-image: url(:/resources/images/ic_delete_disabled.svg);}"
                                         "QToolTip {"
                                         "color: %1;"
                                         "background-color: %2;"
                                         "qproperty-shadow: none;"
                                         "border: 0px solid #2A82DA;"
                                         "}")
                                     .arg(getWhite1().name(QColor::HexArgb))
                                     .arg(getGrey10().name(QColor::HexArgb)));
    connect(deleteButton_, &QPushButton::clicked, this, [this]() { emit sigDeleteButtonClicked(name_); });
    operatorLayout->addWidget(deleteButton_);

    operatorButton_ = new RecorderPushButton18(this);
    operatorButton_->setFixedSize(48, 24);
    operatorButton_->setIcon(QIcon(":/resources/images//ic_start_up.svg"));
    operatorButton_->setStateColor(NemuUiLib::NemuColor::getBrand1(), getBrand2(),
                                   NemuUiLib::NemuColor::getBrand1());
    operatorButton_->setToolTip(tr("execute"));
    operatorButton_->setStyleSheet(QString("QToolTip {"
                                           "color: %1;"
                                           "background-color: %2;"
                                           "border: 0px solid #2A82DA;"
                                           "}")
                                       .arg(getWhite1().name(QColor::HexArgb))
                                       .arg(getGrey10().name(QColor::HexArgb)));
    operatorButton_->setVisible(true);
    connect(operatorButton_, &QPushButton::clicked, this, [this]() { sigItemJsonRun(name_);
    });
    operatorLayout->addWidget(operatorButton_);


    return operatorWidget;
}

void JsonListItem::setIndex(const QString& index) { index_ = index; }

void JsonListItem::setJsonName(const QString& name) {
    name_ = name;
    if (renameEdit_ && renameEdit_->isVisible()) {
        return;
    }

    elidedName(nameLabel_, name);
}

void JsonListItem::setJsonDate(const QString& date) { 
    time_ = date; 
    const auto dateHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
                                  .arg(getGrey2().name(QColor::HexArgb))
                                  .arg(date);
    dateLabel_->updateText(dateHtmlText);
    dateLabel_->setFixedWidth(dateLabel_->adaptiveWidth(date, getFont12()));
}

void JsonListItem::setJsonTime(const QString& time) {
    time_ = time;
    const auto dateHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
                                  .arg(NemuUiLib::NemuColor::getGrey2().name(QColor::HexArgb))
                                  .arg(time);
    timeLabel_->updateText(dateHtmlText);
    timeLabel_->setFixedWidth(timeLabel_->adaptiveWidth(time, getFont12()));
}

void JsonListItem::setJsonScreen(const QString& screen) {
    screen_ = screen; 
    const auto screenHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
                                    .arg(getGrey2().name(QColor::HexArgb))
                                    .arg(screen_);
    screenLabel_->updateText(screenHtmlText);
    screenLabel_->setFixedWidth(timeLabel_->adaptiveWidth(screen, getFont12()));
}

void JsonListItem::setModifyTime(quint64 time) {}

void JsonListItem::enterEvent(QEvent* event) {

    QWidget::enterEvent(event);
}

void JsonListItem::leaveEvent(QEvent* event) {
    if (renameEdit_ && renameEdit_->isVisible()) {
        if (!renameEdit_->hasFocus()) {
            renameEdit_->setVisible(false);
            elidedName(nameLabel_, name_);
        }
    }
    QWidget::leaveEvent(event);
}

void JsonListItem::focusOutEvent(QFocusEvent* event) {
    if (renameEdit_) {
        renameEdit_->setVisible(false);
    }
    QWidget::focusOutEvent(event);
}

void JsonListItem::showNameLabel() {
    renameEdit_->setVisible(false);
    elidedName(nameLabel_, name_);
}

void JsonListItem::showRenameEdit() {
    nameLabel_->clear();
    auto pos = nameLabel_->geometry();
    ensureRenameEdit();
    QSize sz = renameEdit_->size();
    renameEdit_->setGeometry(pos.x() + 40, pos.y() + 18, sz.width(), sz.height());
    renameEdit_->setText(name_);
    renameEdit_->setVisible(true);
}

bool JsonListItem::eventFilter(QObject* object, QEvent* event) {
    if (object == renameEdit_) {
       if (event->type() == QEvent::FocusOut && !mouseEntered_) {
            showNameLabel();
        }
    } else if (object == this) {
        if (event->type() == QEvent::Enter) {
            mouseEntered_ = true;
            if (renameEdit_ && renameEdit_->isVisible()) {
                if (!renameEdit_->hasFocus()) {
                    showNameLabel();
                }
            } else {
                showRenameEdit();
            }
        } else if (event->type() == QEvent::Leave) {
            mouseEntered_ = false;
            if (renameEdit_ && !renameEdit_->hasFocus()) {
                showNameLabel();
            }
        }
    } else if (object != renameEdit_) {
        if (renameEdit_ && !renameEdit_->hasFocus()) {
            showNameLabel();
        }
    }

    return QWidget::eventFilter(object, event);
}

void JsonListItem::ensureRenameEdit() {
    if (renameEdit_) {
        return;
    }

    renameEdit_ = new QLineEdit(this);
    renameEdit_->setContextMenuPolicy(Qt::NoContextMenu);
    renameEdit_->setMaxLength(40);
    renameEdit_->setValidator(
        new QRegularExpressionValidator(QRegularExpression("^((?!\\\\|\\/|:|\\*|\\?|\"|<|>|\\|).)*$"), this));
    renameEdit_->setFixedSize(300, 24);
    renameEdit_->setFont(NemuUiLib::NemuFont::getFont12());
    renameEdit_->installEventFilter(this);
    renameEdit_->setStyleSheet(
        QString("QLineEdit{border-width:1px; border-style:solid; border-color:%1; padding-left:8px; padding-right:8px;"
                "background-color: %1; color: %2; border-radius:2px;}"
                "QLineEdit:hover{border-width:1px; border-style:solid; border-color:%3; background-color:%3;}"
                "QLineEdit:focus{border-width:1px; border-style:solid; border-color:%4; background-color:%5; }")
            .arg(getFill1().name(QColor::HexArgb))
            .arg(getWhite1().name(QColor::HexArgb))
            .arg(getFill2().name(QColor::HexArgb))
            .arg(getBrand1().name(QColor::HexArgb))
            .arg(getFill5().name(QColor::HexArgb)));
    connect(renameEdit_, &QLineEdit::editingFinished, this, [this]() {
        QString newName = renameEdit_->text();
        if (!newName.isEmpty() && newName != name_) {
            emit sigNameChanged(name_, newName);
        }
    });
    connect(renameEdit_, &QLineEdit::returnPressed, this, [this]() {
        QString newName = renameEdit_->text();
        if (!newName.isEmpty() && newName != name_) {
            emit sigNameChanged(name_, newName);
        }
        renameEdit_->setVisible(false);
        elidedName(nameLabel_, name_);
    });
}

void JsonListItem::elidedName(QLabel* label, const QString& name) {
    QFontMetrics fontWidth(label->font());
    int contentWidth = label->width() - label->document()->documentMargin() * 2;
    label->setText(fontWidth.elidedText(name, Qt::ElideRight, contentWidth));
    label->setFixedHeight(24);
}

JsonListWidgetItem.h

#pragma once

#include <QListWidgetItem>

enum ItemRole {
    kRoleId = Qt::UserRole + 1,
    kRoleIndex,
    kRoleNumber,
    kRoleMainFlag,
    kRoleStatus,
    kRoleErrorCode,
    kRoleTime,
    kRoleName,
};

class JsonWidgetItem : public QListWidgetItem {
public:
    virtual bool operator<(const QListWidgetItem &other) const override;

private:
    bool checked_;
};

JsonListWidgetItem.cpp

#include "JsonWidgetItem.h"
#include "JsonWidget.h"
#include <QListWidget>
#include <shlwapi.h>
#include "PlayerItemDataDef.h"

JsonWidgetItem::JsonWidgetItem(QListWidget *listview) : QListWidgetItem(listview), checked_(false) {}

JsonWidgetItem::~JsonWidgetItem() {}

bool JsonWidgetItem::operator<(const QListWidgetItem &other) const {
    if (auto listView = qobject_cast<JsonWidget *>(listWidget())) {
        if (listView->sortFactor() == kFactorNumber) {
            return data(kRoleNumber).toInt() < other.data(kRoleNumber).toInt();
        } else if (listView->sortFactor() == kFactorName) {
            return StrCmpLogicalW((PCWSTR)data(kRoleName).toString().utf16(),
                                  (PCWSTR)other.data(kRoleName).toString().utf16()) == -1;
        } else if (listView->sortFactor() == kFactorTime) {
            if (data(kRoleMainFlag).toBool()) {
                return true;
            } else if (other.data(kRoleMainFlag).toBool()) {
                return false;
            } else {
                return data(kRoleTime).toULongLong() < other.data(kRoleTime).toULongLong();
            }
        }
    }

    return data(kRoleNumber).toString().compare(other.data(kRoleNumber).toString()) < 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/34058.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【python爬虫应用03】csdn个人所有文章质量分查询

&#x1f6e0;️ 环境准备 在开始编写代码之前&#xff0c;我们需要进行一些环境准备。以下是所需的环境和库&#xff1a; 操作系统&#xff1a;Windows编程语言&#xff1a;Python 3编辑器&#xff1a;VSCode&#xff08;可选&#xff09; 安装所需的库&#xff1a; reque…

Git快速入门

Git 1、Git概述Git简介Git下载与安装 2、Git代码托管服务常用的Git代码托管服务使用码云托管服务 3、Git常用命令Git全局设置获取Git仓库工作区、暂存区、版本库概念本地仓库常用命令远程仓库操作命令分支操作标签操作 4、在IDEA中使用Git在IDEA中配置Git获取Git仓库本地仓库操…

OpenAI Gym入门与实操(2)

本文内容参考&#xff1a; Getting Started With OpenAI Gym | Paperspace Blog&#xff0c; 【强化学习】 OpenAI Gym入门&#xff1a;基础组件&#xff08;Getting Started With OpenAI Gym: The Basic Building Blocks&#xff09;_iioSnail的博客-CSDN博客 3. 环境&#…

Blender导出gltf格式ThreeJS不显示问题-

1. 检查代码 import { GLTFLoader } from three/addons/loaders/GLTFLoader.js; 。。。。。。initRoomGltf() {const _this this;// const loader new OBJLoader();const loader new GLTFLoader();// load a resourceloader.load(// resource URL// this.commonFunc.getPat…

vcruntime140_1.dll无法继续执行代码,有哪些方法可以解决?

关于vcruntime140_1.dll无法继续执行代码的错误问题&#xff0c;其实还是非常的普遍的&#xff0c;这属于经常丢失的dll文件之一&#xff0c;当然还有一个vcruntime140.dll也是非常容易丢失的&#xff0c;本文下面会介绍到这两种有啥区别&#xff0c;以及怎么去修复这些文件丢失…

spring复习:(4)AbstractEnvironment

该类中指定了激活profile属性的名称(spring.profiles.active)&#xff0c;默认profile属性的名称(spring.profiles.default)&#xff0c;以及默认的profile的名字(default)。

【Leetcode】19.删除链表的倒数第 N 个结点

一、题目 1、题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例1: 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]示例2: 输入:head = [1], n = 1 输出:[]示例3: 输入:head = [1,2], n = 1 输出:[1]提示: 链表中结点的数目为 sz…

【剑指offer专项突破版】二叉树篇——“C“

文章目录 前言一、二叉树剪枝题目分析思路分析代码 二、序列化与反序列化二叉树题目分析思路分析代码 三、从根节点到叶节点的路径数字之和题目分析思路分析代码 四、 向下的路径节点之和题目分析思路分析思路①代码思路②代码 五、节点之和最大的路径题目分析思路分析代码 六、…

XSS注入——DOM型XSS

DOM型xss XSS根据恶意脚本的传递方式可以分为3种&#xff0c;分别为反射型、存储型、DOM型&#xff0c;前面两种恶意脚本都会经过服务器端然后返回给客户端&#xff0c;相对DOM型来说比较好检测与防御&#xff0c;而DOM型不用将恶意脚本传输到服务器在返回客户端&#xff0c;这…

Elasticsearch 地理空间计算

地理位1置搜索&#xff1a;使用查询API进行搜索 1、Geo Distance Query Geo Distance Query是在给定的距离范围内搜索数据的查询。例如&#xff0c;可以搜索给定地理位置附近指定距离内的所有文档。 GET /my_index/_search {"query": {"bool" : {"fi…

9、Redis集群(cluster)

是什么 Redis集群是一个提供在多个Redis节点间共享数据的程序集&#xff0c;Redis集群可以支持多个master 能干嘛 Redis集群支持多个master&#xff0c;每个master又可以挂载多个slave 读写分离 支持数据的高可用 支持海量数据的读写存储操作 由于Cluster自带Sentinel的故障转…

软考高级系统架构设计师(九) 作文模板-论设计模式及其应用(未完待续)

目录 掌握的知识点 创建型 结构型 行为型 掌握的知识点 设计模式分为哪3类 每一类包含哪些具体的设计模式 创建型 创建型模式是对对象实例化过程的抽象&#xff0c;他通过抽象类所定义的接口&#xff0c;封装了系统中对象如何创建、组合等信息。 创建型模式主要用于创建对…

Buildroot 取消默认QT桌面-迅为RK3588开发板

本小节将讲解如何取消掉默认的 qt 桌面。 首先对开发板进行上电&#xff0c;开发板正常启动后&#xff0c;使用命令“cd /etc/init.d”进入到/etc/init.d 目录 下&#xff0c;然后使用以下命令对开机自启动脚本 rcS 进行查看&#xff0c;如下图所示&#xff1a; vi rcS 从上…

视觉SLAM十四讲需要提前知道的数学基础知识

学习视觉SLAM十四讲之前的必备数学基础知识 1. 正交矩阵2. 线性关系3. 求矩阵的逆4. 叉乘5.反对称矩阵6. 复数 1. 正交矩阵 定义&#xff1a; 设n阶矩阵A满足AATATAI &#xff0c;则称A为正交矩阵 性质&#xff1a; 以下为手写&#xff0c;从小字丑&#xff0c;请多担待。。 …

红色通信史(一):红色通信的萌芽

1927年4月和7月&#xff0c;蒋介石、汪精卫分别在上海、武汉发动“四一二”、“七一五”反革命政变&#xff0c;实行“清党”、“分共”&#xff0c;大肆逮捕和杀害中共党员&#xff0c;制造“白色恐怖”。 面对敌人的残酷镇压&#xff0c;我党决定创建自己的革命军队&#xff…

元宇宙装备展正式拉开帷幕,深眸科技CEO周礼出席产业论坛发表主题演讲

6月27日&#xff0c;一场令人期待已久的工业元宇宙盛会在昆山国际会展中心拉开帷幕&#xff0c;大会由昆山市人民政府主办&#xff0c;昆山市工业和信息化局、赛迪工业和信息化研究院集团&#xff08;苏州&#xff09;有限公司联合承办&#xff0c;并得到了十数家单位的支持&am…

计算机网络那些事之 MTU 篇 pt.2

哈喽大家好&#xff0c;我是咸鱼 在《计算机网络那些事之 MTU 篇 》中&#xff0c;咸鱼跟大家介绍了 MTU 是指数据链路层能够传输的最大数据帧的大小 如果发送的数据大于 MTU&#xff0c;则就会进行分片操作&#xff08;Fragment&#xff09;&#xff1b;如果小于 MTU&#x…

Git安装及使用图文教程详解(附带安装文件)

Git安装及使用图文教程详解&#xff08;附带安装文件&#xff09; 原创&#xff1a;丶无殇  2023-06-26 文章目录 下载安装下载安装验证安装成功版本查看 基础指令Git常用指令【首次必须】设置签名用户、邮箱1.初始化本地仓库2.查看本地库状态3.创建文件4.添加文件至暂存区5…

maven打包本地jar到项目中

在maven项目中&#xff0c;我们的项目依赖一般取自local的repository或者远程的repository&#xff0c;比如下面这个配置&#xff1a; maven <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> &l…

C++11新特性(5):多线程

学习C11&#xff0c;根据网上资料的知识总结。 1. 线程创建 1.1 初始函数 #include <iostream> #include <thread> void myfunc(int &a) {cout << "a in myfunc:" << a << endl; }int main() {int a 1;std::thread mythread(…
最新文章