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

news2024/12/26 14:07:34

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

文章目录

    • 需求场景
    • 思路描述
    • 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.coloradmin.cn/o/713470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝牙通过串口获取电量!!!

问题&#xff1a;样机短时间出现电池没电情况&#xff08;异常放电&#xff09;&#xff0c;经过检查&#xff0c;蓝牙在休眠是会有2.1V左右的电压&#xff0c;导致电池电量消耗过快。机器由于有语音功能&#xff0c;播放语音时需要很大电流&#xff0c;给机器装的是两节南孚电…

UE4/5数字人Metahuman与iClone的使用【数字人与动画】

iClone软件下载 iClone 8 是一款由Reallusion开发的3D动画软件&#xff0c;接下来就不多说了&#xff0c;首先进入官网&#xff0c;我们可以看到两个下载的东西&#xff0c;左边是下面这个软件&#xff0c;直接下载即可&#xff0c;右边的我们在后面下载&#xff1a; iClone插…

将DES解密用Python实现

将此段代码用python实现 var CryptoJS require("crypto-js"); var ciphertext "1MpdxK203ZrnyxuJRrYatKSBxHUIi1TSdQF2BQKXOG54plwfaB2GA"; var key CryptoJS.enc.Utf8.parse("11"); var parsedCiphertext CryptoJS.enc.Base64.parse(ciphe…

6月VR大数据:Quest 2下跌2个百分点,SteamVR统计加入大朋E4

Hello大家好&#xff0c;每月一期的VR内容/硬件大数据统计又和大家见面了。 想了解VR软硬件行情么&#xff1f;关注这里就对了。我们会统计Steam平台的用户及内容等数据&#xff0c;每月初准时为你推送&#xff0c;不要错过喔&#xff01; 本数据报告包含&#xff1a;Steam VR硬…

计算机找不到msvcr120.dll无法安装启动,三招修复方法

在安装运行软件的时候&#xff0c;计算机提示“找不到msvcr120.dll”&#xff0c;“msvcr120.dll缺失”无法启动运行是什么原因呢&#xff1f;msvcr120.dll是一个Windows系统的动态链接库&#xff0c;它是Microsoft Visual C Redistributable for Visual Studio 2013的一部分。…

Rosetta从头蛋白抗体设计、结构优化及在药物研发中的应用专题

第一天 时间:AM9:00~9:50 内容:一.从蛋白质折叠到蛋白质设计 教学目标&#xff1a;了解本方向内容、理论基础、研究意义。主要知识点 主要知识点:1蛋白质折叠与结构预测简介 1.1主链二面角与二级结构 1.2侧链堆积与三级结构 2蛋白质设计简介 2.1蛋白质设计的分类及应用 时间:AM…

DataGrip编写SQL语句操作Spark(Spark ThriftServer)

文章目录 1.Spark ThriftServer2.启动 Spark ThriftServer3.Beeline方式连接4.DataGrip方式连接5. 代码方式6. SparkSQL运行方式7.参考文章 1.Spark ThriftServer Spark ThriftServer 相当于一个持续性的Spark on Hive集成模式&#xff0c;可以启动并监听在10000端口&#xff…

盘口策略 | 交易中最重要的是什么?

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 『正文』 ˇ 交易中最重要的是什么&#xff1f; 当然是Timing啊~~~ “时机是这个世界上最难得到&#xff0c;又最容易失去的东西”夫难得而易失者,时也&#xff1b;时至而不旋踵者,机也,故圣人常顺时…

浅谈Java8中map的新方法

Map在java8中新增了两个replace的方法 1.replace(k,v) 在指定的键已经存在并且有与之相关的映射值时才会将指定的键映射到指定的值&#xff08;新值&#xff09; 在指定的键不存在时&#xff0c;方法会return回来一个null javadoc的注释解释了该默认值方法的实现的等价Java…

Web安全-Godzilla(哥斯拉)Webshell管理工具使用

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 工具下载地址02 运行环境03 工具介绍04 使用案例 01 工具下载地址 https://github.com/BeichenDream/Godzilla点击页面右侧"releases"&#xff0c;进入工具的版本下载页面。 在个人终端…

安装配置云计算模板机

安装虚拟机模板机 一、在VMware上安装Centos虚拟机二、修改虚拟机的ip、网关、DNS三、更换yum源3.1 更换本地yum源3.2 更换国内互联网Yum源 四、 安装net-tools和bash-completion五、 关闭防火墙和SELinux 学习云计算后续需要多个虚拟机&#xff0c;作为云计算集群的节点&#…

数据结构--初识栈和队列

1.栈 1.1栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压…

神级 IDEA 插件!效率提升 50 倍!

安装好Intellij idea之后&#xff0c;进行如下的初始化操作&#xff0c;工作效率提升50倍。 一. 安装插件 1. Codota 代码智能提示插件 只要打出首字母就能联想出一整条语句&#xff0c;这也太智能了&#xff0c;还显示了每条语句使用频率。原因是它学习了我的项目代码&#…

4.从CPU缓存结构到原子操作

一、CPU缓存结构 1.1 CPU的多级缓存 因为CPU的计算速度非常快&#xff0c;但内存的访问速度相对较慢。因此&#xff0c;如果CPU每次都要从内存读取数据&#xff0c;会造成大量的等待时间&#xff0c;降低整体性能。 通过引入多级缓存&#xff0c;可以在CPU和内存之间建立数据…

html5学习精选5篇案例

html5学习心得1 一&#xff1a;了解HTML5前端开发技术 HTML 指的是超文本标记语言 (Hyper Text Markup Language)&#xff0c;标记语言是一套标记标签 (markup tag)&#xff0c;HTML 使用标记标签来描述网页。HTML5区别于HTML的标准&#xff0c;基于全新的规则手册&#xff0…

stm32mp157aaa裸机开发学习之led灯亮灭

asm-led.S .text .global _start _start: /**********LED1点灯**********//**********RCC章节初始化**********/ RCC_INIT:通过RCC_MP_AHB4ENSETR寄存器使能GPIOE组控制器 0x50000A28[4] 1ldr r0,0x50000A28 LED1 GPIOE10 LED3 GPIOE8ldr r1,[r0]orr r1,r1,#(0x1 << 4…

vite4+vue3:从0到1搭建vben后台管理系统(四)-封装dayjs的日历组件

前言 在后台管理系统中,封装vue的日历组件是很常见的一个功能,有时候antdvue里面的组件跟我们业务需求差异比较大时,去改antdui的官方组件比较麻烦,这个时候,我们就得自己去封装这样一个日历组件,效果如下图所示: 两种实现方式之vue2.x的实现 <template><div&…

用简单易懂的方式手写一个单例模式,看了不会来打我

文章目录 一、如何手写一个单例模式1.1 什么是单例模式1.2 单例模式的适用场景1.3 单例模式的设计原理1.4 单例模式的实现方案1.5 代码测试 一、如何手写一个单例模式 1.1 什么是单例模式 单例模式是一种常用的软件设计模式&#xff0c;它的核心是只包含一个实例的特殊类。单…

每日一道算法题--进制转换

进制转换 题目来源解题思路代码 题目来源 题目链接: 进制转换 解题思路 首先&#xff0c;从标准输入读取两个整数 M 和 N&#xff0c;分别表示待转换的十进制数和目标进制。如果输入的十进制数 M 等于 0&#xff0c;直接输出 0 并返回。判断输入的十进制数是否为负数&#xf…

网络商城源码如何选择?

电商行业的不断发展&#xff0c;越来越多的企业和商家希望建设自己的网络商城系统&#xff0c;为消费者提供更加便捷的购物体验。 但是&#xff0c;想要实现这一目标&#xff0c;选择一款优秀的网络商城系统源码至关重要。那么&#xff0c;在如此众多的商城系统源码中&#xff…