Qt4.8.2 实现简单的界面换肤功能

Qt4.8.2   实现简单的界面换肤功能              
        分类:             Qt4学习笔记                   1107人阅读     评论(1)     收藏     举报    
qt signal spring 测试 url mfc

声明下:这只是我自己在学习Qt的时候,想到的,也不知道这方法合不合适,反正是能够实现换肤功能。

一、思路及准备

双击主程序界面,弹出换肤界面,点击换肤界面上的图片,主程序改变相应界面背景图片。

我准备了四张图片,big_spring.png,big_summer.png,small_spring.png,small_summer.png.看名字就知道换肤界面列出来small_spring.png和small_summer.png,点击图片后,主程序界面显示相应大图。

二、皮肤窗口

新建Qt4空项目,新建C++类,继承自QWidget,取名SkinWidget

头文件暂时不修改,看看SkinWidget.cpp

[cpp] view plain copy print ?
  1. #include "skinwidget.h"  
  2.   
  3. #include <QPushButton>  
  4. #include <QHBoxLayout>  
  5.   
  6. SkinWidget::SkinWidget(QWidget *parent) :  
  7.     QWidget(parent)  
  8. {  
  9.     QStringList btnText;  
  10.     btnText<<"spring"<<"summer";  
  11.     QHBoxLayout *mainLayout=new QHBoxLayout;  
  12.     for(int i=0;i<btnText.length();i++)  
  13.     {  
  14.         QPushButton *btn=new QPushButton;  
  15.         QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";  
  16.         btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示  
  17.         btn->setStyleSheet(qss);//设置样式表,按钮的背景图片  
  18.         btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小  
  19.         btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框  
  20.         mainLayout->addWidget(btn);  
  21.     }  
  22.     setLayout(mainLayout);  
  23.     setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小  
  24. }  
#include "skinwidget.h"

#include <QPushButton>
#include <QHBoxLayout>

SkinWidget::SkinWidget(QWidget *parent) :
    QWidget(parent)
{
    QStringList btnText;
    btnText<<"spring"<<"summer";
    QHBoxLayout *mainLayout=new QHBoxLayout;
    for(int i=0;i<btnText.length();i++)
    {
        QPushButton *btn=new QPushButton;
        QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";
        btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示
        btn->setStyleSheet(qss);//设置样式表,按钮的背景图片
        btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小
        btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框
        mainLayout->addWidget(btn);
    }
    setLayout(mainLayout);
    setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小
}

新建个main.cpp测试下,

[cpp] view plain copy print ?
  1. #include <QApplication>  
  2. #include "skinwidget.h"  
  3. int main(int argc,char *argv[])  
  4. {  
  5.     QApplication app(argc,argv);  
  6.       
  7.     SkinWidget skin;  
  8.     skin.show();  
  9.       
  10.     return app.exec();  
  11. }  
#include <QApplication>
#include "skinwidget.h"
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    
    SkinWidget skin;
    skin.show();
    
    return app.exec();
}


Qt4.8.2 实现简单的界面换肤功能_第1张图片

看样子还马马虎虎,可以继续进行。

三、主程序窗口

新建C++类MainWidget,继承自QWidget。我们想实现双击主程序,弹出换肤窗体,就必须捕捉到双击时间,类似于MFC的OnDbClick。

先看看基类QWidget提供的虚函数

Qt4.8.2 实现简单的界面换肤功能_第2张图片

虚函数就是基类提供的,在我们需要的时候去重载的接口,所以在MainWidget头文件中,重载鼠标双击事件函数。

MainWidget.h

[cpp] view plain copy print ?
  1. #ifndef MAINWIDGET_H  
  2. #define MAINWIDGET_H  
  3.   
  4. #include <QWidget>  
  5.   
  6. class MainWidget : public QWidget  
  7. {  
  8.     Q_OBJECT  
  9. public:  
  10.     explicit MainWidget(QWidget *parent = 0);  
  11.       
  12. signals:  
  13.       
  14. public slots:  
  15.   
  16. protected:  
  17.     virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承  
  18. };  
  19.   
  20. #endif // MAINWIDGET_H  
