QT 界面实现简单换肤功能

https://blog.csdn.net/QQ575787460/article/details/7825983

QSignalMapper

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

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

二、皮肤窗口

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

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

#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测试下,

#include <QApplication>
#include "skinwidget.h"
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    
    SkinWidget skin;
    skin.show();
    
    return app.exec();
}

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

 

三、主程序窗口

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

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

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

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 

#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");
}

测试一下,结果还行。

 

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

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

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


#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


#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

#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);
}

运行下,确实可以。

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

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

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

源码如下:

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


#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());//设置皮肤窗体为合适的大小
}

 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

#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

#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();
}

运行结果:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值