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

一.背景图片描述

 

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!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值