CustomWidget::~CustomWidget() {for (size_t i = 0; i < buttonManager.registerItem.size(); ++i) {delete buttonManager.registerItem(exitButton);}
}
以上该怎么写删除对象操作,类如下:template <typename T>
class GenericManager {
public:using ConditionFunc = std::function<bool(const T&, const QPoint&)>;using ActionFunc = std::function<void(QPainter&, const T&, bool)>;GenericManager() {}void registerItem(T* item) {int count = items.count();qWarning("Inserting at index %d, current count: %d", count, count);items.insert(count, item);}void processItems(QPainter& bufferPainter, QMouseEvent* event, QWidget* widget, ConditionFunc conditionFunc, ActionFunc actionFunc) {QPoint cursorPos = event ? event->pos() : widget->mapFromGlobal(QCursor::pos());// 将 i 的类型改为 size_tfor (size_t i = 0; i < items.count(); ++i) {T* item = items.at(i);if (item) {qWarning("Inserting at index");bool shouldHighlight = conditionFunc(*item, cursorPos);actionFunc(bufferPainter, *item, shouldHighlight);}}}private:QPtrVector<T> items;
};
使用模板来泛化类,如何增加删除对象的处理,增加代码如下:
// 提供一个公共方法来获取 items 的数量size_t getItemCount() const {return items.count();}// 提供一个公共方法来获取指定索引的元素T* getItemAt(size_t index) const {if (index < items.count()) {return items.at(index);}return nullptr;}
析构函数删除对象:
CustomWidget::~CustomWidget() {// 遍历 GenericManager 中的 items 并释放内存for (size_t i = 0; i < buttonManager.getItemCount(); ++i) {ButtonInfo* item = buttonManager.getItemAt(i);if (item) {delete item;}}
}
注意不能用T* item= buttonManager.getItemAt(i);这样, CustomWidget
的析构函数中正确释放内存
T
是未定义的标识符,因为 T
是 GenericManager
类模板的模板参数,在 CustomWidget
类的作用域内并没有这个类型定义。而在 CustomWidget
里使用的是 GenericManager<ButtonInfo>
,所以应该明确使用 ButtonInfo*
来接收 getItemAt
方法返回的指针。
调用方式:
void CustomWidget::paintEvent(QPaintEvent *event) {bufferPixmap = QPixmap(size());//bufferPixmap.fill(Qt::transparent);QPainter bufferPainter(&bufferPixmap);// drawBackgroundAndBorder(bufferPainter);buttonManager.processItems(bufferPainter, nullptr, this, [](const ButtonInfo& button, const QPoint& cursorPos) {return button.rect.contains(cursorPos);},[this](QPainter& painter, const ButtonInfo& button, bool isHighlighted) { // 添加 this 到捕获列表QRect drawRect(button.rect.x(), button.rect.y(), button.rect.width(), button.rect.height());qWarning("Draw rect: (%d, %d, %d, %d)", drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());QImage img;img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,isHighlighted ? button.highlight_png_size : button.normal_png_size,"PNG");if (img.isNull()) {// 使用 qWarning 替代 qDebugqWarning("Failed to load image");}// 如果 Qt 版本支持,可以保留下面这行// painter.setRenderHint(QPainter::Antialiasing); this->simulateLinearGradient(painter, drawRect, QColor(15, 10, 60), QColor(7, 69, 111));painter.drawImage(drawRect, img);});QPainter painter(this);painter.drawPixmap(0, 0, bufferPixmap);
}
注意,可以随意设置条件和绘制内容,conditionFun本例是lambda表达式 return button.rect.contains(cursorPos);
绘制结果简单一句img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,
isHighlighted ? button.highlight_png_size : button.normal_png_size,
"PNG");
这样充分利用C++的新特性,代码变得简单清晰
在 C++ 的 Lambda 表达式中,方括号 []
部分被称为捕获列表,它用于指定 Lambda 表达式可以访问哪些外部变量。捕获列表不同的写法有不同的作用,下面详细解释为什么在你的代码里一个 Lambda 用 []
,另一个用 [this]
。
1. []
捕获列表
[](const ButtonInfo& button, const QPoint& cursorPos) {return button.rect.contains(cursorPos);
}
这里使用 []
表示该 Lambda 表达式不捕获任何外部变量。这个 Lambda 表达式作为 conditionFunc
传递给 buttonManager.processItems
方法,它只依赖于传入的参数 button
和 cursorPos
,不需要访问外部作用域中的任何变量,所以捕获列表为空。它的功能仅仅是判断鼠标位置 cursorPos
是否在按钮的矩形区域 button.rect
内。
2. [this]
捕获列表
[this](QPainter& painter, const ButtonInfo& button, bool isHighlighted) {QRect drawRect(button.rect.x(), button.rect.y(), button.rect.width(), button.rect.height());qWarning("Draw rect: (%d, %d, %d, %d)", drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());QImage img;img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,isHighlighted ? button.highlight_png_size : button.normal_png_size,"PNG");if (img.isNull()) {qWarning("Failed to load image");}this->simulateLinearGradient(painter, drawRect, QColor(15, 10, 60), QColor(7, 69, 111));painter.drawImage(drawRect, img);
}
这里使用 [this]
表示该 Lambda 表达式捕获当前对象的指针 this
。在这个 Lambda 表达式中,调用了 this->simulateLinearGradient
方法,这是当前对象 CustomWidget
的一个成员函数。为了能够访问当前对象的成员函数和成员变量,需要通过 this
指针,所以在捕获列表中指定 this
。这样,Lambda 表达式就可以在其内部调用当前对象的方法和访问成员变量了。
总结
[]
:不捕获任何外部变量,Lambda 表达式只能使用其参数列表中的变量。[this]
:捕获当前对象的指针,Lambda 表达式可以访问当前对象的成员函数和成员变量。
通过合理使用捕获列表,可以让 Lambda 表达式根据需要访问外部作用域中的变量,从而实现更灵活的功能