您的位置:首页 > Web前端 > JQuery

android on qt 之模拟jquery-mobile控件的box-shadow效果

2015-07-14 09:51 786 查看
一.背景图片描述

1. 名称定义

在Qt的控件中,加入类似CSS3的box-shodow的阴影效果。由于QSS不支持box-shodow属性,故而通过截图拼凑来模拟。



图1. radius_border.png
上图为我们需要准备的背景图(radius_border.png):

矩形区域(x2,y2,x5,y5)所内切包含的圆角矩形背景透明,之所以透明,是为了不遮掩住QT的控件背景,比如QLineEdit;

矩形区域(x1,y1,x6,y6)所内切包含的蓝色带状区域为控件的阴影;

矩形区域(x1,y1,x3,y3)所内切包含的蓝色扇环区域命名为leftTop;

矩形区域(x3,y1,x4,y2)所内切包含的蓝色矩形区域命名为top;

矩形区域(x4,y1,x6,y3)所内切包含的蓝色扇环区域命名为rightTop;

矩形区域(x5,y3,x6,y4)所内切包含的蓝色矩形区域命名为right;

矩形区域(x4,y4,x6,y6)所内切包含的蓝色扇环区域命名为rightBottom;

矩形区域(x3y5,x4,y6)所内切包含的蓝色矩形区域命名为bottom;

矩形区域(x1,y4,x3,y6)所内切包含的蓝色扇环区域命名为leftBottom

矩形区域(x1,y3,x2,y4)所内切包含的蓝色矩形区域命名为left;

注:当border_radius为0时,阴影即为直角矩形,其所修饰的控件也应该为直角。

2. 变量定义

border_width: 蓝色带状阴影的宽度

border_radius: 带状阴影圆角的幅度

background_width: 背景图片的宽度

background_height: 背景图片的高度

二.背景图片使用

1. 获取背景图片的尺寸

QPixmap background =QPixmap(":/image/radius_border.png");

int background_width = background.width(); // 背景图片宽度

int background_height =background.height(); // 背景图片高度

2. 定义阴影带相关值

int border_width = 5; //阴影带的宽度

int border_radius = 5; // 阴影带圆角的半径

int corner_width = border_width + border_radius; // 阴影带4个转角的宽

int corner_height = border_width +border_radius; // 阴影带4个转角的高

int original_border = 1; // 控件原始边界宽度

3. 从左上角(leftTop)开始,顺时针截取(QPixmap对象的copy方法)4个转角与4个边

QPixmap leftTop =

background.copy(0, 0, corner_width,corner_height);

QPixmap top =

background.copy(corner_width, 0,background_width - 2 * corner_width, border_width);

QPixmap rightTop =

background.copy(background_width- corner_width, 0, corner_width, corner_height);

QPixmap right =

background.copy(background_width- border_width, corner_height, border_width,

background_height - 2 *corner_height);

QPixmap rightBottom =

background.copy(background_width - corner_width,background_height - corner_height,

corner_width, corner_height);

QPixmap bottom =

background.copy(corner_width, background_height -border_width, background_width –

2 * corner_width, border_width);

QPixmap leftBottom =

background.copy(0, background_height -corner_height, corner_width, corner_height);

QPixmap left =

background.copy(0, corner_height,border_width, background_height - 2 * corner_height);

4. 获取控件的位置,把上述截取的4角4边绘制在控件的边缘

/* 获取控件的位置 */

QRect rect =ui->lineEdit->geometry();

int startX = rect.left(); // 控件的起始X坐标

int endX = rect.right(); // 控件的终止X坐标

int startY = rect.top(); // 控件的起始Y坐标

int endY = rect.bottom(); // 控件的终止Y坐标

int width = rect.width(); // 控件宽度

int height = rect.height(); // 控件高度

/* 绘制4角4边 */

painter.drawPixmap(startX - border_width,startY - border_width, leftTop);

painter.drawPixmap(startX + border_radius,startY - border_width,

width - 2 *border_radius - original_border, border_width, top);

painter.drawPixmap(endX - border_radius,startY - border_width, rightTop);

painter.drawPixmap(endX, startY +border_radius, border_width,

height - 2 *border_radius - original_border, right);

painter.drawPixmap(endX - border_radius,endY - border_radius, rightBottom);

painter.drawPixmap(startX + border_radius,endY , width - 2 * border_radius - original_border,

border_width,bottom);

painter.drawPixmap(startX - border_width,endY - border_width, leftBottom);

painter.drawPixmap(startX - border_width,startY + border_radius, border_width,

height - 2 *border_radius - original_border, left);

二.工程源代码

2.1 工程结构如下图所示:



2.2 边界描述类

2.2.1 头文件 border.h

#ifndef BORDER_H
#define BORDER_H

#include <QPixmap>
#include <QPainter>

class Border
{

public:
Border(const char* bg);
Border(const char* bg, int border_width, int border_radius, int original_border);
void paintBorder(QPainter &painter, QRect &rect);
~Border();

private:
QPixmap background;    // 完整背景图
int background_width;  // 背景图片宽度
int background_height; // 背景图片高度
int border_width;
int border_radius;
int original_border;
int corner_width;
int corner_height;

QPixmap leftTop;
QPixmap top;
QPixmap rightTop;
QPixmap right;
QPixmap rightBottom;
QPixmap bottom;
QPixmap leftBottom;
QPixmap left;
QPixmap center;
};

#endif // BORDER_H
2.2.2 源文件border.cpp

#include "border.h"

Border::Border(const char* bg):border_width(5), border_radius(5), original_border(1) {
this->background = QPixmap(bg);
}

