Qt 环境下做的小滑块组件

Qt下实现在里面添加键值对的两个值,设置其显示模式,使其动态滑动出来

详细功能看代码!

kinfocube.h

/*************************************************===========================================================================
* 模块名称:信息块  KInfoCube
* 功能说明:滑动显示信息模块,具有水平显示和垂直显示模式
* ---------------------------------------------------------------------------
* 修改日期       姓名         内容
* ---------------------------------------------------------------------------
* 2014-10-25    冷光跃        初始版本
*
******************************************************************************/
#ifndef KINFOCUBE_H
#define KINFOCUBE_H

#include <QWidget>
#include <QFrame>
#include <QPushButton>
#include <QLabel>
#include <QParallelAnimationGroup>

class  KInfoCube : public QFrame
{
    Q_OBJECT
public:

    /* 枚举变量:定义框架显示模式 */
    enum FrameDisplayModel
    {
        Horizontal, //框架水平显示
        Vertical    //框架垂直显示
    };

    /* 枚举变量:定义文字显示模式 */
    enum TextDisplayModel
    {
        OneLine,    //在一行中显示
        TwoLine     //在两行中显示
    };

    /*
        构造函数,初始化
     @param
        model   显示模式
        parent  父窗口
    */
    explicit KInfoCube(QWidget *parent = 0, FrameDisplayModel frameModel = Horizontal, TextDisplayModel textModel = TwoLine);

    /*
        析构函数,释放没有指明父窗口的元件
     */
    ~KInfoCube();

    /*
        添加元素,更新已存在的元素
     @param
        sKey   键
        sVlue  值
     */
    void addItem(const QString& sKey,const QString& sVlue);

    /*
        添加元素,更新已存在的元素
     @param
        pair   存储QPair<QString,QString>类型的键值对
     */
    void addItem(QPair<QString,QString> pair);

    /*
        添加元素,更新已存在的元素
     @param
        list   存储QList<QPair<QString,QString>>类型的键值对
     */
    void addItem(QList<QPair<QString,QString>> list);

    /*
        清除所有元素
     */
    void clear();

    /*
        设置左边距
     @param
        value   值
     */
    void setLeftMargin(const int value);

    /*
        设置右边距
     @param
        value   值
     */
    void setRightMargin(const int value);

    /*
        设置上边距
     @param
        value   值
     */
    void setTopMargin(const int value);

    /*
        设置下边距
     @param
        value   值
     */
    void setBottomMargin(const int value);

    /*
        设置元素的宽,框架显示模式为水平时有效
     @param
        value   值
     */
    void setItemWidth(const int value);

    /*
       设置元素的高,框架显示模式为垂直时有效
     @param
        value   值
     */
    void setItemHeight(const int value);

    /*
        设置元素之间的间隔
     @param
        value   值
     */
    void setItemSpacing(const int value);

    /*
        设置按钮的宽
     @param
        value   值
     */
    void setButtonSize(const int value);

    /*
        设置按钮的样式
     @param
        styleSheet   string类型的样式值
     */
    void setBtnStyleSheet(const QString& styleSheet = "background-color: rgb(255, 0, 127)");

    /*
        设置框架显示模式
     @param
        frameModel   FrameDisplayModel的枚举类型
     */
    void setFrameDisplayModel(FrameDisplayModel frameModel);

    /*
        设置问子显示模式
     @param
        textModel   TextDisplayModel的枚举类型
     */
    void setTextDisplayModel(TextDisplayModel textModel);

    /*
        开始更新
     */
    void beginUpdate();

    /*
        结束更新
     */
    void endUpdate();

    /*
        设置文字显示模式
     @param
        aligin   对齐方式
     */
    void setTextAligin(Qt::Alignment aligin);

    /*
        设置文字的分隔符
     @param
        sSeparator   分隔符
     */
    void setTextSeparator(const QString& sSeparator);

protected:

    /* 枚举变量:定义元素移动方向 */
    enum Direction
    {
        Up,     //
        Down,   //
        Left,   //
        Right   //
    };

