Qt高级--(1)自定义导航栏

news2024/11/23 13:16:44

好久没有水博客,参考别人的写一个自定义的导航栏吧。用处挺多的,可以用来切换到不同的信息显示界面。

功能点

1.默认情况下,文字居中显示,不显示图标,不显示三角。
2.可设置文字左侧、顶部、右侧、底部边距;可设置文字对齐方式。
3.可设置图标是否显示、一侧边距、图标大小、显示位置。
4可设置三角是否显示、大小、显示位置,三角值设置了鼠标悬停和鼠标选中状态下显示。
5.可设置背景颜色为画刷颜色。
6.可设置文字与图标的相对位置:图标左文字右、图标右文字左、图标上文字下、图标下文字上。
7.按钮状态分为三种:正常、鼠标悬停、鼠标选中。
8.在按钮不同状态下可设置不同的背景颜色、字体颜色、图标切换、三角颜色等。
9.一组导航按钮一次只能选中一个。
在这里插入图片描述

一、如何分析自己的需求:

布局

1.我这个类是要显示出,界面上的控件,显示的图标,文字(大小,颜色)。
2.除了显示的,还有图标文字之间的布局,还有背景颜色。

从上面看出显示上的主要有,图标文字,布局,背景颜色。
文字
最简单的一种情况是,一个导航按钮只有文字,没有图标。如下图所示,需要考虑到文字到四边的边距、颜色、背景颜色等。
文字距四边的边距分别使用一个变量来保存,在绘制文本时需要将边距计算在内。
在这里插入图片描述
图标 + 文字
当在文字的基础上加上图标时需要增加属性,并且在计算边距时需要将图标考虑在内。
在计算图标与文字的相对位置时需要注意图标的边距与文字的同边边距是重叠的。如下图中图标边距是距离左侧的边距,文字的左边距是包含了图标边距。
此时需要计算图标的大小,同时还需要考虑图标与文字的相对位置,即图标在左文字在右、图标在右文字在左、图标在上文字在下、图标在下文字在上。
在以上的可能性中,图标在左文字在右、图标在上文字在下这两种方式是常用的。
图标与文字左右结构:

在这里插入图片描述

图标与文字上下结构:
在这里插入图片描述

图标 + 文字 + 三角
在 图标 + 文字的基础上增加三角,多个导航按钮组合时可能会达到更好的效果。
在画三角时可以不考虑边距的文字,只需要考虑三角的方向、颜色。
在这里插入图片描述
从上面看出,我们需要定义的变量就有:

//布局限制位置
    int m_paddingLeft;                  // 文字左侧间距
    int m_paddingTop;                   // 文字顶部间距
    int m_paddingRight;                 // 文字右侧间距
    int m_paddingBottom;                // 文字底部间距
    //文字(大小,颜色,对齐方式)
    TextAlign m_textAlign;              // 文字对齐方式,TextAlign对齐样式 
    QColor m_nTextColor;                // 正常文字颜色
    QColor m_hTextColor;                // 悬停文字颜色
    QColor m_cTextColor;                // 选中文字颜色
    QPen m_textPen;                     // 文字大小、颜色
    //背景
    QBrush m_nBgBrush;                  // 正常背景画刷
    QBrush m_hBgBrush;                  // 悬停背景画刷
    QBrush m_cBgBrush;                  // 选中背景画刷
    QColor m_nBgColor;                  // 正常背景颜色
    QColor m_hBgColor;                  // 悬停背景颜色
    QColor m_cBgColor;                  // 选中背景颜色
    //图标()
    bool m_showIcon;                    // 显示图标
    int m_iconSpace;                    // 图标边距,左边显示图标是距离左边边距,顶部显示图标表示距离顶部边距,以此类推
    QSize m_iconSize;                   // 图标尺寸
    QPixmap m_nIcon;                    // 正常图标
    QPixmap m_hIcon;                    // 悬停图标
    QPixmap m_cIcon;                    // 选中图标
    IconPosition m_iconPos;             // 图标显示位置
    //三角
    bool m_showTriangle;                // 是否显示三角
    int m_triSideLength;                // 三角形边长
    TrianglePosition m_triPos;          // 三角形显示位置
    QColor m_triColor;                  // 三角形显示颜色

总结:如果是可以有的,也可以没有的,增加一个bool来控制是否显示。

状态

1.在设计的导航按钮中使用三种状态:正常、鼠标悬停、鼠标选中。
2.文字颜色在三种状态下颜色不同,需要使用三个颜色变量分别保存三种状态下的颜色值。
3.背景颜色在三种状态下颜色不同,需要使用三个颜色变量分别保存三种状态下的颜色值。
4.继承 enterEvent 和 leaveEvent 事件函数来判断鼠标上划状态。

bool m_hover;                       // 鼠标悬停标志
//不需要选中状态,因为,可以根据QpushButton来获取是否是点击状态

总结:我们只要知道一些布局和行为就可以定出所有的变量出来。

Q_PROPERTY 属性

Q_PROPERTY 是 Qt 中的一个宏,是用类中声明属性。如果需要使用该宏,必须要继承 QObject 类或者其子类。QPushButton 则是 QObject 的间接子类,所以继承 QPushButton 类后同样可以使用 Q_PROPERTY 宏。

Q_PROPERTY 属性自带了一些属性,同样程序可以自定义。本实验中只讲解 Q_PROPERTY 自带的属性。

在自定义导航按钮的程序中同样使用了 Q_PROPERTY,且程序中只使用了 Q_PROPERTY 的 READ 属性和 WRITE 属性。

class JNaviButton : public QPushButton
{
    Q_PROPERTY(int m_paddingLeft READ paddingLeft WRITE setPaddingLeft)
    Q_PROPERTY(int m_paddingTop READ paddingTop WRITE setPaddingTop)
    Q_PROPERTY(int m_paddingRight READ paddingRight WRITE setPaddingRight)
    Q_PROPERTY(int m_paddingBottom READ paddingBottom WRITE setPaddingBottom)
    // ...
}