Border::Border(const char* bg, int border_width, int border_radius, int original_border)
:border_width(5), border_radius(5), original_border(1) {
this->background = QPixmap(bg);
this->background_width  = background.width();  // 背景图片宽度
this->background_height = background.height(); // 背景图片高度

this->border_width = border_width;
this->border_radius = border_radius;
this->original_border = original_border;

this->corner_width  = border_width + border_radius;
this->corner_height = border_width + border_radius;

/* 以顺时针方向旋转的边界 */
this->leftTop     = background.copy(0, 0, corner_width, corner_height);
this->top         = background.copy(corner_width, 0, background_width - 2 * corner_width, border_width);
this->rightTop    = background.copy(background_width - corner_width, 0, corner_width, corner_height);
this->right       = background.copy(background_width - border_width, corner_height, border_width,
this->                              background_height - 2 * corner_height);
this->rightBottom = background.copy(background_width - corner_width, background_height - corner_height,
this->                              corner_width, corner_height);
this->bottom      = background.copy(corner_width, background_height - border_width,
this->                              background_width - 2 * corner_width, border_width);
this->leftBottom  = background.copy(0, background_height - corner_height, corner_width, corner_height);
this->left        = background.copy(0, corner_height, border_width, background_height - 2 * corner_height);

}

Border::~Border() {

}

void Border::paintBorder(QPainter &painter, QRect& rect) {
int startX = rect.left();
int endX   = rect.right();
int startY = rect.top();
int endY   = rect.bottom();
int width  = rect.width();
int height = rect.height();

painter.drawPixmap(startX - border_width, startY - border_width, leftTop);
painter.drawPixmap(startX + border_radius, startY - border_width,
width - 2 * border_radius - original_border, border_width, top);
painter.drawPixmap(endX - border_radius, startY - border_width, rightTop);
painter.drawPixmap(endX, startY + border_radius, border_width,
height - 2 * border_radius - original_border, right);
painter.drawPixmap(endX - border_radius, endY - border_radius, rightBottom);
painter.drawPixmap(startX + border_radius, endY , width - 2 * border_radius - original_border,
border_width, bottom);
painter.drawPixmap(startX - border_width, endY - border_width, leftBottom);
painter.drawPixmap(startX - border_width, startY + border_radius, border_width,
height - 2 * border_radius - original_border, left);
}


2.3 主窗口

2.3.1 头文件mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTabWidget>
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QToolBar>
#include "border.h"

namespace Ui {
class MainWindow;
}

/*
*  class MainWindow: 子类
*  public QMainWindow:父类
*/
class MainWindow : public QMainWindow
{
Q_OBJECT

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

private:
Ui::MainWindow *ui;
Border *border;

protected:
void paintEvent(QPaintEvent *event);
bool eventFilter(QObject *watched,QEvent *event);
bool event(QEvent *event);

};

#endif // MAINWINDOW_H
2.3.2 源文件mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QMessageBox>
#include <QGraphicsDropShadowEffect>
#include <QDebug>
#include <QPainter>
#include <QMouseEvent>

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

// 遍历子控件
QObjectList list = ui->centralWidget->children();
foreach (QObject *obj, list) {
obj->installEventFilter(this);
#if 0
qDebug() << obj->objectName(); // 控件名称
qDebug() << obj->metaObject()->className(); // 控件类名称
#endif
char *className = (char *)obj->metaObject()->className();

// 去掉按钮的焦点
if(strcmp(className, "QPushButton") == 0) {
QPushButton *button = qobject_cast<QPushButton*>(obj);
button->setFocusPolicy(Qt::NoFocus);
}
}

border = new Border(":/image/radius_border.png", 5, 5, 1);

}

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

/*
* 在eventFilter函数中调用this->update(),则会触发该函数
*/
void MainWindow::paintEvent(QPaintEvent *event) {

QPainter painter(this);

QObjectList list = ui->centralWidget->children();
foreach (QObject *obj, list) {

char *className = (char *)obj->metaObject()->className();
if(strcmp(className, "QPushButton") == 0) {
QPushButton *button = qobject_cast<QPushButton*>(obj);
if(button->isDown()) {
QRect rect = button->geometry();
border->paintBorder(painter, rect);
}
}

if(strcmp(className, "QLineEdit") == 0) {
QLineEdit *edit = qobject_cast<QLineEdit*>(obj);
if(edit->hasFocus()) {
QRect rect = edit->geometry();
border->paintBorder(painter, rect);
}
}
}

}

/*
* eventFilter针对某一控件事件的过滤,使用前需要在控件安装事件过滤器:
* QObject->installEventFilter(this);
*/
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
char *className = (char *)watched->metaObject()->className();
if(strcmp(className, "QPushButton") == 0 ||
strcmp(className, "QLineEdit") == 0) {
this->update();
}

return QWidget::eventFilter(watched, event);
}

/*
* MainWindow的事件处理函数,例如鼠标点击事件:若鼠标点击在MainWindow窗口上面,则进入该函数。
* 如果鼠标点击事件在QLineEdit或者QPushButton上面,则不会进入。
*/
bool MainWindow::event(QEvent* event)
{
switch(event->type()) {
case QEvent::MouseButtonPress:
qDebug() << "QEvent::MouseButtonPress";
break;
default:
break;
}

return QWidget::event(event);
}
2.4 主函数 main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QFile>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

QFile styleFile(":/image/blue.css");
styleFile.open(QIODevice::ReadOnly);
QString setStyleSheet(styleFile.readAll());;
a.setStyleSheet(setStyleSheet);

return a.exec();
}


点击下载

最后要感谢的是刘典武大侠,本工程所采用的blue.css是从他的工程里面拿来的,3ks!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: