【Qt】可爱的窗口关闭确认弹窗实现

embedded/2025/2/26 12:03:05/

文章目录

  • ​​​实现思路
      • 界面构建
      • 交互逻辑实现
      • 颜色渐变处理
      • 圆形部件绘制
  • 代码
    • 在主窗口的构造函数中创建弹窗实例
    • ExitConfirmDialog 类代码
    • ColorCircleWidget 类代码

在这里插入图片描述
今天在Qt实现了这样一个可互动的窗口(上图由于录屏工具限制没有录制到鼠标)

​​​实现思路

实现这样一个可爱的退出确认弹窗,整体思路是结合多个组件和交互逻辑来打造具有吸引力和交互性的界面。具体如下:

界面构建

  • 布局设计:在 ExitConfirmDialog 类的构造函数中,使用多种布局(如 QVBoxLayoutQHBoxLayout)将各个组件有序排列。首先创建提示信息标签显示询问文本,然后添加圆形部件 ColorCircleWidget 作为视觉焦点,最后设置“确认退出”和“取消”两个按钮,方便用户进行操作选择。
  • 组件创建与属性设置:对每个组件进行个性化设置,如调整标签的字体大小和对齐方式,设置按钮的文本内容,固定圆形部件的大小等,同时为部分组件设置鼠标穿透属性,避免影响整体交互体验。

交互逻辑实现

  • 按钮点击响应:使用 connect 函数将按钮的点击信号与相应的槽函数连接。当点击“确认退出”按钮时,触发 onRightButtonClicked 槽函数,发出 rightButtonClicked 信号并接受对话框;点击“取消”按钮时,直接拒绝对话框。
  • 鼠标交互效果:通过重写 mouseMoveEvententerEventleaveEvent 事件处理函数,实现与鼠标的交互效果。当鼠标移动或进入对话框时,调用 updateCircleGradientBasedOnMouse 函数根据鼠标位置更新圆形部件的渐变颜色和嘴巴表情,同时更新眼珠位置,使圆形部件更生动;当鼠标离开对话框时,将圆形部件的渐变颜色、嘴巴表情和眼珠位置恢复到初始状态。

颜色渐变处理

  • 获取渐变颜色:定义 getColorFromGradient 函数,用于从线性渐变中获取指定位置的颜色。通过遍历渐变的颜色停靠点,计算指定位置的颜色值,实现颜色的平滑过渡。
  • 混合渐变颜色:在 updateCircleGradientBasedOnMouse 函数中,根据鼠标到两个按钮的距离计算权重,对权重进行平滑处理后,根据权重混合不同的渐变颜色,生成最终的渐变效果,并应用到圆形部件上。

圆形部件绘制

  • 初始化与属性设置:在 ColorCircleWidget 类的构造函数中,初始化圆形部件的基本属性,如嘴巴表情、渐变颜色等,并开启鼠标跟踪功能。
  • 绘制图形:重写 paintEvent 函数,使用 QPainter 绘制圆形、眼睛、眼珠和嘴巴等图形元素。根据当前的渐变颜色填充圆形,根据嘴巴表情调整嘴巴宽度,根据鼠标位置更新眼珠位置,实现动态绘制效果。

代码

在主窗口的构造函数中创建弹窗实例

    // 拦截默认关闭事件_closeDialog = new ExitConfirmDialog(this);_closeDialog->setFixedSize(400,300);connect(_closeDialog, &ExitConfirmDialog::rightButtonClicked, this, &MainWindow::closeWindow);this->setIsDefaultClosed(false);connect(this, &MainWindow::closeButtonClicked, this, [=]() {_closeDialog->exec();});

ExitConfirmDialog 类代码