Q_PROPERTY 自带属性:

Q_PROPERTY(type name
           READ getFunction
           [WRITE setFunction]
           [RESET resetFunction]
           [NOTIFY notifySignal]
           [DESIGNABLE bool]
           [SCRIPTABLE bool]
           [STORED bool]
           [USER bool]
           [CONSTANT]
           [FINAL])

在上面的代码中,方括号 [] 中的内容属性可选。
必选 READ 属性:用来读取属性值,因此使用 const 限制,返回值类型必须为属性类型或者属性类型的引用或者指针。
可选 WRITE 属性:用来设置属性值,返回值必须为 void 类型,需要一个参数。
可选 RESET 属性:能够将值设置为默认状态,返回值为 void 类型且不带参数。
可选 NOTIFY 属性:提供一个信号,当值发送改变是该信号会自动被触发。
可选 DESIGNABLE 属性:是否在界面设计器的属性编辑器中出现。大多数属性是可见的,除了可以为变量传入 true 或 false 还可以执行一个 bool 行的成员函数。
可选 SCRIPTABLE 属性:是够可以被脚本引擎操作(默认为 true)。可以赋予 true 或者 false 或 bool 类型的函数。
可选 STORED 属性:是否被认为是独立存在还是依赖于其他的值而存在,也可以表明是否在保存对象状态时保存此属性的值。大多数属性都是需要保存的,但也有例外,例如 QWidget::minimumWidth() 就是不被保存的,因为它的值是从另一个属性 QWidget::minimumSize() 得来的。
可选 USER 属性:是否被设计为面向用户的或用户可修改的类属性。通常,每个类只有一个 USER 属性。例如 QAbstractButton::checked 是按钮类的用户可修改属性。注意 QItemDelegate 获取和设置 widget 的 USER 属性。
可选 CONSTANT 属性:表示属性的值是不变的。
可选 FINAL 属性:表示属性不能被派生类所重写。

源代码:

.pro

#-------------------------------------------------
#
# Project created by QtCreator 2020-06-30T08:24:07
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 3-1-JNaviButton
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp \
    jnavibutton.cpp

HEADERS  += widget.h \
    jnavibutton.h

FORMS    += widget.ui

RESOURCES += \
    source.qrc

JNaviButton .h

#ifndef JNAVIBUTTON_H
#define JNAVIBUTTON_H

/**
  该导航按钮参考了 feiyangqingyun 的导航按钮类
 */
/** 功能
 * 1. 默认情况下,文字居中显示,不显示图标,不显示三角
 * 2. 可设置文字左侧、顶部、右侧、底部编剧;可设置文字显示对其方式
 * 3. 可设置图标是否显示、一侧边距、图标大小、显示位置
 * 4. 可设置三角是否显示、大小、显示位置,三角只设置了鼠标悬停和鼠标选中状态下显示
 * 5. 可设置北京颜色为画刷颜色
 * 6. 可设置文字与图标的相对位置:图标左文字右、图标右文字左、图标上文字下、图标下文字上
 * 7. 按钮状态分为三种:正常、鼠标悬停、鼠标选中
 * 8. 在按钮不同状态下可设置不同的背景颜色、字体颜色、图标切换、三角颜色等
 * 9. 一组导航按钮一次只能选中一个
 */

#include <QPushButton>
#include <QPainter>

class JNaviButton : public QPushButton
{
    Q_OBJECT
    Q_ENUMS(TextAlign)
    Q_ENUMS(IconPosition)

    Q_PROPERTY(int m_paddingLeft READ paddingLeft WRITE setPaddingLeft)
    Q_PROPERTY(int m_paddingTop READ paddingTop WRITE setPaddingTop)
    Q_PROPERTY(int m_paddingRight READ paddingRight WRITE setPaddingRight)
    Q_PROPERTY(int m_paddingBottom READ paddingBottom WRITE setPaddingBottom)
    Q_PROPERTY(TextAlign m_textAlign READ textAlign WRITE setTextAlign)
    Q_PROPERTY(QColor m_nTextColor READ normalTextColor WRITE setNormalTextColor)
    Q_PROPERTY(QColor m_hTextColor READ hoverTextColor WRITE setHoverTextColor)
    Q_PROPERTY(QColor m_cTextColor READ checkedTextColor WRITE setCheckedTextColor)
    Q_PROPERTY(QPen m_textPen READ textPen WRITE setTextPen)

    Q_PROPERTY(QBrush m_nBgBrush READ normalBgBrush WRITE setNormalBgBrush)
    Q_PROPERTY(QBrush m_hBgBrush READ hoverBgBrush WRITE setHoverBgBrush)
    Q_PROPERTY(QBrush m_cBgBrush READ checkedBgBrush WRITE setCheckedBgBrush)

    Q_PROPERTY(QColor m_nBgColor READ normalBgColor WRITE setNormalBgColor)
    Q_PROPERTY(QColor m_hBgColor READ hoverBgColor WRITE setHoverBgColor)
    Q_PROPERTY(QColor m_cBgColor READ checkedBgColor WRITE setCheckedBgColor)

    Q_PROPERTY(bool m_showIcon READ showIcon WRITE setShowIcon)
    Q_PROPERTY(int  m_iconSpace READ iconSpace WRITE setIconSpace)
    Q_PROPERTY(QSize m_iconSize READ iconSize WRITE setIconSize)
    Q_PROPERTY(QPixmap m_nIcon READ normalIcon WRITE setNormalIcon)
    Q_PROPERTY(QPixmap m_hIcon READ hoverIcon WRITE setHoverIcon)
    Q_PROPERTY(QPixmap m_cIcon READ checkedIcon WRITE setCheckedIcon)
    Q_PROPERTY(IconPosition m_iconPos READ iconPosition WRITE setIconPosition)

    Q_PROPERTY(bool m_showTriangle READ showTriabgle WRITE setShowTriangle)
    Q_PROPERTY(int m_triSideLength READ triangleSideLength WRITE setTriangleSideLength)
    Q_PROPERTY(TrianglePosition m_triPos READ trianglePos WRITE setTrianglePosition)
    Q_PROPERTY(QColor m_triColor READ triangleColor WRITE setTriangleColor)
public:
    explicit JNaviButton(QWidget *parent = 0);

    enum TextAlign {
        TextAlign_Left = 0x0001,        // 左对齐
        TextAlign_Right = 0x0002,       // 右对齐
        TextAlign_Top = 0x0020,         // 顶部对齐
        TextAlign_Bottom = 0x0040,      // 底部对齐
        TextAlign_Center = 0x0004       // 居中对齐
    };

    enum IconPosition {
        IP_Left = 0,                    // 左侧
        IP_Top = 1,                     // 顶部
        IP_Right = 2,                   // 右侧
        IP_Bottom = 3                   // 底部
    };

    enum TrianglePosition {
        TP_Left = 0,                    // 左侧
        TP_Top = 1,                     // 顶部
        TP_Right = 2,                   // 右侧
        TP_Bottom = 3                   // 底部
    };

protected:
    virtual void enterEvent(QEnterEvent *);
    virtual void leaveEvent(QEvent *);
    virtual void paintEvent(QPaintEvent *);

    void drawBackGround(QPainter *painter);
    void drawText(QPainter *painter);
    void drawIcon(QPainter *painter);
    void drawTriangle(QPainter *painter);

private:
    bool m_hover;                       // 鼠标悬停标志

    int m_paddingLeft;                  // 文字左侧间距
    int m_paddingTop;                   // 文字顶部间距
    int m_paddingRight;                 // 文字右侧间距
    int m_paddingBottom;                // 文字底部间距
    TextAlign m_textAlign;              // 文字对齐方式
    QColor m_nTextColor;                // 正常文字颜色
    QColor m_hTextColor;                // 悬停文字颜色
    QColor m_cTextColor;                // 选中文字颜色
    QPen m_textPen;                     // 文字大小、颜色

    QBrush m_nBgBrush;                  // 正常背景画刷
    QBrush m_hBgBrush;                  // 悬停背景画刷
    QBrush m_cBgBrush;                  // 选中背景画刷

    QColor m_nBgColor;                  // 正常背景颜色
    QColor m_hBgColor;                  // 悬停背景颜色
    QColor m_cBgColor;                  // 选中背景颜色

    bool m_showIcon;                    // 显示图标
    int m_iconSpace;                    // 图标边距,左边显示图标是距离左边边距,顶部显示图标表示距离顶部边距,以此类推
    QSize m_iconSize;                   // 图标尺寸
    QPixmap m_nIcon;                    // 正常图标
    QPixmap m_hIcon;                    // 悬停图标
    QPixmap m_cIcon;                    // 选中图标
    IconPosition m_iconPos;             // 图标显示位置

    bool m_showTriangle;                // 是否显示三角
    int m_triSideLength;                // 三角形边长
    TrianglePosition m_triPos;          // 三角形显示位置
    QColor m_triColor;                  // 三角形显示颜色

public:
    int paddingLeft() const;
    int paddingTop() const;
    int paddingRight() const;
    int paddingBottom() const;
    TextAlign textAlign() const;
    QColor normalTextColor() const;
    QColor hoverTextColor() const;
    QColor checkedTextColor() const;
    QPen textPen() const;

    QBrush normalBgBrush() const;
    QBrush hoverBgBrush() const;
    QBrush checkedBgBrush() const;

    QColor normalBgColor() const;
    QColor hoverBgColor() const;
    QColor checkedBgColor() const;

    bool showIcon() const;
    int iconSpace() const;
    QSize iconSize() const;
    QPixmap normalIcon() const;
    QPixmap hoverIcon() const;
    QPixmap checkedIcon() const;
    IconPosition iconPosition() const;

    bool showTriabgle() const;
    int triangleSideLength() const;
    TrianglePosition trianglePos() const;
    QColor triangleColor() const;

    QSize sizeHint() const;
    QSize minimumSizeHint() const;

public Q_SLOTS:
    void setPaddingLeft(int padding);
    void setPaddingTop(int padding);
    void setPaddingRight(int padding);
    void setPaddingBottom(int padding);
    void setTextAlign(TextAlign align);
    void setNormalTextColor(const QColor &c);
    void setHoverTextColor(const QColor &c);
    void setCheckedTextColor(const QColor &c);
    void setTextPen(const QPen &pen);

    void setNormalBgBrush(const QBrush &b);
    void setHoverBgBrush(const QBrush &b);
    void setCheckedBgBrush(const QBrush &b);

    void setNormalBgColor(const QColor &c);
    void setHoverBgColor(const QColor &c);
    void setCheckedBgColor(const QColor &c);

    void setShowIcon(bool visible);
    void setIconSpace(int space);
    void setIconSize(int w, int h);
    void setIconSize(const QSize &size);
    void setNormalIcon(const QPixmap &nIcon);
    void setHoverIcon(const QPixmap &hIcon);
    void setCheckedIcon(const QPixmap &cIcon);
    void setIconPosition(IconPosition pos);

    void setShowTriangle(bool visiable);
    void setTriangleSideLength(int len);
    void setTrianglePosition(TrianglePosition pos);
    void setTriangleColor(const QColor &c);
};

#endif // JNAVIBUTTON_H

JNaviButton.cpp

#include "jnavibutton.h"
#include <QDebug>


