What is flattening?
Flattening here refers to a style of interactive design.
Flattening is popular with the trend of simple attention. The core of this concept is to give up all decorative effects, such as shadows, pivoting, and textures, gradient and other elements that can make 3D effects are not required. The boundaries of all elements are neat and neat, without any feathers, gradient, or shadows. From the earlier Windows 8 Metro,
Windows 8
Ios7
Android4.0
The holo style of android4.0 and the flat design of "Ivy style" of ios7. After that, I felt like everything was flat.
Today, we will look at how to flatten the QT program from a technical perspective.
The final result is: (an image browser)
Flat, let's go! Custom flat button
QWidget w;w.show().
The above code will generate a QT widget, and then display it. Such a window will carry an external box that comes with the system, and include buttons such as maximization and minimization, however, such buttons are not the style we need and cannot be controlled. Therefore, we need to implement the window control button in the upper right corner, create a Pushbutton class, and inherit from qpushbutton.
Pushbutton. h
#ifndef PUSHBUTTON_H#define PUSHBUTTON_H#include <QPushButton>#include <QMouseEvent>#include <QPainter>#include <QDebug>class PushButton : public QPushButton{Q_OBJECTpublic: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));}
You need to prepare a button image, including the status of the button. Different parts of the image are drawn in the paintevent function according to the status of the button.
Remove the border and add widget projection
Only one line of code is required to remove the built-in border.
setWindowFlags(Qt::FramelessWindowHint);
The method for adding a projection to the widget took me two days. There are two existing methods on the Internet. One is to prepare some shadow images first, and then manually draw a part of the shadow in paintevent. This method is time-consuming, labor-intensive, inflexible, and ineffective.
Another way is to add a widget on stackoverflow, put all the window controls in the widget, add the shadow effect to the widget, and then put it on a transparent widget. I tried this for a long time and the effect was not very good.
Finally, I will provide a solution.
Custom widgets inherit from qwidgets, In the constructor
this->setWindowFlags(Qt::FramelessWindowHint);this->setAttribute(Qt::WA_TranslucentBackground);
Use a layout to hold all the controls, and then
# Define shadow_widt 5
mainLayout->setContentsMargins(SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH, SHADOW_WIDTH);this->setLayout(mainLayout);
In Main. cpp
MainWindow w; QGraphicsDropShadowEffect *wndShadow = new QGraphicsDropShadowEffect;wndShadow->setBlurRadius(5.0);wndShadow->setOffset(0);wndShadow->setColor(QColor("#017acc"));w.setGraphicsEffect(wndShadow);w.show();
The effect is still perfect ^.
Set widget background
Two Methods: First, use qpalette
m_pMyWidget = new QWidget(this);m_pMyWidget->setGeometry(0,0,300,100);QPalette Pal(palette());// set black backgroundPal.setColor(QPalette::Background, Qt::black);m_pMyWidget->setAutoFillBackground(true);m_pMyWidget->setPalette(Pal);m_pMyWidget->show();
Second, use CSS
m_pMyWidget = new QWidget(this);m_pMyWidget->setGeometry(0,0,300,100);m_pMyWidget->setStyleSheet("background-color:black;");m_pMyWidget->show();
Like using CSS to modify HTML, CSS can also be used to define the style of Widgets. For the document on using style sheets in QT, refer to here and here.
Note! You must manually implement the paintevent function for any widget that inherits the sub-qwidget by using a style sheet. The Code is as follows:
void CustomWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); }
Summary
Compared with window management that comes with QT, the custom flat window is certainly a lot bigger, but the development cost and design cost come with it, because all widgets need to be managed by themselves (size, color, and so on), you must make a balance before development.
Flattening your QT Application