您的位置:首页 > 编程语言 > Qt开发

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

2012-08-03 10:31 567 查看
声明下:这只是我自己在学习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

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



QSignalMapper

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


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt signal spring 测试 url mfc