当前位置:   article > 正文

Qt,C++开发炫酷圆形扇形菜单面板_qt扇形控件

qt扇形控件

一如既往,先上图

动画效果参考下面的是视频

20220316-182247

摘要描述:

1、支持嵌入面板和弹出按钮两种,目前仅完成嵌入面板,后期会实现弹出实现

2、支持非常多的自定义功能,有关自定义功能定义参考下面的风格数据结构体代码,结构体中的功能均支持自定义

风格数据结构体代码如下:

  1. /// 圆形菜单控件风格样式数据结构
  2. ///
  3. typedef struct LNCFROUNDMENU_STYLE_{
  4. QList<DGRADIENTCOLOR_DATA> vMenuCtlBkgClr; //菜单渐变背景颜色集合列表
  5. QColor cMenuCtlBkgClr = QColor(88,88,88,44); //菜单控件背景颜色
  6. QColor cMenuBtnBkgClr = QColor(77,77,77,44); //菜单按钮默认背景色
  7. QColor cMenuBtnHovers = QColor(192,192,192,144);//菜单按钮悬停背景色
  8. QColor cMenuBtnTxtClr = QColor(202,202,202); //菜单按钮文字颜色
  9. QColor cMenuTextHover = QColor(255,255,255); //菜单按钮文字悬停颜色
  10. QColor cSwicthBnColor = QColor(144,133,227); //切换按钮默认颜色
  11. QColor cSwicthExpands = QColor(250,142,85); //切换按钮菜单展开时背景颜色
  12. QColor cSwicthBnHover = QColor(250,85,101); //切换按钮鼠标悬停颜色
  13. QColor cBkgBorderClrs = QColor(11,11,21,99); //背景边框颜色
  14. QColor cItemBorderClr = QColor(11,11,21,99); //菜单项边框颜色
  15. qreal dFrameOutScale = 0.75; //菜单外边框距离窗口边界比例
  16. qreal dFrameInnScale = 0.40; //菜单内边框距离窗口边界比例
  17. qreal dCenterBnScale = 1.5; //菜单中心按钮大小比例,相对于菜单窗口大小的缩小比例
  18. qreal dItemsBtnScale = 2.0; //菜单按钮图标大小比例,相对于菜单按钮扇形区域大小缩放比例
  19. qreal dItemsBkgScale = 1.25; //菜单按钮圆形背景大小比例,相对于菜单按钮扇形区域大小缩放比例
  20. qreal dItemBorderWid = 1; //菜单按钮边框宽度
  21. qreal dBnRoundRadius = 0.5; //菜单按钮圆角比例,0-0.5之间
  22. qreal dBkgBordersWid = 1; //菜单背景宽度
  23. qreal dStartDrawAngle = 180.0; //起始绘制角度
  24. uint uCenterBtnSize = 64; //菜单中心按钮绝对大小尺寸
  25. uint uAnimatedTimer = 400; //菜单展开和关闭动画周期时长
  26. bool bShowCtrlBkgnd = false; //是否显示控件背景
  27. bool bShowItemsLine = false; //是否绘制分割线
  28. bool bRoundMenuItem = true; //是否绘制圆形菜单项,默认是,否则显示扇形
  29. bool bDrawCenterBtn = true; //绘制中心按钮
  30. bool bMenuBtnsScale = true; //中心按钮大小比例类型,true表示绝对比例,false绝对大小
  31. bool bHasRandomClrs = false; //是否使用随机按钮背景颜色
  32. bool bRotateAnimate = true; //是否启用旋转动画,如果使用旋转动画至少将菜单展开和关闭周期设置到400或以上
  33. bool bShowBkgBorder = false; //是否显示背景边框
  34. bool bHasItemBorder = false; //是否显示菜单按钮边框
  35. bool bNoIcoFullName = true; //无图标按钮是否显示菜单全名
  36. bool operator == (const LNCFROUNDMENU_STYLE_& rhs) // == 操作运算符重载
  37. {
  38. if(vMenuCtlBkgClr.count()!= rhs.vMenuCtlBkgClr.count())
  39. return false;
  40. if(vMenuCtlBkgClr.count()== rhs.vMenuCtlBkgClr.count()&&rhs.vMenuCtlBkgClr.count()>0){
  41. for(int i=0;i<rhs.vMenuCtlBkgClr.count();i++)
  42. {
  43. if(QString("%1").arg(vMenuCtlBkgClr[i].fBkgndAngleVal) !=QString("%1").arg(rhs.vMenuCtlBkgClr[i].fBkgndAngleVal))
  44. return false;
  45. if(vMenuCtlBkgClr[i].cBkgndAngleClr != rhs.vMenuCtlBkgClr[i].cBkgndAngleClr)
  46. return false;
  47. }
  48. }
  49. return (cMenuCtlBkgClr == rhs.cMenuCtlBkgClr)
  50. && (cMenuBtnBkgClr == rhs.cMenuBtnBkgClr)
  51. && (cMenuBtnHovers == rhs.cMenuBtnHovers)
  52. && (cMenuBtnTxtClr == rhs.cMenuBtnTxtClr)
  53. && (bHasRandomClrs == rhs.bHasRandomClrs)
  54. && (cMenuTextHover == rhs.cMenuTextHover)
  55. && (cSwicthBnColor == rhs.cSwicthBnColor)
  56. && (cSwicthExpands == rhs.cSwicthExpands)
  57. && (cSwicthBnHover == rhs.cSwicthBnHover)
  58. && (QString("%1").arg(dFrameOutScale) == QString("%1").arg(rhs.dFrameOutScale))
  59. && (QString("%1").arg(dFrameInnScale) == QString("%1").arg(rhs.dFrameInnScale))
  60. && (QString("%1").arg(dCenterBnScale) == QString("%1").arg(rhs.dCenterBnScale))
  61. && (QString("%1").arg(dItemsBtnScale) == QString("%1").arg(rhs.dItemsBtnScale))
  62. && (QString("%1").arg(dItemsBkgScale) == QString("%1").arg(rhs.dItemsBkgScale))
  63. && (QString("%1").arg(dStartDrawAngle) == QString("%1").arg(rhs.dStartDrawAngle))
  64. && (uCenterBtnSize == rhs.uCenterBtnSize)
  65. && (uAnimatedTimer == rhs.uAnimatedTimer)
  66. && (bShowCtrlBkgnd == rhs.bShowCtrlBkgnd)
  67. && (bShowItemsLine == rhs.bShowItemsLine)
  68. && (bRoundMenuItem == rhs.bRoundMenuItem)
  69. && (bDrawCenterBtn == rhs.bDrawCenterBtn)
  70. && (bMenuBtnsScale == rhs.bMenuBtnsScale)
  71. && (bHasRandomClrs == rhs.bHasRandomClrs)
  72. && (bRotateAnimate == rhs.bRotateAnimate)
  73. && (cBkgBorderClrs == rhs.cBkgBorderClrs)
  74. && (bShowBkgBorder == rhs.bShowBkgBorder)
  75. && (cItemBorderClr == rhs.cItemBorderClr)
  76. && (QString("%1").arg(dItemBorderWid) == QString("%1").arg(rhs.dItemBorderWid))
  77. && (bHasItemBorder == rhs.bHasItemBorder)
  78. && (dBnRoundRadius == rhs.dBnRoundRadius)
  79. && (QString("%1").arg(dBkgBordersWid) == QString("%1").arg(rhs.dBkgBordersWid))
  80. && (bNoIcoFullName == rhs.bNoIcoFullName); //无图标按钮是否显示菜单全名
  81. }
  82. bool operator != (const LNCFROUNDMENU_STYLE_& rhs) // != 操作运算符重载
  83. {
  84. return !(*this == rhs);
  85. }
  86. }LNCFROUNDMENU_STYLE,*PLNCFROUNDMENU_STYLE;