#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MainWidget(QWidget *parent = 0);
    
signals:
    
public slots:

protected:
    virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承
};

#endif // MAINWIDGET_H


 MainWidget.cpp

[cpp] view plain copy print ?
  1. #include "mainwidget.h"  
  2.   
  3. #include <QMouseEvent>//鼠标事件  
  4. #include <QPalette>//调色板 设置背景颜色  
  5.   
  6. #include <QMessageBox>  
  7.   
  8. MainWidget::MainWidget(QWidget *parent) :  
  9.     QWidget(parent)  
  10. {  
  11.     setFixedSize(500,400);  
  12.     QPalette palette;  
  13.     palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));  
  14.     setPalette(palette);  
  15. }  
  16.   
  17. void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)  
  18. {  
  19.     //如果双击鼠标左键,弹出测试对话框  
  20.     if(event->button()&Qt::LeftButton)  
  21.         QMessageBox::information(this,"skin","leftButton double click test");  
  22. }  
#include "mainwidget.h"

#include <QMouseEvent>//鼠标事件
#include <QPalette>//调色板 设置背景颜色

#include <QMessageBox>

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent)
{
    setFixedSize(500,400);
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));
    setPalette(palette);
}

void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    //如果双击鼠标左键,弹出测试对话框
    if(event->button()&Qt::LeftButton)
        QMessageBox::information(this,"skin","leftButton double click test");
}


测试一下,结果还行。

Qt4.8.2 实现简单的界面换肤功能_第3张图片

 四、皮肤窗口与主程序窗口的交互 和QSignalMapper

在主窗口双击事件中,弹出皮肤窗体,然后把皮肤窗体各个按钮的clicked信号同主程序不同背景的槽连接起来

SkinWidget.h

[cpp] view plain copy print ?
  1. #ifndef SKINWIDGET_H  
  2. #define SKINWIDGET_H  
  3.   
  4. #include <QWidget>  
  5.   
  6. class SkinWidget : public QWidget  
  7. {  
  8.     Q_OBJECT  
  9. public:  
  10.     explicit SkinWidget(QWidget *parent = 0);  
  11.       
  12. signals:  
  13.     void changeSkinSpring();//与春天按钮的clicked信号绑定  
  14.     void changeSkinSummer();//与夏天按钮的clicked信号绑定  
  15. private slots:  
  16.   
  17. };  
  18.   
  19. #endif // SKINWIDGET_H  
#ifndef SKINWIDGET_H
#define SKINWIDGET_H

#include <QWidget>

class SkinWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SkinWidget(QWidget *parent = 0);
    
signals:
    void changeSkinSpring();//与春天按钮的clicked信号绑定
    void changeSkinSummer();//与夏天按钮的clicked信号绑定
private slots:

};

#endif // SKINWIDGET_H


SkinWidget.cpp

[cpp] view plain copy print ?
  1. #include "skinwidget.h"  
  2.   
  3. #include <QPushButton>  
  4. #include <QHBoxLayout>  
  5.   
  6. SkinWidget::SkinWidget(QWidget *parent) :  
  7.     QWidget(parent)  
  8. {  
  9.     QStringList btnText;  
  10.     btnText<<"spring"<<"summer";  
  11.     QHBoxLayout *mainLayout=new QHBoxLayout;  
  12.     for(int i=0;i<btnText.length();i++)  
  13.     {  
  14.         QPushButton *btn=new QPushButton;  
  15.         QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";  
  16.         btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示  
  17.         btn->setStyleSheet(qss);//设置样式表,按钮的背景图片  
  18.         btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小  
  19.         btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框  
  20.         mainLayout->addWidget(btn);  
  21.         switch(i)  
  22.         {  
  23.         case 0:  
  24.             QObject::connect(btn,SIGNAL(clicked()),this,SIGNAL(changeSkinSpring()));  
  25.             break;  
  26.         case 1:  
  27.             QObject::connect(btn,SIGNAL(clicked()),this,SIGNAL(changeSkinSummer()));  
  28.             break;  
  29.         }  
  30.     }  
  31.     setLayout(mainLayout);  
  32.     setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小  
  33. }  