    void initValue();                       // 初始化值
    void creatFrame();                      // 创建框架
    void connectSignalSlot();               // 连接信号和曹
    void frameLayout();                     // 为框架布局
    void changeSize();                      // 改变框架大小
    int findItem(const QString& sKey);      // 查找元素,找到返回元素所在的位置,否则返回-1
    void creatItemLabel();                  // 为每个元素创建label
    bool isCreateItemLabel();               // 是否已经为元素创建了label,是返回true,不是返回false
    void showItem(int nPosition);           // 显示nPosition开始之后的所有元素
    void moveItem(Direction eDirecttion);   // 根据eDirecttion的值移动元素的位置
    void updateButtonState();               // 更新按钮状态,根据元素的多少显示对应按钮,方便查看
    void clearItemLabel();                  // 清除所有元素
    void layoutControl();                   // 重新调整控件
    int getFaceWidth(int position);         // 获得前面item的总宽度
    int getBackPosition();                  // 返回能容纳最后几个item的收个位置

    void resizeEvent(QResizeEvent* event);  // 监听改变窗口大小时的事件

private slots:
    void clickOnForward();  // 响应向前按钮单击的曹
    void clickOnNext();     // 相应向后按钮单击的曹

private:
    FrameDisplayModel m_eFrameDisModel;             // 框架显示模式
    TextDisplayModel m_eTextDisModel;               // 文字显示模式
    QPushButton* btn_forward;                       // 向前按钮
    QPushButton* btn_next;                          // 向右按钮
    QWidget* frameWidget;                           // 框架的QWidget
    QList<QPair<QString, QString> > keyValue_list;  // 存储元素显示的文字
    QList<QLabel*>item_list;                        // 存储元素
    QParallelAnimationGroup* m_pAnimGroup;          // 并行动画组
    Qt::Alignment m_eItemAligin;                    // item文本的对齐方式

    int m_nButtonSize;          // ,在水平显示时是按钮的宽,在垂直显示时是按钮的高
    int m_nItemWidth;           // 元素label的宽
    int m_nItemHeight;          // 元素label的高
    int m_nTopMargin;           // 框架上边距
    int m_nBottomMargin;        // 框架下边距
    int m_nLeftMargin;          // 框架左边距
    int m_nRightMargin;         // 框架右边距
    int m_nItemSpacing;         // 元素之间的间距
    int m_nNowItemPosition;     // 当前显示的第一个元素
    int m_nUpdateFlags;         // 更新标志,0为立即更新,否则等待更新
    bool bCreateItemLabel;      // 是否为元素文字创建了label

    QString sItemStyleSheet;    // item样式
    QString m_sTextSeparator;   // 文字之间的分隔符

};

#endif // KINFOCUBE_H
View Code

 

 

kinfocube.cpp

#include "kinfocube.h"

#include <QLayout>
#include <QPropertyAnimation>

/*
    构造函数,初始化
 @param
    model   显示模式
    parent  父窗口
*/
KInfoCube::KInfoCube(QWidget *parent, FrameDisplayModel frameModel, TextDisplayModel textModel)
    : QFrame(parent),
    m_eTextDisModel(textModel),
    m_eFrameDisModel(frameModel)    
{
    initValue();
    creatFrame();
    connectSignalSlot();
    frameLayout();
}

/*
    析构函数,释放没有指明父窗口的元件
 */
KInfoCube::~KInfoCube()
{
    clearItemLabel();
    delete m_pAnimGroup;
    m_pAnimGroup = nullptr;
}

/*
    添加元素,更新已存在的元素
 @param
    sKey   键
    sVlue  值
 */
void KInfoCube::addItem(const QString &sKey, const QString &sVlue)
{
    int position = findItem(sKey);
    if(position != -1)
    {
        keyValue_list[position].second = sVlue;
    }
    else
    {
        QPair<QString, QString>newPair;
        newPair.first = sKey;
        newPair.second= sVlue;
        keyValue_list.append(newPair);
    }
    layoutControl();
}

/*
    添加元素,更新已存在的元素
 @param
    pair   存储QPair<QString,QString>类型的键值对
 */