JNaviButton::JNaviButton(QWidget *parent)
    : QPushButton(parent)
    , m_hover(false)
    , m_paddingLeft(6)
    , m_paddingTop(2)
    , m_paddingRight(6)
    , m_paddingBottom(2)
    , m_textAlign(TextAlign_Center)
    , m_nTextColor(QColor(138, 43, 226))
    , m_hTextColor(QColor(255, 255, 255))
    , m_cTextColor(QColor(139, 69, 19))
    , m_nBgBrush(Qt::NoBrush)
    , m_hBgBrush(Qt::NoBrush)
    , m_cBgBrush(Qt::NoBrush)
    , m_nBgColor(QColor(205, 197, 191))
    , m_hBgColor(QColor(90, 165, 238))
    , m_cBgColor(QColor(173, 216, 234))
    , m_showIcon(false)
    , m_iconSpace(6)
    , m_iconSize(QSize(16, 16))
    , m_nIcon(QPixmap())
    , m_hIcon(QPixmap())
    , m_cIcon(QPixmap())
    , m_iconPos(IP_Left)
    , m_showTriangle(false)
    , m_triSideLength(5)
    , m_triPos(TP_Right)
    , m_triColor(QColor(255, 255, 255))
{
    // 设置按钮为可被选中
    setCheckable(true);
    // 一组按钮一次只能 选中一个
    setAutoExclusive(true);
}

void JNaviButton::enterEvent(QEnterEvent *e)
{
    Q_UNUSED(e)
    m_hover = true;
}

void JNaviButton::leaveEvent(QEvent *e)
{
    Q_UNUSED(e)
    m_hover = false;
}

void JNaviButton::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e)
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    // 绘制背景
    drawBackGround(&painter);
    // 绘制文字
    drawText(&painter);
    // 绘制图标
    drawIcon(&painter);
    // 绘制三角
    drawTriangle(&painter);
}

void JNaviButton::drawBackGround(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    QBrush brush;
    if(isChecked()) {
        brush = m_cBgBrush;
    }
    else if(m_hover) {
        brush = m_hBgBrush;
    }
    else {
        brush = m_nBgBrush;
    }

    if(brush != Qt::NoBrush) {
        painter->setBrush(brush);
    }
    else {
        QColor color;
        if(isChecked()) {
            color = m_cBgColor;
        }
        else if(m_hover) {
            color = m_hBgColor;
        }
        else {
            color = m_nBgColor;
        }
        painter->setBrush(color);
    }

    QRect rect = QRect(0, 0, width(), height());
    painter->drawRect(rect);

    painter->restore();
}

void JNaviButton::drawText(QPainter *painter)
{
    painter->save();
    painter->setBrush(Qt::NoBrush);

    QColor color;
    if(isChecked()) {
        color = m_cTextColor;
    }
    else if(m_hover) {
        color = m_hTextColor;
    }
    else {
        color = m_nTextColor;
    }

    QRect rect = QRect(m_paddingLeft, m_paddingTop,
                       width() - m_paddingLeft - m_paddingRight,
                       height() - m_paddingTop - m_paddingBottom);
    m_textPen.setColor(color);
    painter->setPen(m_textPen);
    painter->drawText(rect, Qt::AlignVCenter | m_textAlign, text());
    painter->restore();
}