#include "skinwidget.h"

#include <QPushButton>
#include <QHBoxLayout>

SkinWidget::SkinWidget(QWidget *parent) :
    QWidget(parent)
{
    QStringList btnText;
    btnText<<"spring"<<"summer";
    QHBoxLayout *mainLayout=new QHBoxLayout;
    for(int i=0;i<btnText.length();i++)
    {
        QPushButton *btn=new QPushButton;
        QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";
        btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示
        btn->setStyleSheet(qss);//设置样式表,按钮的背景图片
        btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小
        btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框
        mainLayout->addWidget(btn);
        switch(i)
        {
        case 0:
            QObject::connect(btn,SIGNAL(clicked()),this,SIGNAL(changeSkinSpring()));
            break;
        case 1:
            QObject::connect(btn,SIGNAL(clicked()),this,SIGNAL(changeSkinSummer()));
            break;
        }
    }
    setLayout(mainLayout);
    setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小
}


MainWidget.h

[cpp] view plain copy print ?
  1. #ifndef MAINWIDGET_H  
  2. #define MAINWIDGET_H  
  3.   
  4. #include <QWidget>  
  5.   
  6. class MainWidget : public QWidget  
  7. {  
  8.     Q_OBJECT  
  9. public:  
  10.     explicit MainWidget(QWidget *parent = 0);  
  11.       
  12. signals:  
  13.       
  14. private slots:  
  15.     void setBkSpring();//与SkinWidget的changeSkinSpring信号连接  
  16.     void setBkSummer();//与SkinWidget的changeSkinSummer信号连接  
  17.   
  18. protected:  
  19.     virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承  
  20. };  
  21.   
  22. #endif // MAINWIDGET_H  
#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MainWidget(QWidget *parent = 0);
    
signals:
    
private slots:
    void setBkSpring();//与SkinWidget的changeSkinSpring信号连接
    void setBkSummer();//与SkinWidget的changeSkinSummer信号连接

protected:
    virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承
};

#endif // MAINWIDGET_H


MainWidget.cpp

[cpp] view plain copy print ?
  1. #include "mainwidget.h"  
  2. #include "skinwidget.h"  
  3. #include <QMouseEvent>//鼠标事件  
  4. #include <QPalette>//调色板 设置背景颜色  
  5.   
  6. MainWidget::MainWidget(QWidget *parent) :  
  7.     QWidget(parent)  
  8. {  
  9.     setFixedSize(500,400);  
  10.     QPalette palette;  
  11.     palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));  
  12.     setPalette(palette);  
  13. }  
  14.   
  15. void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)  
  16. {  
  17.     SkinWidget *skin=new SkinWidget;  
  18.     skin->setAttribute(Qt::WA_DeleteOnClose);  
  19.     QObject::connect(skin,SIGNAL(changeSkinSpring()),this,SLOT(setBkSpring()));  
  20.     QObject::connect(skin,SIGNAL(changeSkinSummer()),this,SLOT(setBkSummer()));  
  21.     skin->show();  
  22. }  
  23.   
  24. //private slot 换肤 春天  
  25. void MainWidget::setBkSpring()  
  26. {  
  27.     QPalette palette;  
  28.     palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));  
  29.     setPalette(palette);  
  30. }  
  31. //private slot 换肤 夏天  
  32. void MainWidget::setBkSummer()  
  33. {  
  34.     QPalette palette;  
  35.     palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_summer.png")));  
  36.     setPalette(palette);  
  37. }  
#include "mainwidget.h"
#include "skinwidget.h"
#include <QMouseEvent>//鼠标事件
#include <QPalette>//调色板 设置背景颜色

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent)
{
    setFixedSize(500,400);
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));
    setPalette(palette);
}

void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    SkinWidget *skin=new SkinWidget;
    skin->setAttribute(Qt::WA_DeleteOnClose);
    QObject::connect(skin,SIGNAL(changeSkinSpring()),this,SLOT(setBkSpring()));
    QObject::connect(skin,SIGNAL(changeSkinSummer()),this,SLOT(setBkSummer()));
    skin->show();
}

//private slot 换肤 春天
void MainWidget::setBkSpring()
{
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_spring.png")));
    setPalette(palette);
}
//private slot 换肤 夏天
void MainWidget::setBkSummer()
{
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_summer.png")));
    setPalette(palette);
}


 Qt4.8.2 实现简单的界面换肤功能_第4张图片

运行下,确实可以。

但是,这是个好办法么,如果有1000张候选图片,我们就要建立1000个槽函数????

如果可以把图片的名字当作信号的参数多好啊,就是点击春天按钮的时候,把“spring”这个字符串当作信号的参数。点击夏天按钮的时候,把“summer”这个字符串当作信号的参数。问题转化为:如何把一个无参信号同一个有参信号联系起来。

终于,在网上搜到了这个类QSignalMapper。这个类可以看成信号的翻译和转发器,可以把无参信号翻译成带int参数、QString参数、QObject*参数或者QWidget*参数的信号, 并将之转发。

源码如下:

SkinWidget.h

[cpp] view plain copy print ?
  1. #ifndef SKINWIDGET_H  
  2. #define SKINWIDGET_H  
  3.   
  4. #include <QWidget>  
  5.   
  6. class QSignalMapper;  
  7. class SkinWidget : public QWidget  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit SkinWidget(QWidget *parent = 0);  
  12.       
  13. signals:  
  14.     void skinChange(QString);  
  15.   
  16. private slots:  
  17. private:  
  18.     QSignalMapper *signalMapper;  
  19.   
  20. };  
  21.   
  22. #endif // SKINWIDGET_H  
#ifndef SKINWIDGET_H
#define SKINWIDGET_H

#include <QWidget>

class QSignalMapper;
class SkinWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SkinWidget(QWidget *parent = 0);
    
signals:
    void skinChange(QString);

private slots:
private:
    QSignalMapper *signalMapper;

};

#endif // SKINWIDGET_H


SkinWidget.cpp

[cpp] view plain copy print ?
  1. #include "skinwidget.h"  
  2.   
  3. #include <QPushButton>  
  4. #include <QHBoxLayout>  
  5. #include <QSignalMapper>  
  6.   
  7. SkinWidget::SkinWidget(QWidget *parent) :  
  8.     QWidget(parent)  
  9. {  
  10.     signalMapper=new QSignalMapper(this);  
  11.   
  12.     QStringList btnText;  
  13.     btnText<<"spring"<<"summer";  
  14.     QHBoxLayout *mainLayout=new QHBoxLayout;  
  15.     for(int i=0;i<btnText.length();i++)  
  16.     {  
  17.         QPushButton *btn=new QPushButton;  
  18.         QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";  
  19.         btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示  
  20.         btn->setStyleSheet(qss);//设置样式表,按钮的背景图片  
  21.         btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小  
  22.         btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框  
  23.         mainLayout->addWidget(btn);  
  24.   
  25.         QObject::connect(btn,SIGNAL(clicked()),signalMapper,SLOT(map()));  
  26.         signalMapper->setMapping(btn,btnText[i]);  
  27.     }  
  28.   
  29.     connect(signalMapper,SIGNAL(mapped(QString)),this,SIGNAL(skinChange(QString)));  
  30.     setLayout(mainLayout);  
  31.     setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小  
  32. }  
#include "skinwidget.h"

#include <QPushButton>
#include <QHBoxLayout>
#include <QSignalMapper>

SkinWidget::SkinWidget(QWidget *parent) :
    QWidget(parent)
{
    signalMapper=new QSignalMapper(this);

    QStringList btnText;
    btnText<<"spring"<<"summer";
    QHBoxLayout *mainLayout=new QHBoxLayout;
    for(int i=0;i<btnText.length();i++)
    {
        QPushButton *btn=new QPushButton;
        QString qss="background-image:url(:/img/small_"+btnText[i]+".png)";
        btn->setToolTip(btnText[i]);//鼠标停留在按钮上的提示
        btn->setStyleSheet(qss);//设置样式表,按钮的背景图片
        btn->setFixedSize(150,120);//设置按钮固定大小为背景图片的大小
        btn->setFlat(true);//设置按钮的平坦属性,也就是按钮无边框
        mainLayout->addWidget(btn);

        QObject::connect(btn,SIGNAL(clicked()),signalMapper,SLOT(map()));
        signalMapper->setMapping(btn,btnText[i]);
    }

    connect(signalMapper,SIGNAL(mapped(QString)),this,SIGNAL(skinChange(QString)));
    setLayout(mainLayout);
    setFixedSize(sizeHint().width(),sizeHint().height());//设置皮肤窗体为合适的大小
}