void KInfoCube::addItem(QPair<QString, QString> pair)
{
    int position = findItem(pair.first);
    if(position != -1)
    {
        keyValue_list[position].second = pair.second;
    }
    else
    {
        QPair<QString, QString>newPair;
        newPair.first = pair.first;
        newPair.second= pair.second;
        keyValue_list.append(newPair);
    }
    layoutControl();
}

/*
    添加元素,更新已存在的元素
 @param
    list   存储QList<QPair<QString,QString>>类型的键值对
 */
void KInfoCube::addItem(QList<QPair<QString, QString> > list)
{
    for(int i=0; i<list.size(); i++)
    {
        int position = findItem(list[i].first);
        if(position != -1)
        {
            keyValue_list[position].second = list.at(i).second;
        }
        else
        {
            QPair<QString, QString>newPair;
            newPair.first = list.at(i).first;
            newPair.second= list.at(i).second;
            keyValue_list.append(newPair);
        }
    }
    layoutControl();
}

/*
    清除所有元素
 */
void KInfoCube::clear()
{
    keyValue_list.clear();
    clearItemLabel();
    bCreateItemLabel = false;
}

/*
    设置左边距
 @param
    value   值
 */
void KInfoCube::setLeftMargin(const int value)
{
    m_nLeftMargin = value;
    layoutControl();
}

/*
    设置右边距
 @param
    value   值
 */
void KInfoCube::setRightMargin(const int value)
{
    m_nRightMargin = value;
    layoutControl();
}

/*
    设置上边距
 @param
    value   值
 */
void KInfoCube::setTopMargin(const int value)
{
    m_nTopMargin = value;
    layoutControl();
}

/*
    设置下边距
 @param
    value   值
 */
void KInfoCube::setBottomMargin(const int value)
{
    m_nBottomMargin = value;
    layoutControl();
}

/*
    设置元素的宽,框架显示模式为水平时有效
 @param
    value   值
 */
void KInfoCube::setItemWidth(const int value)
{
    m_nItemWidth = value;
    layoutControl();
}

/*
   设置元素的高,框架显示模式为垂直时有效
 @param
    value   值
 */
void KInfoCube::setItemHeight(const int value)
{
    m_nItemHeight = value;
    layoutControl();
}

/*
    设置元素之间的间隔
 @param
    value   值
 */
void KInfoCube::setItemSpacing(const int value)
{
    m_nItemSpacing = value;
    layoutControl();
}

/*
    设置按钮的宽
 @param
    value   值
 */
void KInfoCube::setButtonSize(const int value)
{
    m_nButtonSize = value;
    layoutControl();
}

/*
    设置按钮的样式
 @param
    styleSheet   string类型的样式值
 */
void KInfoCube::setBtnStyleSheet(const QString &styleSheet)
{
    btn_forward ->setStyleSheet(styleSheet);
    btn_next    ->setStyleSheet(styleSheet);
    layoutControl();
}

/*
    设置框架显示模式
 @param
    frameModel   FrameDisplayModel的枚举类型
 */
void KInfoCube::setFrameDisplayModel(KInfoCube::FrameDisplayModel frameModel)
{
    m_eFrameDisModel = frameModel;
    layoutControl();
}

/*
    设置问子显示模式
 @param
    textModel   TextDisplayModel的枚举类型
 */
void KInfoCube::setTextDisplayModel(KInfoCube::TextDisplayModel textModel)
{
    m_eTextDisModel = textModel;
    layoutControl();
}

/* 开始更新 */
void KInfoCube::beginUpdate()
{
    ++m_nUpdateFlags;
}

/* 结束更新 */
void KInfoCube::endUpdate()
{
    --m_nUpdateFlags;
    layoutControl();
}

/*
    设置文字显示模式
 @param
    aligin   对齐方式
 */
void KInfoCube::setTextAligin(Qt::Alignment aligin)
{
    m_eItemAligin = aligin;
    layoutControl();
}

/*
    设置文字的分隔符
 @param
    aligin   分隔符
 */
void KInfoCube::setTextSeparator(const QString &sSeparator)
{
    m_sTextSeparator = sSeparator;
    layoutControl();
}