void JNaviButton::drawIcon(QPainter *painter)
{
    if(!m_showIcon) {
        return;
    }
    painter->save();
    QPixmap icon;
    if(isChecked()) {
        icon = m_cIcon;
    }
    else if(m_hover) {
        icon = m_hIcon;
    }
    else {
        icon = m_nIcon;
    }
    if(!icon.isNull()) {
        icon = icon.scaled(m_iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        if(IP_Left == m_iconPos) {
            painter->drawPixmap(m_iconSpace, (height() - m_iconSize.height()) / 2, icon);
        }
        else if(IP_Top == m_iconPos) {
            painter->drawPixmap((width() - m_iconSize.width()) / 2, m_iconSpace, icon);
        }
        else if(IP_Right == m_iconPos) {
            painter->drawPixmap(width() - m_iconSize.width() - m_iconSpace,
                                (height() - m_iconSize.height()) / 2, icon);
        }
        else if(IP_Bottom == m_iconPos) {
            painter->drawPixmap((width() - m_iconSize.width()) / 2,
                                height() - m_iconSize.height() - m_iconSpace, icon);
        }
    }

    painter->restore();
}

void JNaviButton::drawTriangle(QPainter *painter)
{
    if(!m_showTriangle) {
        return;
    }
    if(!m_hover && !isChecked()) {
        return;
    }
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(m_triColor);
    QPolygon pts;
    if(TP_Left == m_triPos) {
        pts.setPoints(3, m_triSideLength, height() / 2,
                      0, height() / 2 - m_triSideLength,
                      0, height() / 2 + m_triSideLength);
    }
    else if(TP_Top == m_triPos) {
        pts.setPoints(3, width() / 2, m_triSideLength,
                      width() / 2 - m_triSideLength, 0,
                      width() / 2 + m_triSideLength, 0);
    }
    else if(TP_Right == m_triPos) {
        pts.setPoints(3, width() - m_triSideLength, height() / 2,
                      width(), height() / 2 - m_triSideLength,
                      width(), height() / 2 + m_triSideLength);
    }
    else if(TP_Bottom == m_triPos) {
        pts.setPoints(3, width() / 2, height() - m_triSideLength,
                      width() / 2 - m_triSideLength, height(),
                      width() / 2 + m_triSideLength, height());
    }
    painter->drawPolygon(pts);

    painter->restore();
}

int JNaviButton::paddingLeft() const
{
    return m_paddingLeft;
}

int JNaviButton::paddingTop() const
{
    return m_paddingTop;
}

int JNaviButton::paddingRight() const
{
    return m_paddingRight;
}

int JNaviButton::paddingBottom() const
{
    return m_paddingBottom;
}

JNaviButton::TextAlign JNaviButton::textAlign() const
{
    return m_textAlign;
}

QColor JNaviButton::normalTextColor() const
{
    return m_nTextColor;
}

QColor JNaviButton::hoverTextColor() const
{
    return m_hTextColor;
}

QColor JNaviButton::checkedTextColor() const
{
    return m_cTextColor;
}

QPen JNaviButton::textPen() const
{
    return m_textPen;
}

QBrush JNaviButton::normalBgBrush() const
{
    return m_nBgBrush;
}

QBrush JNaviButton::hoverBgBrush() const
{
    return m_hBgBrush;
}

QBrush JNaviButton::checkedBgBrush() const
{
    return m_cBgBrush;
}

QColor JNaviButton::normalBgColor() const
{
    return m_nBgColor;
}

QColor JNaviButton::hoverBgColor() const
{
    return m_hBgColor;
}

QColor JNaviButton::checkedBgColor() const
{
    return m_cBgColor;
}

bool JNaviButton::showIcon() const
{
    return m_showIcon;
}

int JNaviButton::iconSpace() const
{
    return m_iconSpace;
}

QSize JNaviButton::iconSize() const
{
    return m_iconSize;
}

QPixmap JNaviButton::normalIcon() const
{
    return m_nIcon;
}

QPixmap JNaviButton::hoverIcon() const
{
    return m_hIcon;
}

QPixmap JNaviButton::checkedIcon() const
{
    return m_cIcon;
}

JNaviButton::IconPosition JNaviButton::iconPosition() const
{
    return m_iconPos;
}

bool JNaviButton::showTriabgle() const
{
    return m_showTriangle;
}

int JNaviButton::triangleSideLength() const
{
    return m_triSideLength;
}

JNaviButton::TrianglePosition JNaviButton::trianglePos() const
{
    return m_triPos;
}

QColor JNaviButton::triangleColor() const
{
    return m_triColor;
}

QSize JNaviButton::sizeHint() const
{
    return QSize(100, 30);
}

QSize JNaviButton::minimumSizeHint() const
{
    return QSize(20, 10);
}

void JNaviButton::setPaddingLeft(int padding)
{
    if(m_paddingLeft != padding) {
        m_paddingLeft = padding;
        update();
    }
}

void JNaviButton::setPaddingTop(int padding)
{
    if(m_paddingTop != padding) {
        m_paddingTop = padding;
        update();
    }
}

void JNaviButton::setPaddingRight(int padding)
{
    if(m_paddingRight != padding) {
        m_paddingRight = padding;
        update();
    }
}

void JNaviButton::setPaddingBottom(int padding)
{
    if(m_paddingBottom != padding) {
        m_paddingBottom = padding;
        update();
    }
}

void JNaviButton::setTextAlign(TextAlign align)
{
    if(m_textAlign != align) {
        m_textAlign = align;
        update();
    }
}

void JNaviButton::setNormalTextColor(const QColor &c)
{
    if(m_nTextColor != c) {
        m_nTextColor = c;
        update();
    }
}

void JNaviButton::setHoverTextColor(const QColor &c)
{
    if(m_hTextColor != c) {
        m_hTextColor = c;
        update();
    }
}

void JNaviButton::setCheckedTextColor(const QColor &c)
{
    if(m_cTextColor != c) {
        m_cTextColor = c;
        update();
    }
}

void JNaviButton::setTextPen(const QPen &pen)
{
    if(m_textPen != pen) {
        m_textPen = pen;
        update();
    }
}

void JNaviButton::setNormalBgBrush(const QBrush &b)
{
    if(m_nBgBrush != b) {
        m_nBgBrush = b;
        update();
    }
}

void JNaviButton::setHoverBgBrush(const QBrush &b)
{
    if(m_hBgBrush != b) {
        m_hBgBrush = b;
        update();
    }
}

void JNaviButton::setCheckedBgBrush(const QBrush &b)
{
    if(m_cBgBrush != b) {
        m_cBgBrush = b;
        update();
    }
}

void JNaviButton::setNormalBgColor(const QColor &c)
{
    if(m_nTextColor != c) {
        m_nBgColor = c;
        update();
    }
}

void JNaviButton::setHoverBgColor(const QColor &c)
{
    if(m_hTextColor != c) {
        m_hBgColor = c;
        update();
    }
}

void JNaviButton::setCheckedBgColor(const QColor &c)
{
    if(m_cTextColor != c) {
        m_cBgColor = c;
        update();
    }
}

void JNaviButton::setShowIcon(bool visible)
{
    if(m_showIcon != visible) {
        m_showIcon = visible;
        update();
    }
}

void JNaviButton::setIconSpace(int space)
{
    if(m_iconSpace != space) {
        m_iconSpace = space;
        update();
    }
}

void JNaviButton::setIconSize(int w, int h)
{
    setIconSize(QSize(w, h));
}

void JNaviButton::setIconSize(const QSize &size)
{
    if(m_iconSize != size) {
        m_iconSize = size;
        update();
    }
}

void JNaviButton::setNormalIcon(const QPixmap &nIcon)
{
    if(nIcon.isNull())
        return;
    m_nIcon = nIcon;
    update();
}

void JNaviButton::setHoverIcon(const QPixmap &hIcon)
{
    if(hIcon.isNull())
        return;
    m_hIcon = hIcon;
    update();
}

void JNaviButton::setCheckedIcon(const QPixmap &cIcon)
{
    if(cIcon.isNull())
        return;
    m_cIcon = cIcon;
    update();
}

void JNaviButton::setIconPosition(IconPosition pos)
{
    if(m_iconPos != pos) {
        m_iconPos = pos;
        update();
    }
}

void JNaviButton::setShowTriangle(bool visiable)
{
    if(m_showTriangle != visiable) {
        m_showTriangle = visiable;
        update();
    }
}

void JNaviButton::setTriangleSideLength(int len)
{
    if(m_triSideLength != len) {
        m_triSideLength = len;
        update();
    }
}

void JNaviButton::setTrianglePosition(JNaviButton::TrianglePosition pos)
{
    if(m_triPos != pos) {
        m_triPos = pos;
        update();
    }
}

void JNaviButton::setTriangleColor(const QColor &c)
{
    if(m_triColor != c) {
        m_triColor = c;
        update();
    }
}

Widget .h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "jnavibutton.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

Q_SIGNALS:
    void custom_signal(const QString &msg);

public slots:
    void btns1_clicked();
    void btns2_clicked();
    void btns3_clicked();
    void btns4_clicked();
    void btns5_clicked();
    void btns6_clicked();
    void custom_slot(const QString &msg);

private:
    Ui::Widget *ui;

    QVector<JNaviButton*> btns1;
    QVector<JNaviButton*> btns2;
    QVector<JNaviButton*> btns3;
    QVector<JNaviButton*> btns4;
    QVector<JNaviButton*> btns5;
    QVector<JNaviButton*> btns6;
};

