#include "QtWidgetsApplication4.h" #include #include #include #include #include #include #include #include //#include #include CardData::CardData(const QString& name, const QString& date, const QString& description) : name(name), date(date), description(description), activated(false) { } CardItemDelegate::CardItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { } void CardItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { painter->setRenderHint(QPainter::Antialiasing); painter->save(); // 获取数据 CardData data = index.data(Qt::UserRole).value(); // 绘制卡片背景 QRect rect = option.rect; rect.adjust(8, 4, -8, -4); // 创建圆角路径 QPainterPath path; path.addRoundedRect(rect, 8, 8); // 绘制阴影 QColor shadowColor(0, 0, 0, 30); for (int i = 0; i < 5; ++i) { QRect shadowRect = rect.adjusted(0, i, 0, i); QPainterPath shadowPath; shadowPath.addRoundedRect(shadowRect, 8, 8); painter->fillPath(shadowPath, shadowColor); } // 绘制卡片背景 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); if (data.activated) { gradient.setColorAt(0, QColor(40, 70, 45)); gradient.setColorAt(1, QColor(45, 80, 50)); painter->fillPath(path, gradient); painter->setPen(QPen(QColor(60, 180, 90), 2)); } else if (option.state & QStyle::State_Selected) { gradient.setColorAt(0, QColor(45, 45, 55)); gradient.setColorAt(1, QColor(55, 55, 65)); painter->fillPath(path, gradient); painter->setPen(QPen(QColor(70, 130, 180), 2)); } else { painter->fillPath(path, QColor(35, 35, 40)); painter->setPen(QPen(QColor(60, 60, 65))); } painter->drawPath(path); // 设置字体 QFont nameFont("Microsoft YaHei", 10); nameFont.setBold(true); QFont normalFont("Microsoft YaHei", 9); // 计算文本区域 int padding = 15; QRect nameRect = rect.adjusted(padding, padding, -padding, 0); nameRect.setHeight(25); QRect dateRect = nameRect; dateRect.translate(0, nameRect.height()); QRect descRect = dateRect; descRect.translate(0, dateRect.height()); descRect.setHeight(40); // 绘制文本 painter->setFont(nameFont); painter->setPen(Qt::white); painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, data.name); painter->setFont(normalFont); painter->setPen(QColor(180, 180, 180)); painter->drawText(dateRect, Qt::AlignLeft | Qt::AlignVCenter, data.date); painter->setPen(QColor(160, 160, 160)); painter->drawText(descRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, data.description); painter->restore(); } QSize CardItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(option); Q_UNUSED(index); return QSize(380, 130); } MainWindow::MainWindow(QWidget* parent) : QWidget(parent) { setupUI(); setupStyle(); // 添加示例数据 for (int i = 1; i <= 10; ++i) { CardData data( QString("项目 %1").arg(i), QDate::currentDate().toString("yyyy-MM-dd"), QString("这是项目 %1 的详细描述信息,可以包含多行文本内容。这是一个较长的描述,用于测试换行效果。").arg(i) ); addCardItem(data); } } void MainWindow::setupUI() { setWindowTitle(tr("卡片列表示例")); resize(400, 600); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(10, 10, 10, 10); layout->setSpacing(0); listWidget = new QListWidget(this); listWidget->setSpacing(10); listWidget->setResizeMode(QListWidget::Adjust); listWidget->setUniformItemSizes(false); listWidget->setViewMode(QListWidget::ListMode); listWidget->setVerticalScrollMode(QListWidget::ScrollPerPixel); listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); CardItemDelegate* delegate = new CardItemDelegate(listWidget); listWidget->setItemDelegate(delegate); // 连接信号 connect(listWidget, &QListWidget::itemDoubleClicked, this, &MainWindow::onItemDoubleClicked); listWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(listWidget, &QListWidget::customContextMenuRequested, this, &MainWindow::showContextMenu); layout->addWidget(listWidget); } void MainWindow::setupStyle() { setStyleSheet("QWidget {" " background-color: #1e1e1e;" "}" "QListWidget {" " background-color: #1e1e1e;" " border: none;" " outline: none;" "}" "QListWidget::item {" " background-color: transparent;" " padding: 4px;" "}" "QListWidget::item:selected {" " background-color: transparent;" "}" "QScrollBar:vertical {" " border: none;" " background: #1e1e1e;" " width: 8px;" " margin: 0px;" "}" "QScrollBar::handle:vertical {" " background: #404040;" " min-height: 20px;" " border-radius: 4px;" "}" "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {" " height: 0px;" "}" "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {" " background: none;" "}" "QMenu {" " background-color: #2d2d2d;" " border: 1px solid #404040;" " padding: 5px;" "}" "QMenu::item {" " background-color: transparent;" " padding: 6px 25px;" " border-radius: 4px;" " color: #ffffff;" "}" "QMenu::item:selected {" " background-color: #404040;" "}" "QMenu::separator {" " height: 1px;" " background: #404040;" " margin: 5px 0px;" "}" ); } void MainWindow::addCardItem(const CardData& data) { QListWidgetItem* item = new QListWidgetItem(listWidget); item->setData(Qt::UserRole, QVariant::fromValue(data)); item->setSizeHint(QSize(380, 120)); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); } void MainWindow::onItemDoubleClicked(QListWidgetItem* item) { // 先将所有项目设置为未激活状态 for (int row = 0; row < listWidget->count(); ++row) { QListWidgetItem* currentItem = listWidget->item(row); CardData data = currentItem->data(Qt::UserRole).value(); data.activated = false; currentItem->setData(Qt::UserRole, QVariant::fromValue(data)); } // 设置当前点击项目为激活状态 CardData data = item->data(Qt::UserRole).value(); data.activated = true; item->setData(Qt::UserRole, QVariant::fromValue(data)); listWidget->viewport()->update(); } void MainWindow::showContextMenu(const QPoint& pos) { QListWidgetItem* item = listWidget->itemAt(pos); if (!item) return; QMenu menu(this); QAction* sendAction = menu.addAction(tr("发送到设备")); menu.addSeparator(); QAction* editAction = menu.addAction(tr("修改")); QAction* deleteAction = menu.addAction(tr("删除")); menu.addSeparator(); QAction* showInExplorerAction = menu.addAction(tr("在资源管理器中显示")); // 设置图标 sendAction->setIcon(QIcon::fromTheme("document-send")); editAction->setIcon(QIcon::fromTheme("document-edit")); deleteAction->setIcon(QIcon::fromTheme("document-delete")); showInExplorerAction->setIcon(QIcon::fromTheme("folder")); QAction* action = menu.exec(listWidget->viewport()->mapToGlobal(pos)); if (!action) return; if (action == sendAction) sendToDevice(item); else if (action == editAction) editItem(item); else if (action == deleteAction) deleteItem(item); else if (action == showInExplorerAction) showInExplorer(item); } void MainWindow::sendToDevice(QListWidgetItem* item) { CardData data = item->data(Qt::UserRole).value(); qDebug() << "发送到设备:" << data.name; } void MainWindow::editItem(QListWidgetItem* item) { CardData data = item->data(Qt::UserRole).value(); qDebug() << "编辑项目:" << data.name; } void MainWindow::deleteItem(QListWidgetItem* item) { int row = listWidget->row(item); delete listWidget->takeItem(row); } void MainWindow::showInExplorer(QListWidgetItem* item) { QString path = QDir::currentPath(); #ifdef Q_OS_WIN QProcess::startDetached("explorer.exe", { "/select,", QDir::toNativeSeparators(path) }); #elif defined(Q_OS_MAC) QProcess::startDetached("open", { "-R", path }); #else QProcess::startDetached("xdg-open", { QFileInfo(path).path() }); #endif }