#ifndef EXITCONFIRMDIALOG_H
#define EXITCONFIRMDIALOG_H#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include "ColorCircleWidget.h"class ExitConfirmDialog : public QDialog
{Q_OBJECT
public:explicit ExitConfirmDialog(QWidget *parent = nullptr);~ExitConfirmDialog();signals:void rightButtonClicked();protected:void mouseMoveEvent(QMouseEvent *event) override;void enterEvent(QEnterEvent *event) override;void leaveEvent(QEvent *event) override;private slots:void onRightButtonClicked();private:QLabel *messageLabel;QPushButton *rightButton;QPushButton *cancelButton;ColorCircleWidget *circleWidget;void updateCircleGradientBasedOnMouse();QColor getColorFromGradient(const QLinearGradient& gradient, double position);
};#endif // EXITCONFIRMDIALOG_H
#include "ExitConfirmDialog.h"
#include <QPalette>
#include <QSpacerItem>
#include <QLinearGradient>
#include <QDebug>
#include <QEasingCurve>
#include <QMouseEvent>ExitConfirmDialog::ExitConfirmDialog(QWidget *parent) : QDialog(parent)
{setWindowTitle("确认退出");// 创建提示信息标签messageLabel = new QLabel("确定要退出应用程序吗?", this);messageLabel->setAlignment(Qt::AlignHCenter);QFont font = messageLabel->font();font.setPointSize(18);messageLabel->setFont(font);messageLabel->setAttribute(Qt::WA_TransparentForMouseEvents); // 设置鼠标穿透// 创建按钮rightButton = new QPushButton("确认退出", this);cancelButton = new QPushButton("取消", this);// 连接按钮点击信号到相应槽函数connect(rightButton, &QPushButton::clicked, this, &ExitConfirmDialog::onRightButtonClicked);connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject);// 创建圆形部件circleWidget = new ColorCircleWidget(this);circleWidget->setFixedSize(150, 150);circleWidget->setAttribute(Qt::WA_TransparentForMouseEvents); // 设置鼠标穿透// 创建主布局QVBoxLayout *mainLayout = new QVBoxLayout;mainLayout->addWidget(messageLabel, 0, Qt::AlignTop | Qt::AlignHCenter);// 创建圆形布局QVBoxLayout *circleLayout = new QVBoxLayout;circleLayout->addStretch();circleLayout->addWidget(circleWidget, 0, Qt::AlignHCenter);circleLayout->addStretch();mainLayout->addLayout(circleLayout);// 创建按钮布局QHBoxLayout *buttonLayout = new QHBoxLayout;buttonLayout->addWidget(cancelButton);buttonLayout->addStretch();buttonLayout->addWidget(rightButton);mainLayout->addLayout(buttonLayout);setLayout(mainLayout);// 设置鼠标跟踪setMouseTracking(true);rightButton->setMouseTracking(true);cancelButton->setMouseTracking(true);circleWidget->setMouseTracking(true);
}ExitConfirmDialog::~ExitConfirmDialog()
{// 析构函数,这里没有动态分配的资源需要手动释放,Qt会自动处理
}// 从渐变中获取指定位置的颜色
QColor ExitConfirmDialog::getColorFromGradient(const QLinearGradient& gradient, double position)
{position = qBound(0.0, position, 1.0);QGradientStops stops = gradient.stops();for (int i = 0; i < stops.size() - 1; ++i) {if (position >= stops[i].first && position < stops[i + 1].first) {double ratio = (position - stops[i].first) / (stops[i + 1].first - stops[i].first);QColor startColor = stops[i].second;QColor endColor = stops[i + 1].second;int red = static_cast<int>(startColor.red() + (endColor.red() - startColor.red()) * ratio);int green = static_cast<int>(startColor.green() + (endColor.green() - startColor.green()) * ratio);int blue = static_cast<int>(startColor.blue() + (endColor.blue() - startColor.blue()) * ratio);return QColor(red, green, blue);}}return stops.back().second;
}// 鼠标移动事件处理
void ExitConfirmDialog::mouseMoveEvent(QMouseEvent *event)
{updateCircleGradientBasedOnMouse();QPointF localPos = circleWidget->mapFromGlobal(QCursor::pos());circleWidget->updatePupilPosition(localPos);QDialog::mouseMoveEvent(event);
}// 鼠标进入事件处理
void ExitConfirmDialog::enterEvent(QEnterEvent *event)
{updateCircleGradientBasedOnMouse();QPointF localPos = circleWidget->mapFromGlobal(QCursor::pos());circleWidget->updatePupilPosition(localPos);QDialog::enterEvent(event);
}// 鼠标离开事件处理
void ExitConfirmDialog::leaveEvent(QEvent *event)
{QLinearGradient yellowGradient(0, 0, 0, circleWidget->height());yellowGradient.setColorAt(0, QColor(243, 203, 130));yellowGradient.setColorAt(1, QColor(243, 203, 130));circleWidget->setGradient(yellowGradient);circleWidget->setMouthExpression(1);circleWidget->resetPupilPosition(); // 眼珠复原QDialog::leaveEvent(event);
}// 根据鼠标位置更新圆形部件的渐变
void ExitConfirmDialog::updateCircleGradientBasedOnMouse()
{// 检查鼠标是否在对话框内,如果不在则直接返回if (!underMouse()) {return;}// 获取鼠标在对话框内的全局位置QPoint mousePos = mapFromGlobal(QCursor::pos());// 获取取消按钮的中心点位置QPoint cancelCenter = cancelButton->geometry().center();// 获取确认退出按钮的中心点位置QPoint rightCenter = rightButton->geometry().center();// 计算鼠标位置到取消按钮中心点的距离double distToCancel = QLineF(mousePos, cancelCenter).length();// 计算鼠标位置到确认退出按钮中心点的距离double distToRight = QLineF(mousePos, rightCenter).length();// 计算对话框对角线的长度,作为最大距离double maxDist = std::sqrt(std::pow(width(), 2) + std::pow(height(), 2));// 对鼠标到取消按钮的距离进行归一化处理,确保值在 0 到 1 之间double normalizedDistToCancel = qMin(distToCancel / maxDist, 1.0);// 对鼠标到确认退出按钮的距离进行归一化处理,确保值在 0 到 1 之间double normalizedDistToRight = qMin(distToRight / maxDist, 1.0);// 计算取消按钮的权重,距离越近权重越大double weightCancel = 0.70 - normalizedDistToCancel;// 计算确认退出按钮的权重,距离越近权重越大double weightRight = 0.70 - normalizedDistToRight;// 计算总权重double totalWeight = weightCancel + weightRight;// 如果总权重大于 0,则对两个按钮的权重进行归一化处理if (totalWeight > 0) {weightCancel /= totalWeight;weightRight /= totalWeight;}// 使用 InOutQuad 曲线对取消按钮的权重进行平滑处理QEasingCurve easing(QEasingCurve::InOutQuad);double smoothWeightCancel = easing.valueForProgress(weightCancel);// 根据平滑后的取消按钮权重设置圆形部件的嘴巴表情circleWidget->setMouthExpression(smoothWeightCancel);// 如果平滑后的取消按钮权重超过 0.8,则将圆形部件的渐变设置为纯黄色if (smoothWeightCancel > 0.80) {QLinearGradient yellowGradient(0, 0, 0, circleWidget->height());yellowGradient.setColorAt(0, QColor(243, 203, 130));yellowGradient.setColorAt(1, QColor(243, 203, 130));circleWidget->setGradient(yellowGradient);return;}// 创建一个绿黄渐变对象QLinearGradient greenYellowGradient(0, 0, 0, circleWidget->height());greenYellowGradient.setColorAt(0, QColor(118, 174, 141));greenYellowGradient.setColorAt(0.8, QColor(243, 203, 130));greenYellowGradient.setColorAt(1, QColor(243, 203, 130));// 创建一个混合渐变对象,用于存储最终的渐变QLinearGradient mixedGradient(0, 0, 0, circleWidget->height());// 遍历渐变的起始和结束位置(0 到 1)for (int y = 0; y <= 1; y += 1) {// 定义左侧颜色为黄色QColor leftColor = QColor(243, 203, 130);// 从绿黄渐变中获取指定位置的颜色QColor rightColor = getColorFromGradient(greenYellowGradient, y);// 根据平滑后的取消按钮权重对左右颜色进行混合QColor mixedColor(qBound(0, int(leftColor.red() * smoothWeightCancel + rightColor.red() * (1 - smoothWeightCancel)), 255),qBound(0, int(leftColor.green() * smoothWeightCancel + rightColor.green() * (1 - smoothWeightCancel)), 255),qBound(0, int(leftColor.blue() * smoothWeightCancel + rightColor.blue() * (1 - smoothWeightCancel)), 255));// 将混合后的颜色设置到混合渐变对象的指定位置mixedGradient.setColorAt(y, mixedColor);}// 将最终的混合渐变设置到圆形部件上circleWidget->setGradient(mixedGradient);
}// 确认退出按钮点击事件处理
void ExitConfirmDialog::onRightButtonClicked()
{emit rightButtonClicked();accept();
}