#endif // WIDGET_H

Widget .cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    connect(this, &Widget::custom_signal, this, &Widget::custom_slot);

    btns1 << ui->pushButton << ui->pushButton_2 << ui->pushButton_3 <<
             ui->pushButton_4 << ui->pushButton_5;
    ui->pushButton->setChecked(true);
    for(int i = 0; i < btns1.size(); i++) {
        connect(btns1.at(i), &JNaviButton::clicked, this, &Widget::btns1_clicked);
        btns1.at(i)->setShowIcon(true);
        btns1.at(i)->setNormalIcon(QPixmap(":/image/image/right.png"));
        btns1.at(i)->setHoverIcon(QPixmap(":/image/image/right-hover.png"));
        btns1.at(i)->setCheckedIcon(QPixmap(":/image/image/right-pressed.png"));
        btns1.at(i)->setStyleSheet("JNaviButton{font-size:14px;}");
    }


    btns2 << ui->pushButton_6 << ui->pushButton_7 <<
             ui->pushButton_8 << ui->pushButton_9;
    ui->pushButton_6->setChecked(true);
    for(int i = 0; i < btns2.size(); i++) {
        btns2.at(i)->setMinimumHeight(40);
        btns2.at(i)->setShowIcon(true);
        btns2.at(i)->setNormalBgColor(QColor(50, 56, 82));
        btns2.at(i)->setHoverBgColor(QColor(30, 40, 50));
        btns2.at(i)->setCheckedBgColor(QColor(10, 20, 30));
        btns2.at(i)->setNormalTextColor(QColor(210, 210, 215));
        btns2.at(i)->setHoverTextColor(QColor(255, 255, 255));
        btns2.at(i)->setCheckedTextColor(QColor(255, 255, 255));
        btns2.at(i)->setStyleSheet("JNaviButton{font-size:14px;}");
    }
    ui->pushButton_6->setNormalIcon(QPixmap(":/image/image/home.png"));
    ui->pushButton_6->setHoverIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_6->setCheckedIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_7->setNormalIcon(QPixmap(":/image/image/group.png"));
    ui->pushButton_7->setHoverIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_7->setCheckedIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_8->setNormalIcon(QPixmap(":/image/image/works.png"));
    ui->pushButton_8->setHoverIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_8->setCheckedIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_9->setNormalIcon(QPixmap(":/image/image/help.png"));
    ui->pushButton_9->setHoverIcon(QPixmap(":/image/image/help-hover.png"));
    ui->pushButton_9->setCheckedIcon(QPixmap(":/image/image/help-hover.png"));


    btns3 << ui->pushButton_10 << ui->pushButton_11 <<
             ui->pushButton_12 << ui->pushButton_13;
    ui->pushButton_10->setChecked(true);
    for(int i = 0; i < btns3.size(); i++) {
        btns3.at(i)->setShowIcon(true);

        btns3.at(i)->setMinimumHeight(60);
        btns3.at(i)->setIconSize(30, 30);
        btns3.at(i)->setIconPosition(JNaviButton::IP_Top);
        btns3.at(i)->setPaddingTop(35);

        btns3.at(i)->setNormalBgColor(QColor(50, 56, 82));
        btns3.at(i)->setHoverBgColor(QColor(30, 40, 50));
        btns3.at(i)->setCheckedBgColor(QColor(30, 30, 30));
        btns3.at(i)->setNormalTextColor(QColor(210, 210, 215));
        btns3.at(i)->setHoverTextColor(QColor(255, 255, 255));
        btns3.at(i)->setCheckedTextColor(QColor(255, 255, 255));
        btns3.at(i)->setStyleSheet("JNaviButton{font-size:12px;}");
    }
    ui->pushButton_10->setNormalIcon(QPixmap(":/image/image/home.png"));
    ui->pushButton_10->setHoverIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_10->setCheckedIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_11->setNormalIcon(QPixmap(":/image/image/group.png"));
    ui->pushButton_11->setHoverIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_11->setCheckedIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_12->setNormalIcon(QPixmap(":/image/image/works.png"));
    ui->pushButton_12->setHoverIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_12->setCheckedIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_13->setNormalIcon(QPixmap(":/image/image/help.png"));
    ui->pushButton_13->setHoverIcon(QPixmap(":/image/image/help-hover.png"));
    ui->pushButton_13->setCheckedIcon(QPixmap(":/image/image/help-hover.png"));


    btns4 << ui->pushButton_14 << ui->pushButton_15 << ui->pushButton_16 <<
             ui->pushButton_17 << ui->pushButton_18;
    ui->pushButton_14->setChecked(true);
    for(int i = 0; i < btns4.size(); i++) {

        btns4.at(i)->setNormalBgColor(QColor(45, 145, 145));
        btns4.at(i)->setHoverBgColor(QColor(24, 114, 148));
        btns4.at(i)->setCheckedBgColor(QColor(20, 92, 117));
        btns4.at(i)->setNormalTextColor(QColor(230, 230, 235));
        btns4.at(i)->setHoverTextColor(QColor(255, 255, 255));
        btns4.at(i)->setCheckedTextColor(QColor(255, 255, 255));

        btns4.at(i)->setShowIcon(true);
        btns4.at(i)->setNormalIcon(QPixmap(":/image/image/right-hover.png"));
        btns4.at(i)->setHoverIcon(QPixmap(":/image/image/right-hover.png"));
        btns4.at(i)->setCheckedIcon(QPixmap(":/image/image/right-pressed.png"));
        btns4.at(i)->setStyleSheet("JNaviButton{font-size:12px;}");

        btns4.at(i)->setShowTriangle(true);
    }


    btns5 << ui->pushButton_19 << ui->pushButton_20 <<
             ui->pushButton_21 << ui->pushButton_22;
    ui->pushButton_19->setChecked(true);
    for(int i = 0; i < btns5.size(); i++) {
        btns5.at(i)->setMinimumHeight(40);
        btns5.at(i)->setShowIcon(true);
        btns5.at(i)->setNormalBgColor(QColor(50, 56, 82));
        btns5.at(i)->setHoverBgColor(QColor(30, 40, 50));
        btns5.at(i)->setCheckedBgColor(QColor(10, 20, 30));
        btns5.at(i)->setNormalTextColor(QColor(210, 210, 215));
        btns5.at(i)->setHoverTextColor(QColor(255, 255, 255));
        btns5.at(i)->setCheckedTextColor(QColor(255, 255, 255));
        btns5.at(i)->setStyleSheet("JNaviButton{font-size:14px;}");

        btns5.at(i)->setShowTriangle(true);
        btns5.at(i)->setTrianglePosition(JNaviButton::TP_Bottom);
    }
    ui->pushButton_19->setNormalIcon(QPixmap(":/image/image/home.png"));
    ui->pushButton_19->setHoverIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_19->setCheckedIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_20->setNormalIcon(QPixmap(":/image/image/group.png"));
    ui->pushButton_20->setHoverIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_20->setCheckedIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_21->setNormalIcon(QPixmap(":/image/image/works.png"));
    ui->pushButton_21->setHoverIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_21->setCheckedIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_22->setNormalIcon(QPixmap(":/image/image/help.png"));
    ui->pushButton_22->setHoverIcon(QPixmap(":/image/image/help-hover.png"));
    ui->pushButton_22->setCheckedIcon(QPixmap(":/image/image/help-hover.png"));


    btns6 << ui->pushButton_23 << ui->pushButton_24 <<
             ui->pushButton_25 << ui->pushButton_26;
    ui->pushButton_23->setChecked(true);
    for(int i = 0; i < btns6.size(); i++) {
        btns6.at(i)->setShowIcon(true);

        btns6.at(i)->setMinimumHeight(45);
        btns6.at(i)->setIconSize(30, 30);
        btns6.at(i)->setIconPosition(JNaviButton::IP_Top);

        btns6.at(i)->setNormalBgColor(QColor(50, 56, 82));
        btns6.at(i)->setHoverBgColor(QColor(30, 40, 50));
        btns6.at(i)->setCheckedBgColor(QColor(30, 30, 30));

        btns6.at(i)->setShowTriangle(true);
        btns6.at(i)->setTrianglePosition(JNaviButton::TP_Bottom);
    }
    ui->pushButton_23->setToolTip(tr("首页"));
    ui->pushButton_24->setToolTip(tr("论坛"));
    ui->pushButton_25->setToolTip(tr("作品"));
    ui->pushButton_26->setToolTip(tr("帮助"));
    ui->pushButton_23->setNormalIcon(QPixmap(":/image/image/home.png"));
    ui->pushButton_23->setHoverIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_23->setCheckedIcon(QPixmap(":/image/image/home-hover.png"));
    ui->pushButton_24->setNormalIcon(QPixmap(":/image/image/group.png"));
    ui->pushButton_24->setHoverIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_24->setCheckedIcon(QPixmap(":/image/image/group-hover.png"));
    ui->pushButton_25->setNormalIcon(QPixmap(":/image/image/works.png"));
    ui->pushButton_25->setHoverIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_25->setCheckedIcon(QPixmap(":/image/image/works-hover.png"));
    ui->pushButton_26->setNormalIcon(QPixmap(":/image/image/help.png"));
    ui->pushButton_26->setHoverIcon(QPixmap(":/image/image/help-hover.png"));
    ui->pushButton_26->setCheckedIcon(QPixmap(":/image/image/help-hover.png"));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::btns1_clicked()
{
    JNaviButton *btn = dynamic_cast<JNaviButton*>(sender());
//    QMessageBox::information(this, "btns1", btn->text());
    emit custom_signal(btn->text());
}

void Widget::btns2_clicked()
{

}

void Widget::btns3_clicked()
{

}

void Widget::btns4_clicked()
{

}

void Widget::btns5_clicked()
{

}

void Widget::btns6_clicked()
{

}

void Widget::custom_slot(const QString &msg)
{
    QMessageBox::information(this, "info", msg);
}

.ui

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1203257.html

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

相关文章

k8s系列文章二:集群配置

一、关闭交换分区 # 临时关闭分区 swapoff -a # 永久\关闭自动挂载swap分区 sudo sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab 二、修改cgroup管理器 ubuntu 系统&#xff0c;debian 系统&#xff0c;centos7 系统&#xff0c;都是使用 systemd 初始化系统的。systemd 这边…

行业追踪,2023-11-13

自动复盘 2023-11-13 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

CSRF 漏洞详解

CSRF 漏洞详解 漏洞描述 CSRF&#xff08;Cross-Site Request Forgery&#xff09;漏洞是一种Web应用程序安全漏洞&#xff0c;它允许攻击者利用受害者的已认证会话来执行未经授权的恶意操作。攻击者可以诱使受害者在受害者已经登录的情况下&#xff0c;通过社交工程或其他方…

前端中 JS 发起的请求可以暂停吗?

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 这个问题非常有意思&#xff0c;我一看到就想了很多可以回复的答案&#xff0c;但是评论区太窄&#xff0c;就直接开…

MTK手机平台充电原理

EPT GPIO初始化文件 bsp_gpio_ept_config.c 1 知识点总结 1.1 Official 参考充电电路 Figure 1-1 参考电路 VCHG&#xff1a;USB正极 VCDT&#xff1a;VCHG Charger Detect充电电压检测脚 ISENSE&#xff1a;充电电流检测电阻的正极 BATSNS&#xff1a;充电电流检测电阻的负极 …