/* 初始化值 */
void KInfoCube::initValue()
{
    m_nButtonSize       = 20;
    m_nTopMargin        = 6;
    m_nBottomMargin     = 6;
    m_nLeftMargin       = 6;
    m_nRightMargin      = 6;
    m_nItemSpacing      = 6;
    m_nItemWidth        = 60;
    m_nItemHeight       = 60;
    m_nNowItemPosition  = 0;
    m_nUpdateFlags      = 0;
    bCreateItemLabel    = false;

    m_eItemAligin = Qt::AlignCenter;
    m_sTextSeparator = "";
}

/* 创建框架 */
void KInfoCube::creatFrame()
{
    frameWidget = new QWidget(this);
    frameWidget->setStyleSheet("background-color: rgb(170, 0, 0)");
    btn_forward = new QPushButton(this);
    btn_next    = new QPushButton(this);
    m_pAnimGroup = new QParallelAnimationGroup();// 并行动画组
}

/* 连接信号和曹 */
void KInfoCube::connectSignalSlot()
{
    connect(btn_forward,    SIGNAL(clicked()),this,SLOT(clickOnForward()));
    connect(btn_next,       SIGNAL(clicked()),this,SLOT(clickOnNext()));
}

/* 为框架布局 */
void KInfoCube::frameLayout()
{ 
    if(m_eFrameDisModel == Horizontal)
    {
        btn_forward->move(m_nLeftMargin,m_nTopMargin);
        btn_next->move(this->geometry().width()-m_nButtonSize-m_nRightMargin,m_nTopMargin);
        int showBtnSize = 0;
        showBtnSize += btn_forward->isHidden()?0:m_nButtonSize;
        frameWidget->move(m_nLeftMargin+showBtnSize,m_nTopMargin);
    }
    else
    {
        btn_forward  ->move(m_nLeftMargin,m_nTopMargin);
        btn_next->move(m_nLeftMargin,this->geometry().height()-m_nButtonSize-m_nBottomMargin);
        int showBtnSize = 0;
        showBtnSize += btn_forward->isHidden()?0:m_nButtonSize;
        frameWidget->move(m_nLeftMargin,m_nTopMargin+showBtnSize);
    }
}

/* 改变框架大小 */
void KInfoCube::changeSize()
{
    if(m_eFrameDisModel == Horizontal)
    {
        btn_forward->resize(m_nButtonSize, this->geometry().height()-m_nTopMargin-m_nBottomMargin);
        btn_next->resize(m_nButtonSize, this->geometry().height()-m_nTopMargin-m_nBottomMargin);
        int showBtnSize = 0;
        showBtnSize += btn_forward->isHidden()?0:m_nButtonSize;
        showBtnSize += btn_next   ->isHidden()?0:m_nButtonSize;
        frameWidget->resize(this->geometry().width()-m_nLeftMargin-m_nRightMargin-showBtnSize,
                           this->geometry().height()-m_nTopMargin-m_nBottomMargin);
    }
    else
    {
        btn_forward  ->resize(this->geometry().width()-m_nLeftMargin-m_nRightMargin, m_nButtonSize);
        btn_next->resize(this->geometry().width()-m_nLeftMargin-m_nRightMargin, m_nButtonSize);
        int showBtnSize = 0;
        showBtnSize += btn_forward->isHidden()?0:m_nButtonSize;
        showBtnSize += btn_next   ->isHidden()?0:m_nButtonSize;
        frameWidget->resize(this->geometry().width()-m_nLeftMargin-m_nRightMargin,
                           this->geometry().height()-m_nTopMargin-m_nBottomMargin-showBtnSize);
    }
}

/* 监听改变窗口大小时的事件 */
void KInfoCube::resizeEvent(QResizeEvent *event)
{
    QFrame::resizeEvent(event);
    // 根据窗口大小的改变而改变床口内容大小
    changeSize();
    frameLayout();
    if(!isCreateItemLabel())
    {
        creatItemLabel();
        bCreateItemLabel = true;
    }

    showItem(m_nNowItemPosition);
    updateButtonState();
}