ColorCircleWidget 类代码

#ifndef COLORCIRCLEWIDGET_H
#define COLORCIRCLEWIDGET_H#include <QWidget>
#include <QGradient>
#include <QPointF>class ColorCircleWidget : public QWidget
{Q_OBJECT
public:explicit ColorCircleWidget(QWidget *parent = nullptr);~ColorCircleWidget();void setMouthExpression(qreal expression);void setGradient(const QGradient &gradient);void updatePupilPosition(const QPointF& mousePos);void resetPupilPosition();protected:void paintEvent(QPaintEvent *event) override;private:QGradient m_gradient;qreal m_mouthExpression;int mouthWidth;int mouthHeight;int originalMouthWidth;bool isFirstOpen = true;QPointF leftEyeCenter;QPointF rightEyeCenter;QPointF leftPupilPos;QPointF rightPupilPos;int eyeRadius;
};#endif // COLORCIRCLEWIDGET_H
#include "ColorCircleWidget.h"
#include <QPainter>// 构造函数,初始化 ColorCircleWidget 对象
ColorCircleWidget::ColorCircleWidget(QWidget *parent) : QWidget(parent),// 初始化嘴巴表情,范围在 0 到 1 之间m_mouthExpression(0),// 初始化嘴巴宽度mouthWidth(0),// 初始化嘴巴高度mouthHeight(0),// 初始化嘴巴原始宽度originalMouthWidth(0)
{// 创建一个线性渐变对象,渐变方向从顶部到底部QLinearGradient gradient(0, 0, 0, height());// 设置渐变起始颜色gradient.setColorAt(0, QColor(243, 203, 130));// 设置渐变结束颜色gradient.setColorAt(1, QColor(243, 203, 130));// 将渐变对象赋值给成员变量 m_gradientm_gradient = gradient;// 开启鼠标跟踪功能,以便能够接收鼠标移动事件setMouseTracking(true);
}// 析构函数,由于没有动态分配的资源,这里为空
ColorCircleWidget::~ColorCircleWidget()
{
}// 设置嘴巴表情的函数
void ColorCircleWidget::setMouthExpression(qreal expression)
{// 检查传入的表情值是否与当前表情值不同if (m_mouthExpression != expression) {// 将表情值限制在 0 到 1 的范围内m_mouthExpression = qBound(0.0, expression, 1.0);// 如果原始嘴巴宽度还未初始化,则将当前嘴巴宽度赋值给原始嘴巴宽度if (originalMouthWidth == 0) {originalMouthWidth = mouthWidth;}// 根据表情值计算新的嘴巴宽度mouthWidth = static_cast<int>(originalMouthWidth * (1 - 0.5 * m_mouthExpression));// 触发重绘事件,更新界面显示update();}
}// 设置渐变的函数
void ColorCircleWidget::setGradient(const QGradient &gradient)
{// 检查传入的渐变对象是否与当前渐变对象不同if (m_gradient != gradient) {// 将传入的渐变对象赋值给成员变量 m_gradientm_gradient = gradient;// 触发重绘事件,更新界面显示update();}
}// 更新眼珠位置的函数,根据鼠标位置计算眼珠的偏移量
void ColorCircleWidget::updatePupilPosition(const QPointF& mousePos)
{// 获取窗口宽度和高度中的较小值,作为圆形的边长int side = qMin(width(), height());// 计算眼睛半径,为边长的 1/8eyeRadius = side / 8;// 计算眼睛的垂直位置,为边长的 1/3int eyeY = side / 3;// 计算左眼的水平位置int leftEyeX = side / 3 - eyeRadius;// 计算右眼的水平位置int rightEyeX = 2 * side / 3 - eyeRadius;// 计算左眼的中心点位置leftEyeCenter = QPointF(leftEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);// 计算右眼的中心点位置rightEyeCenter = QPointF(rightEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);// 计算鼠标位置相对于左眼中心点的偏移量QPointF leftOffset = mousePos - leftEyeCenter;// 计算鼠标位置相对于右眼中心点的偏移量QPointF rightOffset = mousePos - rightEyeCenter;// 计算左眼偏移量的长度double leftLength = std::sqrt(leftOffset.x() * leftOffset.x() + leftOffset.y() * leftOffset.y());// 计算右眼偏移量的长度double rightLength = std::sqrt(rightOffset.x() * rightOffset.x() + rightOffset.y() * rightOffset.y());// 定义左眼偏移量的最大长度double leftMaxLength = eyeRadius / 2;// 定义右眼偏移量的最大长度double rightMaxLength = eyeRadius / 2;// 如果左眼偏移量的长度超过最大长度,则对偏移量进行缩放if (leftLength > leftMaxLength) {leftOffset *= leftMaxLength / leftLength;}// 如果右眼偏移量的长度超过最大长度,则对偏移量进行缩放if (rightLength > rightMaxLength) {rightOffset *= rightMaxLength / rightLength;}// 计算左眼眼珠的最终位置leftPupilPos = leftEyeCenter + leftOffset;// 计算右眼眼珠的最终位置rightPupilPos = rightEyeCenter + rightOffset;// 触发重绘事件,更新界面显示update();
}// 重置眼珠位置的函数,将眼珠位置恢复到初始状态
void ColorCircleWidget::resetPupilPosition()
{// 获取窗口宽度和高度中的较小值,作为圆形的边长int side = qMin(width(), height());// 计算眼睛半径,为边长的 1/8eyeRadius = side / 8;// 计算眼睛的垂直位置,为边长的 1/3int eyeY = side / 3;// 计算左眼的水平位置int leftEyeX = side / 3 - eyeRadius;// 计算右眼的水平位置int rightEyeX = 2 * side / 3 - eyeRadius;// 计算左眼的中心点位置leftEyeCenter = QPointF(leftEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);// 计算右眼的中心点位置rightEyeCenter = QPointF(rightEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);// 将左眼眼珠位置重置为左眼中心点位置leftPupilPos = leftEyeCenter;// 将右眼眼珠位置重置为右眼中心点位置rightPupilPos = rightEyeCenter;// 触发重绘事件,更新界面显示update();
}// 绘制事件处理函数,当需要重绘界面时调用
void ColorCircleWidget::paintEvent(QPaintEvent *event)
{// 忽略事件参数,因为在本函数中不需要使用Q_UNUSED(event);// 创建一个 QPainter 对象,用于绘制图形QPainter painter(this);// 开启抗锯齿功能,使绘制的图形更加平滑painter.setRenderHint(QPainter::Antialiasing);// 获取窗口宽度和高度中的较小值,作为圆形的边长int side = qMin(width(), height());// 计算圆形的绘制区域QRectF rect((width() - side) / 2, (height() - side) / 2, side, side);// 创建一个画刷对象,使用当前的渐变填充QBrush brush(m_gradient);// 设置画刷painter.setBrush(brush);// 不使用画笔,即绘制的图形没有边框painter.setPen(Qt::NoPen);// 绘制圆形painter.drawEllipse(rect);// 创建一个画笔对象,设置颜色和宽度QPen pen(QColor(233, 200, 127), 1);// 设置画笔painter.setPen(pen);// 不使用画刷,即绘制的图形没有填充颜色painter.setBrush(Qt::NoBrush);// 绘制圆形的边框painter.drawEllipse(rect.adjusted(0.5, 0.5, -0.5, -0.5));// 计算眼睛半径,为边长的 1/8eyeRadius = side / 8;// 计算眼睛的垂直位置,为边长的 1/3int eyeY = side / 3;// 计算左眼的水平位置int leftEyeX = side / 3 - eyeRadius;// 计算右眼的水平位置int rightEyeX = 2 * side / 3 - eyeRadius;// 如果原始嘴巴宽度还未初始化,则将嘴巴宽度初始化为边长的 1/3,并将其赋值给原始嘴巴宽度if (originalMouthWidth == 0) {mouthWidth = side / 3;originalMouthWidth = mouthWidth;}// 计算嘴巴的高度,为边长的 1/10mouthHeight = side / 10;// 计算嘴巴的垂直位置,为边长的 2/3int mouthY = 2 * side / 3;// 计算嘴巴的水平位置int mouthX = side / 2 - mouthWidth / 2;// 设置画刷为白色,用于绘制眼睛的白色部分painter.setBrush(Qt::white);// 不使用画笔,即绘制的图形没有边框painter.setPen(Qt::NoPen);// 计算左眼的绘制区域QRectF leftEyeRect(leftEyeX + (width() - side) / 2, eyeY + (height() - side) / 2, 2 * eyeRadius, 2 * eyeRadius);// 绘制左眼的白色部分painter.drawEllipse(leftEyeRect);// 设置画刷为黑色,用于绘制左眼的眼珠painter.setBrush(Qt::black);// 如果左眼眼珠位置为空,则将其初始化为左眼中心点位置if (leftPupilPos.isNull()) {leftPupilPos = QPointF(leftEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);}// 计算左眼眼珠的绘制区域QRectF leftPupilRect(leftPupilPos.x() - eyeRadius / 2, leftPupilPos.y() - eyeRadius / 2, eyeRadius, eyeRadius);// 绘制左眼的眼珠painter.drawEllipse(leftPupilRect);// 设置画刷为白色,用于绘制右眼的白色部分painter.setBrush(Qt::white);// 不使用画笔,即绘制的图形没有边框painter.setPen(Qt::NoPen);// 计算右眼的绘制区域QRectF rightEyeRect(rightEyeX + (width() - side) / 2, eyeY + (height() - side) / 2, 2 * eyeRadius, 2 * eyeRadius);// 绘制右眼的白色部分painter.drawEllipse(rightEyeRect);// 设置画刷为黑色,用于绘制右眼的眼珠painter.setBrush(Qt::black);// 如果右眼眼珠位置为空,则将其初始化为右眼中心点位置if (rightPupilPos.isNull()) {rightPupilPos = QPointF(rightEyeX + eyeRadius + (width() - side) / 2, eyeY + eyeRadius + (height() - side) / 2);}// 计算右眼眼珠的绘制区域QRectF rightPupilRect(rightPupilPos.x() - eyeRadius / 2, rightPupilPos.y() - eyeRadius / 2, eyeRadius, eyeRadius);// 绘制右眼的眼珠painter.drawEllipse(rightPupilRect);// 创建一个画笔对象,设置颜色和宽度,用于绘制嘴巴QPen mouthPen(QColor(139, 0, 0), 2);// 设置画笔painter.setPen(mouthPen);// 设置画刷为红色,用于填充嘴巴painter.setBrush(QColor(255, 0, 0));// 计算嘴巴的绘制区域QRectF mouthRect(mouthX + (width() - side) / 2, mouthY + (height() - side) / 2, mouthWidth, mouthHeight);// 绘制带有圆角的矩形作为嘴巴painter.drawRoundedRect(mouthRect, 7, 7);// 如果是第一次打开,则设置嘴巴表情为 1,并将标志位设置为 falseif (isFirstOpen) {setMouthExpression(1);isFirstOpen = false;}
}