除了风格自定义还支持自定义图标等功能,参考下面的变量

  1. ///菜单展开图标路径
  2. std::u16string sExpandImgPath;
  3. ///菜单闭合图标路径
  4. std::u16string sClosedImgPath;

头文件主要代码

  1. //默认构造函数
  2. explicit Lncf_QRoundMenuCtl(QWidget *parent = nullptr);
  3. /// 标准构造函数
  4. /// \brief Lncf_QRoundMenuCtl
  5. /// \param bPopup :是否为popup模式
  6. /// \param uBtnSize :中心按钮尺寸
  7. /// \param uItemType :菜单项类型,0圆角矩形,1扇形
  8. /// \param parent :父窗口句柄
  9. ///
  10. explicit Lncf_QRoundMenuCtl(bool bPopup,uint uBtnSize,uint uItemType = 0,QWidget *parent = nullptr);
  11. //标准析构
  12. ~Lncf_QRoundMenuCtl();
  13. private:
  14. /// 初始化圆形菜单控件
  15. /// \brief InitRoundMenuCtl
  16. ///
  17. void InitRoundMenuCtl();
  18. protected:
  19. // 重写系统事件
  20. bool event(QEvent *ev) override;
  21. // 重写系统绘制事件
  22. void paintEvent(QPaintEvent *event) override;
  23. /// 绘制控件圆形背景
  24. /// \brief DrawBackgroundCtl
  25. /// \param painter
  26. ///
  27. void DrawBackgroundCtl(QPainter *painter);
  28. /// 绘制菜单项圆形外边框
  29. /// \brief DrawItemOutBorder
  30. /// \param painter
  31. ///
  32. void DrawItemOutBorder(QPainter *painter);
  33. /// 绘制菜单项圆形内边框
  34. /// \brief DrawItemsInBorder
  35. /// \param painter
  36. ///
  37. void DrawItemsInBorder(QPainter *painter);
  38. /// 绘制菜单中心按钮
  39. /// \brief DrawSwitchsButton
  40. /// \param painter
  41. ///
  42. void DrawSwitchsButton(QPainter *painter);
  43. /// 绘制菜单项按钮
  44. /// \brief DrawMenuCtlButton
  45. /// \param painter
  46. ///
  47. void DrawMenuCtlButton(QPainter *painter);
  48. // 重写系统鼠标松开事件
  49. void mouseReleaseEvent(QMouseEvent *event) override;
  50. private:
  51. /// 初始化菜单动画
  52. /// \brief InitMenuAnimation
  53. ///
  54. void InitMenuAnimation();
  55. /// 获取菜单项外圆半径
  56. /// \brief GetItemsOutRadius
  57. /// \return
  58. ///
  59. qreal GetItemsOutRadius();
  60. /// 获取菜单项内圆半径
  61. /// \brief GetItemsInnRadius
  62. /// \return
  63. ///
  64. qreal GetItemsInnRadius();
  65. /// 获取菜单项目绘制开始角度
  66. /// \brief GetItemStartAngle
  67. /// \return
  68. ///
  69. qreal GetItemStartAngle();
  70. /// 获取菜单控件绘制弧度
  71. /// \brief GetFrmStartRadian
  72. /// \return
  73. ///
  74. qreal GetFrmStartRadian();
  75. /// 获取菜单切换按钮菜单绘图路径
  76. /// \brief GetSwitchBtnsPath
  77. /// \return
  78. ///
  79. QPainterPath GetSwitchBtnsPath();
  80. /// 获取菜单按钮绘图路径
  81. /// \brief GetMenuButtonPath
  82. /// \param index
  83. /// \param hover
  84. /// \return
  85. ///
  86. QPainterPath GetMenuButtonPath(int index, bool hover = false);
  87. private slots:
  88. /// 切换菜单按钮单击
  89. /// \brief MenuSwitchClicked
  90. ///
  91. void MenuSwitchClicked();
  92. /// 菜单项展开或收起
  93. /// \brief MenuItemBtnExpand
  94. /// \param bExpand
  95. ///
  96. void MenuItemBtnExpand(const bool& bExpand);
  97. /// 菜单项单击槽函数
  98. /// \brief MenuItemsBtnClick
  99. /// \param uIndex
  100. ///
  101. void MenuItemsBtnClick(const uint& uIndex);
  102. public:
  103. /// 添加菜单按钮项
  104. /// \brief AddMenuButtonItem
  105. /// \param tMenuItem
  106. /// 注意在插入和添加菜单时图标和title必须提供一个
  107. ///
  108. void AddMenuButtonItem(const LQROUNDMENUBTN_ITEM& tMenuItem);
  109. void AddMenuButtonItem(const QPixmap &icon, const QString &title, const QString &tooltip);
  110. void AddMenuButtonItem(const QPixmap &icon, const QString &title, const QString &tooltip,
  111. const QColor &background);
  112. void AddMenuButtonItem(const QPixmap &icon, const std::u16string &title, const std::u16string &tooltip,
  113. const QColor &background);
  114. /// 插入一个菜单按钮
  115. /// \brief InsertMenuBtnItem
  116. /// \param index
  117. /// \param tMenuItem
  118. ///
  119. void InsertMenuBtnItem(int index,LQROUNDMENUBTN_ITEM tMenuItem);
  120. /// 插入一个按钮项目
  121. /// \brief InsertMenuBtnItem
  122. /// \param index
  123. /// \param icon
  124. /// \param title
  125. /// \param tooltip
  126. /// \param background
  127. ///
  128. void InsertMenuBtnItem(int index, const QPixmap &icon, const QString &title, const QString &tooltip,
  129. const QColor &background = QColor());
  130. void InsertMenuBtnItem(int index, const QPixmap &icon, const std::u16string &title, const std::u16string &tooltip,
  131. const QColor &background = QColor());
  132. /// 获取菜单展开图标路径
  133. /// \brief GetExpandImgPath
  134. /// \return
  135. ///
  136. std::u16string GetExpandImgPath() const;
  137. /// 获取菜单闭合图标路径
  138. /// \brief GetClosedImgPath
  139. /// \return
  140. ///
  141. std::u16string GetClosedImgPath() const;
  142. /// 设置菜单展开图标路径
  143. /// \brief SetExpandImgPath
  144. /// \param sImage
  145. ///
  146. void SetExpandImgPath(const std::u16string& sImage);
  147. /// 设置菜单闭合图标路径
  148. /// \brief SetClosedImgPath
  149. /// \param sImage
  150. ///
  151. void SetClosedImgPath(const std::u16string& sImage);