QSignalMapper

 MainWidget.h

[cpp] view plain copy print ?
  1. #ifndef MAINWIDGET_H  
  2. #define MAINWIDGET_H  
  3.   
  4. #include <QWidget>  
  5.   
  6. class MainWidget : public QWidget  
  7. {  
  8.     Q_OBJECT  
  9. public:  
  10.     explicit MainWidget(QWidget *parent = 0);  
  11.       
  12. signals:  
  13.       
  14. private slots:  
  15.     void setBk(QString);  
  16.   
  17. protected:  
  18.     virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承  
  19. };  
  20.   
  21. #endif // MAINWIDGET_H  
#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MainWidget(QWidget *parent = 0);
    
signals:
    
private slots:
    void setBk(QString);

protected:
    virtual void mouseDoubleClickEvent(QMouseEvent *);//重载鼠标双击事件函数 从QWidget继承
};

#endif // MAINWIDGET_H


MainWidget.cpp

[cpp] view plain copy print ?
  1. #include "mainwidget.h"  
  2. #include "skinwidget.h"  
  3. #include <QMouseEvent>//鼠标事件  
  4. #include <QPalette>//调色板 设置背景颜色  
  5.   
  6. MainWidget::MainWidget(QWidget *parent) :  
  7.     QWidget(parent)  
  8. {  
  9.     setFixedSize(500,400);  
  10.     setBk("spring");  
  11. }  
  12.   
  13. void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)  
  14. {  
  15.     if(event->button()&Qt::LeftButton)  
  16.     {  
  17.         SkinWidget *skin=new SkinWidget;  
  18.         skin->setAttribute(Qt::WA_DeleteOnClose);  
  19.         QObject::connect(skin,SIGNAL(skinChange(QString)),this,SLOT(setBk(QString)));  
  20.         skin->show();  
  21.     }  
  22. }  
  23.   
  24. //private slot  
  25. void MainWidget::setBk(QString picName)  
  26. {  
  27.     QPalette palette;  
  28.     palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_"+picName+".png")));  
  29.     setPalette(palette);  
  30. }  
#include "mainwidget.h"
#include "skinwidget.h"
#include <QMouseEvent>//鼠标事件
#include <QPalette>//调色板 设置背景颜色

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent)
{
    setFixedSize(500,400);
    setBk("spring");
}

void MainWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button()&Qt::LeftButton)
    {
        SkinWidget *skin=new SkinWidget;
        skin->setAttribute(Qt::WA_DeleteOnClose);
        QObject::connect(skin,SIGNAL(skinChange(QString)),this,SLOT(setBk(QString)));
        skin->show();
    }
}

//private slot
void MainWidget::setBk(QString picName)
{
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/img/big_"+picName+".png")));
    setPalette(palette);
}


main.cpp

[cpp] view plain copy print ?
  1. #include <QApplication>  
  2. #include "skinwidget.h"  
  3. #include "mainwidget.h"  
  4. int main(int argc,char *argv[])  
  5. {  
  6.     QApplication app(argc,argv);  
  7.   
  8.   //  SkinWidget skin;  
  9.   //  skin.show();  
  10.   
  11.     MainWidget mainWindow;  
  12.     mainWindow.show();  
  13.   
  14.     return app.exec();  
  15. }  
#include <QApplication>
#include "skinwidget.h"
#include "mainwidget.h"
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);

  //  SkinWidget skin;
  //  skin.show();

    MainWidget mainWindow;
    mainWindow.show();

    return app.exec();
}


运行结果:

Qt4.8.2 实现简单的界面换肤功能_第5张图片

你可能感兴趣的:(Qt4学习笔记)