http://www.ppmy.cn/embedded/167257.html

相关文章

SmartMediakit之音视频直播技术的极致体验与广泛应用

引言 在数字化时代&#xff0c;音视频直播技术已经深入到各个行业和领域&#xff0c;成为信息传递和交流的重要手段。视沃科技自2015年成立以来&#xff0c;一直致力于为传统行业提供极致体验的音视频直播技术解决方案&#xff0c;其旗下的大牛直播SDK凭借强大的功能和卓越的性…

Vue进阶之AI智能助手项目(二)——项目评审与架构设计

AI智能助手项目 基于Vue的最佳实践main.tsApp.vue主应用给子应用下发功能语言language,theme设置及appStore状态管理状态管理router路由index.tspermission.ts基于Vue的最佳实践 src目录概览 api 接口,基于接口可以做 状态处理,interceptorassets/public 静态资源component…

【前端】页面结构管理

在前端开发中&#xff0c;页面结构 的管理有两种常见方式&#xff1a;路由形式 和 组件形式。它们各自有不同的优缺点&#xff0c;适用于不同的场景。以下是它们的对比&#xff1a; 路由形式 在路由形式中&#xff0c;通常会使用前端路由库&#xff08;如 React Router、Vue R…

使用 Three.js 转换 GLSL 粒子效果着色器