/* 查找元素,找到返回元素所在的位置,否则返回-1 */
int KInfoCube::findItem(const QString &sKey)
{
    for(int i=0; i<keyValue_list.size(); i++)
    {
        if(keyValue_list.at(i).first == sKey)
            return i;
    }
    return -1;
}

/* 为每个元素创建label */
void KInfoCube::creatItemLabel()
{
    clearItemLabel();//在创建之前对其进行清除
    // item文字水平显示
    if(m_eTextDisModel == OneLine)
    {
        for(int i=0; i<keyValue_list.size(); i++)
        {
            QString key = keyValue_list.at(i).first;
            QString value = keyValue_list.at(i).second;
            QString text = key+m_sTextSeparator+value;
            QLabel* newItem = new QLabel(frameWidget);
            newItem->setAlignment(m_eItemAligin);
            newItem->setTextFormat(Qt::PlainText);
            newItem->setStyleSheet("background-color: rgb(170, 85, 255)");
            newItem->setText(text);
            item_list.append(newItem);
        }
    }
    // item文字垂直显示
    else
    {
        for(int i=0; i<keyValue_list.size(); i++)
        {
            QString key = keyValue_list.at(i).first;
            QString value = keyValue_list.at(i).second;
            QString text = key+"\n"+value;
            QLabel* newItem = new QLabel(frameWidget);
            newItem->setAlignment(m_eItemAligin);
            newItem->setTextFormat(Qt::PlainText);
            newItem->setStyleSheet("background-color: rgb(170, 85, 255)");
            newItem->resize(m_nItemWidth,m_nItemHeight-m_nItemSpacing);
            newItem->setText(text);
            item_list.append(newItem);
        }
    }
}

/* 是否已经为元素创建了label,是返回true,不是返回false */
bool KInfoCube::isCreateItemLabel()
{
    return bCreateItemLabel?true:false;
}

/* 显示nPosition开始之后的所有元素 */
void KInfoCube::showItem(int nPosition)
{
    if (m_eFrameDisModel == Horizontal)
    {
        int x = 0;
        for(int i=0; i<item_list.size(); i++)
        {
            item_list.at(i)->adjustSize();

            int newWidth = item_list.at(i)->geometry().width();
            newWidth = newWidth>m_nItemWidth?newWidth:m_nItemWidth;

            item_list.at(i)->resize(newWidth ,frameWidget->geometry().height());
            if(i<nPosition)
            {
                item_list.at(i)->move(-1000,0);
            }
            else
            {
                item_list.at(i)->move(x,0);
                x += newWidth+m_nItemSpacing;
            }
            item_list.at(i)->show();
        }
    }
    else
    {
        int y = -(m_nNowItemPosition+1)*m_nItemHeight;
        for(int i=0; i<item_list.size(); i++)
        {
            item_list.at(i)->resize(frameWidget->geometry().width(),m_nItemHeight-m_nItemSpacing);
            item_list.at(i)->move(0,y += m_nItemHeight);
            item_list.at(i)->show();
        }
    }
}

