• 扁平化你的Qt应用程序


    什么是扁平化

    这里的扁平化指的是交互设计方面的一种风格。

    扁平化是随着极简注意的风潮流行起来的,这个概念最核心的地方就是放弃一切装饰效果,诸如阴影。透视,纹理,渐变等等能做出3D效果的元素一概不用。全部的元素的边界都干净利落,没有不论什么羽化。渐变,或者阴影。从比較早的windows 8的Metro,


    windows8

    ios7



    android4.0


    都后面Android4.0的Holo Style,还有iOS7的“Ivy style” 的扁平化设计。

    那之后,感觉一切都被拍扁了。

    今天从技术的角度来看看怎么让Qt程序扁平化。

    终于的效果是这种(一个图片浏览器)



    扁平化。走你!

    自己定义扁扁的按钮

    QWidget w;
    w.show().

    上面的代码会生成一个Qt的Widget,然后显示出来,这种窗体会带上系统自带的外框,也包括有最大化,最小化之类的按钮,可是这种按钮并非我们须要的style,并且我们也无法控制,所以我们须要自己实现右上角的窗体控制按钮,创建一个pushbutton类,继承自QPushButton。

    pushbutton.h

    #ifndef PUSHBUTTON_H
    #define PUSHBUTTON_H
    
    #include <QPushButton>
    #include <QMouseEvent>
    #include <QPainter>
    #include <QDebug>
    
    class PushButton : public QPushButton
    {
    	Q_OBJECT
    
    public:
    	PushButton(QWidget *parent = 0);
    	~PushButton();
    	void loadPixmap(QString pic_name);
    
    protected:
    	void enterEvent(QEvent *);
    	void leaveEvent(QEvent *);
    	void mousePressEvent(QMouseEvent *event);
    	void mouseReleaseEvent(QMouseEvent *event);
    	void paintEvent(QPaintEvent *);
    
    private:
    	enum ButtonStatus{NORMAL, ENTER, PRESS, NOSTATUS};
    	ButtonStatus status;
    	QPixmap pixmap;
    
    	int btn_width;
    	int btn_height;
    	bool isPressed;
    };
    
    #endif // PUSHBUTTON_H
    

    pushbutton.cpp

    #include "pushbutton.h"
    
    PushButton::PushButton(QWidget *parent)
    	:QPushButton(parent)
    {
    	status = NORMAL;
    	isPressed = false;
    }
    
    PushButton::~PushButton()
    {
    
    }
    
    void PushButton::loadPixmap(QString pic_name)
    {
    	pixmap.load(pic_name);
    	//QSize picSize(96, 32);
    	pixmap = pixmap.scaledToHeight(30);
    	btn_width = pixmap.width()/3;
    	btn_height = pixmap.height();
    	setMinimumSize(btn_width, btn_height);
    }
    
    void PushButton::enterEvent(QEvent *)
    {
    	status = ENTER;
    	update();
    }
    
    void PushButton::mousePressEvent(QMouseEvent *event)  
    {  
    	if (event->button() == Qt::LeftButton)  
    	{
    		isPressed = true;
    		status = PRESS;
    		update();
    	}
    }
    
    void PushButton::mouseReleaseEvent(QMouseEvent *)
    {
    	if(isPressed)
    	{
    		isPressed = false;
    		status = ENTER;
    		update();
    		emit clicked();
    	}
    }
    
    void PushButton::leaveEvent(QEvent *)
    {
    	status = NORMAL;
    	update();
    }
    
    void PushButton::paintEvent(QPaintEvent *)
    {
    	QPainter painter(this);
    	painter.drawPixmap(rect(), pixmap.copy(btn_width * status, 0, btn_width, btn_height));
    }

    须要准备一张button的图片。包括button的各个状态,依据button不同的状态在paintEvent函数中绘制图片不同的部分。



    去除边框加上widget投影

    去除系统自带的边框仅仅须要一行代码就能够了。

    setWindowFlags(Qt::FramelessWindowHint);

    给widget加入投影的方法卡了我两天。网上现存的有两种方法,一种是先准备好一些阴影的图片,然后手动在paintEvent中把阴影一个部分一个部分画出来。

    这个方案费时费力,不灵活,效果也不太好。

    还有一种方法是stackoverflow上的,加入一个widget,把全部窗体控件放到这个widget中,给这个widget加入阴影效果,然后放在一个透明的widget上。这个我试了非常久,效果也不太好。

    最后给出我的解决方法.

    自己定义widget继承自QWidget,构造函数中

    	this->setWindowFlags(Qt::FramelessWindowHint);
    	this->setAttribute(Qt::WA_TranslucentBackground);


    用一个layout装下全部控件,然后

    #define SHADOW_WIDT  5

    mainLayout->setContentsMargins(SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH);
    this->setLayout(mainLayout);

    在main.cpp中

    	MainWindow w;   
    	QGraphicsDropShadowEffect *wndShadow = new QGraphicsDropShadowEffect;
    	wndShadow->setBlurRadius(5.0);
    	wndShadow->setOffset(0);
    	wndShadow->setColor(QColor("#017acc"));
    	w.setGraphicsEffect(wndShadow);
    	w.show();  

    效果还算完美^.


    设置widget背景

    两种方法。第一。使用QPalette

    m_pMyWidget = new QWidget(this);
    m_pMyWidget->setGeometry(0,0,300,100);
    QPalette Pal(palette());
    // set black background
    Pal.setColor(QPalette::Background, Qt::black);
    m_pMyWidget->setAutoFillBackground(true);
    m_pMyWidget->setPalette(Pal);
    m_pMyWidget->show();

    另外一种,使用css

    m_pMyWidget = new QWidget(this);
    m_pMyWidget->setGeometry(0,0,300,100);
    m_pMyWidget->setStyleSheet("background-color:black;");
    m_pMyWidget->show();

    就像用css来修饰Html一样,css也能够用来定义widget的样式,Qt中使用样式表的文档能够參考这里这里


    注。不论什么自己定义继承子QWidget的Widget,想要使用样式表,都要手动实现paintevent函数,代码例如以下:

    void CustomWidget::paintEvent(QPaintEvent *)
     {
         QStyleOption opt;
         opt.init(this);
         QPainter p(this);
         style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
     }


    小结

             相比于使用Qt自带的窗体管理,自己定义的扁平化窗体看上肯定高大上很多。但随之而来的是开发成本和设计成本,由于全部的widget如今都须要自己管理(大小,颜色等),所以在开发之前一定要做好权衡。

  • 相关阅读:
    jmeter的beanshell脚本编写
    基于 Flask 的简易 Mock 平台
    mock-server
    linux环境jmeter- java环境安装配置
    服务器监控环境搭建 telegraf+influxdb+grafana框架
    聚类算法:凝聚层次聚类
    python中cursor操作数据库
    python中if __name__ == '__main__': 的解析
    python连接mysql数据库
    Python3.5,flask在命令行执行 [python] view plain copy import pymysql 连接mysql数据库MySQLdb
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7327487.html
Copyright © 2020-2023  润新知