核心绘图代码如下

  1. // 重写系统绘制事件
  2. void Lncf_QRoundMenuCtl::paintEvent(QPaintEvent *event)
  3. {
  4. QWidget::paintEvent(event);
  5. QPainter painter(this);
  6. painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
  7. //绘制背景
  8. if(this->tMenuCtrlStyles.bShowCtrlBkgnd)
  9. DrawBackgroundCtl(&painter);
  10. //绘制菜单按钮
  11. DrawMenuCtlButton(&painter);
  12. //绘制中心按钮
  13. if(this->tMenuCtrlStyles.bDrawCenterBtn)
  14. DrawSwitchsButton(&painter);
  15. }
  16. /// 绘制控件圆形背景
  17. /// \brief DrawBackgroundCtl
  18. /// \param painter
  19. ///
  20. void Lncf_QRoundMenuCtl::DrawBackgroundCtl(QPainter *painter)
  21. {
  22. painter->setPen(this->tMenuCtrlStyles.bShowBkgBorder?QPen(tMenuCtrlStyles.cBkgBorderClrs,tMenuCtrlStyles.dBkgBordersWid):Qt::NoPen);
  23. if(this->tMenuCtrlStyles.vMenuCtlBkgClr.count()>0){
  24. QLinearGradient gradient(QPoint(0, 0), QPoint(width(), height()));
  25. for(int i=0;i<tMenuCtrlStyles.vMenuCtlBkgClr.count();i++)
  26. gradient.setColorAt(tMenuCtrlStyles.vMenuCtlBkgClr[i].fBkgndAngleVal, tMenuCtrlStyles.vMenuCtlBkgClr[i].cBkgndAngleClr);
  27. painter->setBrush(gradient);
  28. }
  29. else{
  30. painter->setBrush(this->tMenuCtrlStyles.cMenuCtlBkgClr);
  31. }
  32. QRectF rect = this->rect();
  33. uint uRectMinVal = qMin(this->width(),this->height());
  34. rect.setSize(QSize(uRectMinVal*tMenuCtrlStyles.dFrameOutScale,uRectMinVal*tMenuCtrlStyles.dFrameOutScale));
  35. rect.moveCenter(QPointF(width() / 2.0, height() / 2.0));
  36. painter->drawEllipse(rect);
  37. }
  38. /// 绘制菜单项圆形外边框
  39. /// \brief DrawItemOutBorder
  40. /// \param painter
  41. ///
  42. void Lncf_QRoundMenuCtl::DrawItemOutBorder(QPainter *painter)
  43. {
  44. QRectF rect(0.0, 0.0, 2.0 * GetItemsOutRadius(), 2.0 * GetItemsOutRadius());
  45. rect.moveCenter(QPointF(width() / 2.0, height() / 2.0));
  46. painter->save();
  47. painter->setPen(QPen(QBrush(this->tMenuCtrlStyles.cItemBorderClr), tMenuCtrlStyles.dItemBorderWid));
  48. painter->drawEllipse(rect);
  49. painter->restore();
  50. }
  51. /// 绘制菜单项圆形内边框
  52. /// \brief DrawItemsInBorder
  53. /// \param painter
  54. ///
  55. void Lncf_QRoundMenuCtl::DrawItemsInBorder(QPainter *painter)
  56. {
  57. QRectF rect(0.0, 0.0, 2.0 * GetItemsInnRadius(), 2.0 * GetItemsInnRadius());
  58. rect.moveCenter(QPointF(width() / 2.0, height() / 2.0));
  59. painter->save();
  60. painter->setPen(QPen(QBrush(this->tMenuCtrlStyles.cItemBorderClr), tMenuCtrlStyles.dItemBorderWid));
  61. painter->drawEllipse(rect);
  62. painter->restore();
  63. }
  64. int imageRotate =0;
  65. /// 绘制菜单中心按钮
  66. /// \brief DrawSwitchsButton
  67. /// \param painter
  68. ///
  69. void Lncf_QRoundMenuCtl::DrawSwitchsButton(QPainter *painter)
  70. {
  71. auto path = GetSwitchBtnsPath();
  72. painter->setBrush(bSwitchBnHover?tMenuCtrlStyles.cSwicthBnHover:(bHasExpandMenu ? tMenuCtrlStyles.cSwicthExpands : tMenuCtrlStyles.cSwicthBnColor));
  73. painter->setPen(tMenuCtrlStyles.bHasItemBorder?QPen(tMenuCtrlStyles.cItemBorderClr,tMenuCtrlStyles.dItemBorderWid):Qt::NoPen);
  74. painter->drawPath(path);
  75. auto pixmap = bHasExpandMenu ? QPixmap(QString::fromStdU16String(sClosedImgPath)) :
  76. QPixmap(QString::fromStdU16String(sExpandImgPath));
  77. auto rect = path.boundingRect();
  78. if(!pixmap.isNull()){
  79. rect = rect.marginsRemoved(QMargins(rect.width() / 4.0,
  80. rect.height() / 4.0,
  81. rect.width() / 4.0,
  82. rect.height() / 4.0));
  83. painter->drawPixmap(rect, pixmap, pixmap.rect());
  84. }
  85. else{
  86. rect = rect.marginsRemoved(QMargins(rect.width() / 4.0,
  87. rect.height() / 4.0,
  88. rect.width() / 4.0,
  89. rect.height() / 4.0));
  90. std::u16string sSwicthText = bHasExpandMenu ? u"MENU":
  91. u"CLOSE";
  92. QFont fontObj = this->font();
  93. fontObj.setPointSizeF(rect.height()/4.0);
  94. painter->setFont(fontObj);
  95. painter->setPen(bSwitchBnHover?tMenuCtrlStyles.cMenuBtnTxtClr:tMenuCtrlStyles.cMenuTextHover);
  96. painter->drawText(rect, Qt::AlignCenter|Qt::TextWordWrap,QString::fromStdU16String(sSwicthText));
  97. }
  98. }
  99. /// 绘制菜单项按钮
  100. /// \brief DrawMenuCtlButton
  101. /// \param painter
  102. ///
  103. void Lncf_QRoundMenuCtl::DrawMenuCtlButton(QPainter *painter)
  104. {
  105. if(pMenuAnimeGroup->state() != QAbstractAnimation::Running){
  106. if(!bHasExpandMenu||vMenuButtonList.count()<=0){
  107. return;
  108. }
  109. }
  110. if(this->tMenuCtrlStyles.bShowItemsLine&&!this->tMenuCtrlStyles.bRoundMenuItem){
  111. DrawItemOutBorder(painter);
  112. DrawItemsInBorder(painter);
  113. }
  114. auto count = vMenuButtonList.count();
  115. if(count == 0) return;
  116. auto radian = 2 * PI / count;
  117. auto outer_radius = GetItemsOutRadius();
  118. auto inner_radius = GetItemsInnRadius();
  119. QFont fontObj = this->font();
  120. for (int i = 0 ; i< count; ++i)
  121. {
  122. auto path = GetMenuButtonPath(i);
  123. //绘制背景
  124. auto bgColor = this->tMenuCtrlStyles.bHasRandomClrs?QColor::fromHsl(rand()%360,rand()%256,rand()%200):vMenuButtonList.at(i)->cCustomBkgClr;
  125. if(!bgColor.isValid()){
  126. bgColor = this->tMenuCtrlStyles.cMenuBtnBkgClr;
  127. }
  128. auto iconRectWidth = outer_radius - inner_radius;
  129. if(!this->tMenuCtrlStyles.bRoundMenuItem){
  130. painter->fillPath(path,vMenuButtonList.at(i)->bIsHoverState?this->tMenuCtrlStyles.cMenuBtnHovers:bgColor);
  131. }
  132. else{
  133. QRectF rectBtnBkg(0, 0, iconRectWidth / this->tMenuCtrlStyles.dItemsBkgScale, iconRectWidth / this->tMenuCtrlStyles.dItemsBkgScale);
  134. rectBtnBkg.moveCenter(path.boundingRect().center());
  135. painter->setBrush(vMenuButtonList.at(i)->bIsHoverState?this->tMenuCtrlStyles.cMenuBtnHovers:bgColor);
  136. painter->setPen(tMenuCtrlStyles.bHasItemBorder?QPen(tMenuCtrlStyles.cItemBorderClr,tMenuCtrlStyles.dItemBorderWid):Qt::NoPen);
  137. painter->drawRoundedRect(rectBtnBkg,rectBtnBkg.width()*tMenuCtrlStyles.dBnRoundRadius,rectBtnBkg.height()*tMenuCtrlStyles.dBnRoundRadius);
  138. }
  139. auto pixmapIcon = vMenuButtonList.at(i)->pMenuItemIcon;
  140. if(!pixmapIcon.isNull()){
  141. QRectF rectIcon(0, 0, iconRectWidth / this->tMenuCtrlStyles.dItemsBtnScale, iconRectWidth / this->tMenuCtrlStyles.dItemsBtnScale);
  142. rectIcon.moveCenter(path.boundingRect().center());
  143. painter->drawPixmap(rectIcon, pixmapIcon, pixmapIcon.rect());
  144. }
  145. else{
  146. QRectF rectText(0, 0, iconRectWidth / this->tMenuCtrlStyles.dItemsBtnScale*0.95, iconRectWidth / this->tMenuCtrlStyles.dItemsBtnScale*0.95);
  147. rectText.moveCenter(path.boundingRect().center());
  148. fontObj.setPointSizeF(rectText.height()/4.0);
  149. painter->setFont(fontObj);
  150. painter->setPen(vMenuButtonList.at(i)->bIsHoverState?tMenuCtrlStyles.cMenuTextHover:tMenuCtrlStyles.cMenuBtnTxtClr);
  151. painter->drawText(rectText, Qt::AlignCenter|Qt::TextWordWrap, QString::fromStdU16String(vMenuButtonList.at(i)->uItemTitleVal));
  152. }
  153. /***************************
  154. * draw seperator
  155. * */
  156. if(this->tMenuCtrlStyles.bShowItemsLine&&!this->tMenuCtrlStyles.bRoundMenuItem){
  157. QPointF point1(width() / 2.0 + outer_radius * std::cos(radian * i + GetFrmStartRadian()),
  158. height() / 2.0 - outer_radius * std::sin(radian * i + GetFrmStartRadian()));
  159. QPointF point2(width() / 2.0 + inner_radius * std::cos(radian * i + GetFrmStartRadian()),
  160. height() / 2.0 - inner_radius * std::sin(radian * i + GetFrmStartRadian()));
  161. painter->save();
  162. painter->setPen(QPen(QBrush(tMenuCtrlStyles.cItemBorderClr), tMenuCtrlStyles.dBkgBordersWid));
  163. painter->drawLine(point1, point2);
  164. painter->restore();
  165. }
  166. }
  167. }

大半夜刚封装完,困的实在类,先写到这。

有关详细信息和技术交流,移步QQ群:717743458。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/137529
推荐阅读
相关标签
  

闽ICP备14008679号