/* 根据eDirecttion的值移动元素的位置 */
void KInfoCube::moveItem(KInfoCube::Direction eDirecttion)
{
    m_pAnimGroup->clear();
    int x=0;
    int y=0;
    int newWidth = m_nItemWidth;
    switch (eDirecttion) {
    case Up:
        y = -(m_nNowItemPosition+1)*m_nItemHeight;
        for(int i=0; i<item_list.size(); i++)
        {
            item_list.at(i)->resize(frameWidget->geometry().width(),m_nItemHeight-m_nItemSpacing);
            QPropertyAnimation *animation = new QPropertyAnimation(item_list.at(i),"pos");
            animation->setDuration(1000);
            animation->setStartValue(QPoint(0,y));
            animation->setEndValue(QPoint(0,y + m_nItemHeight));
            animation->setEasingCurve(QEasingCurve::OutBounce);
            m_pAnimGroup->addAnimation(animation);
            y += m_nItemHeight;
        }
        break;
    case Down:
        y = -m_nNowItemPosition*m_nItemHeight;
        for(int i=0; i<item_list.size(); i++)
        {
            item_list.at(i)->resize(frameWidget->geometry().width(),m_nItemHeight-m_nItemSpacing);
            QPropertyAnimation *animation = new QPropertyAnimation(item_list.at(i),"pos");
            animation->setDuration(1000);
            animation->setStartValue(QPoint(0,y + m_nItemHeight));
            animation->setEndValue(QPoint(QPoint(0,y)));
            animation->setEasingCurve(QEasingCurve::OutBounce);
            m_pAnimGroup->addAnimation(animation);
            y += m_nItemHeight;
        }
        break;
    case Left:
        x = -getFaceWidth(m_nNowItemPosition+1);
        newWidth = item_list.at(m_nNowItemPosition)->geometry().width();
        for(int i=0; i<item_list.size(); i++)
        {
            QPropertyAnimation *animation = new QPropertyAnimation(item_list.at(i),"pos");
            animation->setDuration(1000);
            animation->setStartValue(QPoint(x,0));
            animation->setEndValue(QPoint(x + newWidth + m_nItemSpacing,0));
            animation->setEasingCurve(QEasingCurve::OutBounce);
            m_pAnimGroup->addAnimation(animation);
            x += item_list.at(i)->geometry().width()+m_nItemSpacing;
        }
        break;
    case Right:
        x = -getFaceWidth(m_nNowItemPosition);
        newWidth = item_list.at(m_nNowItemPosition-1)->geometry().width();
        for(int i=0; i<item_list.size(); i++)
        {
            QPropertyAnimation *animation = new QPropertyAnimation(item_list.at(i),"pos");
            animation->setDuration(1000);
            animation->setStartValue(QPoint(x + newWidth,0));
            animation->setEndValue(QPoint(x,0));
            animation->setEasingCurve(QEasingCurve::OutBounce);
            m_pAnimGroup->addAnimation(animation);
            x += item_list.at(i)->geometry().width()+m_nItemSpacing;
        }
        break;
    default:
        break;
    }
    m_pAnimGroup->start();
}

/* 更新按钮状态,根据元素的多少显示对应按钮,方便查看 */
void KInfoCube::updateButtonState()
{
    bool first = m_nNowItemPosition == 0;   // 第一个元素
    first?btn_forward->hide():btn_forward->show();

    int lastPosition = m_eFrameDisModel == Horizontal?
                 getBackPosition() :
                item_list.size()-frameWidget->height()/m_nItemHeight;
    bool last = m_nNowItemPosition >= lastPosition; // 最后一个元素
    last?btn_next->hide():btn_next->show();

    frameLayout();
    changeSize();
    showItem(m_nNowItemPosition);

}

/* 清除所有元素 */
void KInfoCube::clearItemLabel()
{
    for(int i=0; i<item_list.size(); i++)
    {
        delete item_list.at(i);
    }
    item_list.clear();
}

/* 更新,TRUE为立即更新,false为等待更新 */
void KInfoCube::layoutControl()
{
    if(m_nUpdateFlags > 0)
        return;
    creatItemLabel();
    showItem(m_nNowItemPosition);
    updateButtonState();
}

int KInfoCube::getFaceWidth(int position)
{
    int width = 0;
    for(int i=0; i<position; i++)
    {
        width += item_list.at(i)->geometry().width() + m_nItemSpacing;
    }
    return width;
}

int KInfoCube::getBackPosition()
{
    int width = 0;
    for(int i=item_list.size()-1; i>=0; i--)
    {
        width += item_list.at(i)->geometry().width() + m_nItemSpacing;
        if(width - m_nItemSpacing>this->geometry().width())
        {
            return i+1;
        }
    }
}

/* 响应向前按钮单击的曹 */
void KInfoCube::clickOnForward()
{
    m_nNowItemPosition--;
    updateButtonState();
    m_eFrameDisModel==Horizontal?moveItem(Left):moveItem(Up);
}

/* 响应向后按钮单击的曹 */
void KInfoCube::clickOnNext()
{
    m_nNowItemPosition++;
    updateButtonState();
    m_eFrameDisModel==Horizontal?moveItem(Right):moveItem(Down);
}
View Code

 

 

调试效果:

posted @ 2014-10-29 14:45  冷光跃  阅读(1347)  评论(0编辑  收藏  举报