大家好&#xff01;我是 [数擎AI]&#xff0c;一位热爱探索新技术的前端开发者&#xff0c;在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情&#xff0c;欢迎关注我的文章&#xff0c;我们一起成长、进步&#xff01; 开发领域&#xff1a;前端开发 | AI…

【Python】Python判断语句经典题(一)

Python入门——判断语句经典练习题例题&#xff08;一&#xff09;。题目来源&#xff1a;Acwing 目录 001、倍数 题目描述 AC代码 002、零食 题目描述 AC代码 003、加薪 题目描述 AC代码 004、DDD 题目描述 AC代码 005、游戏时间 题目描述 AC代码 006、简单排…

如何禁用uniapp,vue页面下拉刷新功能

在小程序开发中&#xff0c;enablePullDownRefresh 是一个常用的配置项&#xff0c;用来控制页面是否允许下拉刷新。但是&#xff0c;有时即使在 pages.json 中将其设置为 false&#xff0c;下拉刷新依然可能未被完全禁用。 1. enablePullDownRefresh: false 配置无效 enable…

kotlin 知识点三 扩展函数和运算符重载

大有用途的扩展函数 不少现代高级编程语言中有扩展函数这个概念&#xff0c;Java 却一直以来都不支持这个非常有用的功 能&#xff0c;这多少会让人有些遗憾。但值得高兴的是&#xff0c;Kotlin 对扩展函数进行了很好的支持&#xff0c;因此这个 知识点是我们无论如何都不能错…

宿主机的 root 是否等于 Docker 容器的 root?

在 Docker 容器化技术中&#xff0c;宿主机的 root 和 容器的 root 并不完全相同&#xff0c;尽管它们都称作 “root 用户”。这里需要明确的是&#xff0c;Docker 容器与宿主机之间存在隔离机制&#xff0c;容器内的 root 用户和宿主机的 root 用户有一些关键的区别。 1. 宿主…