VMware配置NAT模式网络

一、选择VMWare的NAT模式。 1&#xff09;导航栏“编辑”->“虚拟网络编辑器” ->NAT模式->NAT设置 记住NAT设置中的子网IP、子网掩码、网关IP三项&#xff0c;接下来配置文件主要是这三项。 嗯&#xff0c;这里记得按确定&#xff0c;我之前没有按确定写好配置后还…

c++-哈希

文章目录 前言一、unordered系列关联式容器1、unordered_map2、性能测试 二、哈希1、哈希概念2、哈希冲突3、哈希冲突解决3.1 闭散列3.2 开散列3.3 字符串Hash函数3.4 哈希桶实现的哈希表的效率 三、哈希表封装unordered_map和unordered_set容器1、unordered_map和unordered_se…

【PG】PostgreSQL 预写日志(WAL)、checkpoint、LSN

目录 预写式日志&#xff08;WAL&#xff09; WAL概念 WAL的作用 WAL日志存放路径 WAL日志文件数量 WAL日志文件存储形式 WAL日志文件命名 WAL内容 检查点&#xff08;checkpoint&#xff09; 1 检查点概念 2 检查点作用 触发检查点 触发检查点之后数据库操作 设置合…

擎创动态 | 再获上海区政府肯定,擎创科技被评为年度优秀高新技术企业

11月6日&#xff0c;上海市静安区副区长张慧和市北高新集团总裁陈军一行来到擎创科技调研指导&#xff0c;由擎创科技高管张健和陈莹陪同交流。 陈莹女士首先向副区长一行详细介绍了擎创科技的发展现状、落地实践效益以及未来的规划布局。在公司的成长过程中&#xff0c;得到静…

安卓现代化开发系列——从状态保存到SavedState

由于安卓已经诞生快二十载&#xff0c;其最初的开发思想与现代的开发思想已经大相径庭&#xff0c;特别是Jetpack库诞生之后&#xff0c;项目中存在着新老思想混杂的情况&#xff0c;让许多的新手老手都措手不及&#xff0c;项目大步向屎山迈进。为了解决这个问题&#xff0c;开…

linux时间同步

搭建集群时&#xff0c;都会先设置时间同步&#xff0c;否则会出现多种问题。 方式一&#xff1a; 1.安装ntp软件 yum install -y ntp 2.更新时区 删除原有时区&#xff1a;sudo rm -f /etc/localtime 加载新时区&#xff1a;sudo ln -s /usr/share/zoneinfo/Asia/Shangh…

杂乱知识点记录

杂乱知识点记录 1 目标检测评估指标2 visual grounding3 分割4 VLM经典框架5 RCNN系列RCNNFast RCNNFaster RCNNMask RCNN 6 GIOU7 DETR系列DETRDeformable DETRDAB-DETRDN-DETRDINO 8 COCO20149 COCO评价指标 maxDets[1,10,100]10 FCOS&#xff1a;anchor-free11 ATSS 1 目标检…

公司让我开发一个管理系统,有了它,So easy!

目录 一、前言 二、低代码如何快速开发&#xff1f; 1.可视化开发 2.预构建的组件和模板 3.集成的开发和测试工具 4.跨平台兼容性 5.可伸缩性和可扩展性 三、前后端分离的开发框架 技术架构 一、前言 长期以来&#xff0c;常规软件开发是一项艰苦而详尽的工作。开发人员编写代表…

CMT2300A超低功耗127-1020MHz Sub-1GHz全频段SUB-1G 射频收发芯片

CMT2300A超低功耗127-1020MHz Sub-1GHz全频段SUB-1G 射频收发芯片 Sub-1GHz&#xff0c;是指小于1GHz频率的统称。Sub-1GHz无线电频段应用的主要特点&#xff1a;&#xff08;1&#xff09;频率较低波长较长&#xff0c;传输距离远&#xff0c;穿透性强&#xff1b;&#xff0…

阿里云国际站:专有网络vpc

文章目录 一、阿里云专有网络的概念 二、专有网络的组成部分 三、专有网络的优势 一、阿里云专有网络的概念 专有网络VPC是阿里云用户在云上创建的私有网络&#xff0c;用户自己掌控&#xff0c;可以自定义IP地址段、创建交换机、配置路由表和网关等操作。用户可以在自己的专…

假冒 Skype 应用程序网络钓鱼分析

参考链接: https://slowmist.medium.com/fake-skype-app-phishing-analysis-35c1dc8bc515 背景 在Web3世界中&#xff0c;涉及假冒应用程序的网络钓鱼事件相当频繁。慢雾安全团队此前曾发表过分析此类网络钓鱼案例的文章。由于Google Play在中国无法访问&#xff0c;许多用户…

个推「数据驱动运营增长」上海专场:携程智行火车票分享OTA行业的智能用户运营实践

近日&#xff0c;以“数据增能&#xff0c;高效提升用户运营价值”为主题的个推「数据驱动运营增长」城市巡回沙龙上海专场圆满举行。携程智行火车票用户运营负责人王银笛分享OTA行业的智能用户运营实践。 ▲ 王银笛 携程智行火车票用户运营负责人 负责智行业务线用户运营。从0…

竞赛 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现

文章目录 0 前言1 项目背景2 算法架构3 FP-Growth算法原理3.1 FP树3.2 算法过程3.3 算法实现3.3.1 构建FP树 3.4 从FP树中挖掘频繁项集 4 系统设计展示5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于FP-Growth的新闻挖掘算法系统的设计与实现…

短剧软件APP开发方案

一、项目概述 短剧软件APP是一款集创作、拍摄、观看短剧于一体的移动应用。用户可以随时随地创作自己的短剧&#xff0c;也可以观看其他用户创作的短剧。本方案将详细介绍短剧软件APP的开发流程。 二、需求分析 在开发短剧软件APP之前&#xff0c;需要进行详细的需求分析。通…