qt控制元件動畫效果
阿新 • • 發佈:2019-02-15
#ifndef TERMINAL_H
#define TERMINAL_H
#include <QMouseEvent>
#include <QShowEvent>
#include <QPaintEvent>
#include <QBrush>
#include <QHash>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QSpacerItem>
#include <QGridLayout>
#include <QLabel>
#include <QDragMoveEvent>
#include <QPalette>
#include <QTextEdit>
#include <QPropertyAnimation>
#include <QAnimationGroup>
#include <QEventLoop>
#include <QDesktopWidget>
#include <QApplication>
#include <QPainter>
class EffectAnimation;
enum Direction { UP=0, DOWN=1, LEFT, RIGHT, LEFTTOP, LEFTBOTTOM, RIGHTBOTTOM, RIGHTTOP, NONE };
enum BUTTON {MIN,MAX,CLOSE};
class TitleWidget;
class CenterWidget;
class EffectAnimation;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent=nullptr);
/**
* @brief getBorderWidth 邊框寬度
*/
unsigned getBorderWidth();
void setBorderWidth(const unsigned &value);
/**
* @brief getTitleHeight 標題欄高度
*/
unsigned getTitleHeight();
void setTitleHeight(const unsigned &value);
/**
* @brief getStatusHeight 狀態列高度
*/
unsigned getStatusHeight();
void setStatusHeight(const unsigned &value);
/**
* @brief hasBorder 有邊框
* @return
*/
bool isHasBorder() ;
void setHasBorder(bool value);
/**
* @brief hasTitleBar 有標題欄
* @return
*/
bool isHasTitleBar();
void setHasTitleBar(bool value);
/**
* @brief setTitleColor 設定標題欄顏色
* @param color
*/
void setTitleColor(const QColor& color);
/**
* @brief getLayout 獲取layout
* @return
*/
QVBoxLayout* getLayout();
/**
* @brief getPen 畫筆設定
* @return
*/
QPen getBorderPen();
void setBorderColor(const QColor &value);
/**
* @brief setButtonShow 設定關閉按鈕是否顯示
* @param show
*/
void setButtonShow(const BUTTON& button, bool show);
/**
* @brief getButton 獲取自帶button
* @param button
* @return
*/
QPushButton* getButton(const BUTTON& button);
/**
* @brief setButtonStyle 設定Button風格
* @param button
* @param style
*/
void setButtonStyle(const BUTTON& button, const QString& style);
/**
* @brief getCenterWidget 獲取中央視窗
* @return
*/
QWidget *getCentreWidget();
void setCentreWidget(QWidget *value);
/**
* @brief getTitle 獲取標題
* @return
*/
QString getTitle();
void setTitle(const QString& title);
/**
* @brief getIcon 獲取圖示
* @return
*/
QString getIcon();
void setIcon(const QString& fileName);
/**
* @brief getTitleLable 操作標題
* @return
*/
QLabel* getTitleLable();
QLabel* getIconLable();
/**
* @brief setBackgroundColor 設定背景顏色
* @param color
*/
void setBackgroundColor(const QColor& color);
QColor getBackGroundColor() const;
/**
* @brief isAreaDrag 區域可拖動
* @return
*/
bool isAreaDrag();
void setAreaDrag(bool value);
/**
* @brief getTitleWidget 獲取標題視窗
*/
QWidget *getTitleWidget();
/**
* @brief getTitleTextColor 標題顏色
* @return
*/
QColor getTitleTextColor();
void setTitleTextColor(const QColor &value);
/**
* @brief addWidget 新增視窗
* @param x
* @param y
* @param widget
*/
void addWidget(int x, int y, QWidget *widget);
void emitSizeChangeSignal();
protected:
void mousePressEvent(QMouseEvent* e);
void mouseMoveEvent(QMouseEvent* e);
void mouseReleaseEvent(QMouseEvent* e);
void paintEvent(QPaintEvent* e);
void leaveEvent(QEvent*);
void mouseDoubleClickEvent(QMouseEvent*e);
virtual void drawEverything(QPainter *);
signals:
void sizeChanged(QSize);
private:
/**
* @brief paintFrame 畫邊框
*/
void paintFrame();
/**
* @brief init 初始化
*/
void _initialze();
QVBoxLayout* layout;
QGridLayout* centerLayout;
TitleWidget * titleWidget;
QWidget* widget;
int borderWidth; //邊框寬度
int titleHeight; //標題欄高度
bool hasBorder; //有邊框
bool hasTitleBar; //有標題欄
bool hasStatusBar; //有狀態列
QPainter * painter; //畫家
QPen borderPen; //畫筆
QPen textPen;
QWidget * centerWidget;
QColor backGroundColor;
QColor titleTextColor; //標題顏色
friend class TitleWidget;
bool isLeftPressDown; // 判斷左鍵是否按下
QPoint dragPosition; // 視窗移動拖動時需要記住的點
Direction dir; // 視窗大小改變時,記錄改變方向
bool titleClicked;
QString strBackGroundColor;
bool areaDrag;
/**
* @brief region 獲取區域
* @param cursorGlobalPoint
*/
void region(const QPoint &cursorGlobalPoint);
};
class TitleWidget : public QWidget
{
public:
TitleWidget(int height, QColor titleColor, Widget *parent=nullptr);
QPushButton* minButton, *maxButton, *closeButton; //最小化,最大。。。
QColor getTitleColor();
void setTitleColor(const QColor &value);
private:
void init();
friend class Widget;
QHBoxLayout* btnLayout,*btnLayoutH;
void paintEvent(QPaintEvent *event);
QPainter*painter;
QColor titleColor;
int height;
Widget* parent;
QLabel* title;
QLabel* icon;
QString strTitle;
QString strIcon;
void setHeight(int height);
void setTitle(const QString& title);
void setIcon(const QString& fileName);
QString getTitle();
QString getIcon();
QLabel* getTitleLabel();
QLabel* getIconLabel();
};
#endif // TERMINAL_H
#include "widget.h"
Widget::Widget(QWidget *parent) :QWidget(parent)
,borderWidth(1)
,titleHeight(30)
,hasBorder(true)
,hasTitleBar(true)
,hasStatusBar(true)
,centerWidget(new QWidget(this))
,isLeftPressDown(false)
,areaDrag(false)
,titleClicked(false)
{
}
void Widget::mousePressEvent(QMouseEvent *event)
{
switch(event->button()) {
case Qt::LeftButton:
isLeftPressDown = true;
if(dir != NONE) {
this->mouseGrabber();
} else {
dragPosition = event->globalPos()-pos();
}
if (areaDrag){
QWidget::mousePressEvent(event);
}
if (event->pos().y()<titleHeight+3*borderWidth){
titleClicked=true;
}
break;
default:
break;
}
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
QPoint gloPoint = QCursor::pos();
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
if (isHasBorder()){
if(!isLeftPressDown) {
this->region(gloPoint);
} else {
if(isMaximized() && gloPoint.y()<titleHeight){
showNormal();
isLeftPressDown = false;
return;
}
if(dir != NONE) {
QRect rMove(tl, rb);
switch(dir) {
case LEFT:
if(rb.x() - gloPoint.x() <= this->minimumWidth()){
rMove.setX(tl.x());
} else{
rMove.setX(gloPoint.x());
}
break;
case RIGHT:
rMove.setWidth(gloPoint.x() - tl.x());
break;
case UP:
if(rb.y() - gloPoint.y() <= this->minimumHeight()){
rMove.setY(tl.y());
}else{
rMove.setY(gloPoint.y());
}
break;
case DOWN:
rMove.setHeight(gloPoint.y() - tl.y());
break;
case LEFTTOP:
if(rb.x() - gloPoint.x() <= this->minimumWidth()){
rMove.setX(tl.x());
}else{
rMove.setX(gloPoint.x());
}
if(rb.y() - gloPoint.y() <= this->minimumHeight()){
rMove.setY(tl.y());
}else{
rMove.setY(gloPoint.y());
}
break;
case RIGHTTOP:
rMove.setWidth(gloPoint.x() - tl.x());
rMove.setY(gloPoint.y());
break;
case LEFTBOTTOM:
rMove.setX(gloPoint.x());
rMove.setHeight(gloPoint.y() - tl.y());
break;
case RIGHTBOTTOM:
rMove.setWidth(gloPoint.x() - tl.x());
rMove.setHeight(gloPoint.y() - tl.y());
break;
default:
break;
}
this->setGeometry(rMove);
}else if (isLeftPressDown&&titleClicked){
move(QCursor().pos()-dragPosition);
return;
}else if (areaDrag){
move(QCursor().pos() - dragPosition );
dragPosition = QCursor::pos()-pos();
setCursor(Qt::ClosedHandCursor);
QWidget::mouseMoveEvent(event);
return;
}
}
}
QWidget::mouseMoveEvent(event);
}
void Widget::mouseReleaseEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton) {
isLeftPressDown = false;
titleClicked=false;
if(dir != NONE) {
this->releaseMouse();
this->setCursor(QCursor(Qt::ArrowCursor));
emit sizeChanged(this->size());
}
}
}
void Widget::paintEvent(QPaintEvent *e)
{
_initialze();
paintFrame();
QWidget::paintEvent(e);
}
void Widget::leaveEvent(QEvent *)
{
isLeftPressDown = false;
}
void Widget::mouseDoubleClickEvent(QMouseEvent *e)
{
if (e->button()==Qt::LeftButton){
if (e->pos().y()<titleHeight){
if (isMaximized()){
showNormal();
}else{
showMaximized();
}
}
}
}
void Widget::drawEverything(QPainter *)
{
}
/**
* @brief paintFrame 畫邊框
*/
void Widget::paintFrame()
{
painter->begin(this);
//畫標題欄.
if (isHasTitleBar()){
titleWidget->show();
painter->setPen(titleWidget->getTitleColor());
painter->setBrush(titleWidget->getTitleColor());
painter->drawRect(borderWidth,borderWidth, width()+2*borderWidth, titleHeight);
}else {
painter->eraseRect(borderWidth,borderWidth, width()+2*borderWidth, titleHeight);
}
//畫邊框.
if (isHasBorder()){
painter->setPen(borderPen);
painter->setBrush(QBrush(borderPen.color()));
painter->drawRect(0,0,borderWidth,height());
painter->drawRect(width()-borderWidth,0,borderWidth,height());
painter->drawRect(0,0,width(),borderWidth);
painter->drawRect(0,height()-borderWidth,width(),borderWidth);
}else{
painter->eraseRect(0,0,borderWidth,height());
painter->eraseRect(width()-borderWidth,0,borderWidth,height());
painter->eraseRect(0,0,width(),borderWidth);
painter->eraseRect(0,height()-borderWidth,width(),borderWidth);
}
drawEverything(painter);
painter->end();
}
/**
* @brief init 初始化
*/
bool inited = false;
void Widget::_initialze()
{
if (inited){
return;
}
inited = true;
//去掉邊框
setWindowFlags(Qt::FramelessWindowHint);
setMouseTracking(true);
setWindowOpacity(0.8);
painter = new QPainter(this);
centerLayout = new QGridLayout;
centerLayout->setContentsMargins(1,1,1,1);
centerLayout->setMargin(2);
//邊框預設為灰色半透明
setBorderColor(QColor(50,50,50,50));
layout = new QVBoxLayout();
layout->setContentsMargins(1,1,1,1);
widget = new QWidget(this);
widget->setMouseTracking(true);
widget->setLayout(centerLayout);
centerWidget->setMouseTracking(true);
centerLayout->addWidget(centerWidget);
titleWidget = new TitleWidget(titleHeight,Qt::lightGray,this);
layout->addWidget(titleWidget);
layout->addWidget(widget);
layout->setStretch(0,1);
layout->setStretch(1,100);
layout->setSpacing(0);
layout->setMargin(1);
textPen=borderPen;
setLayout(layout);
this->dir = NONE;
setTitle("新視窗");
resize(500,400);
}
QColor Widget::getBackGroundColor() const
{
return backGroundColor;
}
/**
* @brief getTitleTextColor 標題顏色
* @return
*/
QColor Widget::getTitleTextColor()
{
_initialze();
return titleTextColor;
}
void Widget::setTitleTextColor(const QColor &value)
{
_initialze();
titleTextColor = value;
titleWidget->title->setStyleSheet(QString("color: rgb(%1,%2,%3,%4)").arg(value.red()).arg(value.green())
.arg(value.blue()).arg(value.alpha()));
}
/**
* @brief addWidget 新增視窗
* @param x
* @param y
* @param widget
*/
void Widget::addWidget(int x, int y, QWidget *widget)
{
_initialze();
if (centerWidget && widget){
widget->setParent(centerWidget);
widget->move(x,y);
widget->show();
}
}
void Widget::emitSizeChangeSignal()
{
emit sizeChanged(size());
}
/**
* @brief isAreaDrag 區域可拖動
* @return
*/
bool Widget::isAreaDrag()
{
return areaDrag;
}
void Widget::setAreaDrag(bool value)
{
areaDrag = value;
}
/**
* @brief getTitleWidget 獲取標題視窗
*/
QWidget* Widget::getTitleWidget()
{
_initialze();
return titleWidget;
}
/**
* @brief getCenterWidget 獲取中央視窗
* @return
*/
QWidget *Widget::getCentreWidget()
{
_initialze();
return centerWidget;
}
void Widget::setCentreWidget(QWidget *value)
{
_initialze();
if (value != nullptr){
if (centerLayout->count()){
centerLayout->removeWidget(centerWidget);
delete centerWidget;
centerWidget = nullptr;
}
value->setParent(this);
centerLayout->addWidget(value);
value->setStyleSheet(strBackGroundColor);
centerWidget = value;
}
}
/**
* @brief getTitle 獲取標題
* @return
*/
QString Widget::getTitle()
{
_initialze();
return titleWidget->getTitle();
}
void Widget::setTitle(const QString &title)
{
_initialze();
titleWidget->setTitle(title);
QWidget::setWindowTitle(title);
}
/**
* @brief getIcon 獲取圖示
* @return
*/
QString Widget::getIcon()
{
_initialze();
return titleWidget->getIcon();
}
void Widget::setIcon(const QString &fileName)
{
_initialze();
titleWidget->setIcon(fileName);
}
/**
* @brief getTitleLable 操作標題
* @return
*/
QLabel *Widget::getTitleLable()
{
_initialze();
return titleWidget->getTitleLabel();
}
QLabel *Widget::getIconLable()
{
_initialze();
return titleWidget->getIconLabel();
}
/**
* @brief setBackgroundColor 設定背景顏色
* @param color
*/
void Widget::setBackgroundColor(const QColor &color)
{
_initialze();
QPalette palette(QPalette::Background,color);
setPalette(palette);
if (centerWidget){
QString col = QString("background: rgba(%1,%2,%3,%4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(1/255.0*color.alpha());
centerWidget->setStyleSheet(col);
strBackGroundColor = col;
}
backGroundColor= color;
}
/**
* @brief getPen 畫筆設定
* @return
*/
QPen Widget::getBorderPen()
{
_initialze();
return borderPen;
}
void Widget::setBorderColor(const QColor &value)
{
_initialze();
borderPen.setColor(value);
}
void Widget::setButtonShow(const BUTTON &button, bool show)
{
_initialze();
switch(button){
case MIN:
titleWidget->minButton->setVisible(show);
return;
case MAX:
titleWidget->maxButton->setVisible(show);
return;
case CLOSE:
titleWidget->closeButton->setVisible(show);
return;
default:
return;
}
}
/**
* @brief getButton 獲取自帶button
* @param button
* @return
*/
QPushButton *Widget::getButton(const BUTTON &button)
{
_initialze();
switch(button){
case MIN:
return titleWidget->minButton;
case MAX:
return titleWidget->maxButton;
case CLOSE:
return titleWidget->closeButton;
default:
return nullptr;
}
}
/**
* @brief setButtonStyle 設定Button風格
* @param button
* @param style
*/
void Widget::setButtonStyle(const BUTTON &button, const QString &style)
{
_initialze();
switch(button){
case MIN:
titleWidget->minButton->setStyleSheet(style);
return;
case MAX:
titleWidget->maxButton->setStyleSheet(style);
return;
case CLOSE:
titleWidget->closeButton->setStyleSheet(style);
return;
default:
return;
}
}
/**
* @brief hasTitleBar 有標題欄
* @return
*/
bool Widget::isHasTitleBar()
{
return hasTitleBar;
}
void Widget::setHasTitleBar(bool value)
{
_initialze();
hasTitleBar = value;
titleWidget->setVisible(value);
}
/**
* @brief setTitleColor 設定標題欄顏色
* @param color
*/
void Widget::setTitleColor(const QColor &color)
{
_initialze();
titleWidget->setTitleColor(color);
}
/**
* @brief getLayout 獲取layout
* @return
*/
QVBoxLayout *Widget::getLayout()
{
_initialze();
return layout;
}
/**
* @brief hasBorder 有邊框
* @return
*/
bool Widget::isHasBorder()
{
return hasBorder;
}
void Widget::setHasBorder(bool value)
{
_initialze();
hasBorder = value;
}
/**
* @brief getTitleHeight 標題欄高度
*/
unsigned Widget::getTitleHeight()
{
return titleHeight;
}
void Widget::setTitleHeight(const unsigned &value)
{
_initialze();
titleHeight = value;
titleWidget->setHeight(titleHeight);
}
/**
* @brief getBorderWidth 邊框寬度
*/
unsigned Widget::getBorderWidth()
{
return borderWidth;
}
void Widget::setBorderWidth(const unsigned &value)
{
_initialze();
borderWidth = value;
layout->setMargin(value);
}
/**
* @brief region 獲取區域
* @param cursorGlobalPoint
*/
void Widget::region(const QPoint &cursorGlobalPoint)
{
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
int x = cursorGlobalPoint.x();
int y = cursorGlobalPoint.y();
if(((tl.x()+borderWidth)>=x) && (tl.x()<=x) && ((tl.y()+borderWidth)>=y) && (tl.y()<= y)) {
// 左上角
dir = LEFTTOP;
this->setCursor(QCursor(Qt::SizeFDiagCursor)); // 設定滑鼠形狀
} else if(x >= rb.x() - borderWidth && x <= rb.x() && y >= rb.y() - borderWidth && y <= rb.y()) {
// 右下角
dir = RIGHTBOTTOM;
this->setCursor(QCursor(Qt::SizeFDiagCursor));
} else if(x <= tl.x() + borderWidth && x >= tl.x() && y >= rb.y() - borderWidth && y <= rb.y()) {
//左下角
dir = LEFTBOTTOM;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
} else if(x <= rb.x() && x >= rb.x() - borderWidth && y >= tl.y() && y <= tl.y() + borderWidth) {
// 右上角
dir = RIGHTTOP;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
} else if(x <= tl.x() + borderWidth && x >= tl.x()) {
// 左邊
dir = LEFT;
this->setCursor(QCursor(Qt::SizeHorCursor));
} else if( x <= rb.x() && x >= rb.x() - borderWidth) {
// 右邊
dir = RIGHT;
this->setCursor(QCursor(Qt::SizeHorCursor));
}else if(y >= tl.y() && y <= tl.y() + borderWidth){
// 上邊
dir = UP;
this->setCursor(QCursor(Qt::SizeVerCursor));
} else if(y <= rb.y() && (int)y >= rb.y() - borderWidth) {
// 下邊
dir = DOWN;
this->setCursor(QCursor(Qt::SizeVerCursor));
}else {
// 預設
dir = NONE;
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
TitleWidget::TitleWidget(int height ,QColor titleColor, Widget *parent) : QWidget(parent),parent(parent)
{
this->height = height;
this->titleColor = titleColor;
init();
}
void TitleWidget::init()
{
minButton = new QPushButton("-",this);
connect(minButton,&QPushButton::clicked,[this](){parent->showMinimized();});
minButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(236,64,60,1); } QPushButton:hover{ \
border-radius: 10px;background-color:rgba(220,50,50,1)}QPushButton:pressed{border-radius: 10px;background-color:rgba(210,40,40,1)}"));
maxButton = new QPushButton("□",this);
connect(maxButton, &QPushButton::clicked,[this](){parent->isMaximized()?parent->showNormal():parent->showMaximized();parent->emitSizeChangeSignal();});
maxButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(156,196,1,1); } QPushButton:hover{ \
border-radius: 10px;background-color:rgba(140,180,0,1)}QPushButton:pressed{border-radius: 10px;background-color:green}"));
closeButton = new QPushButton("×",this);
connect(closeButton, &QPushButton::clicked,[this](){
QPropertyAnimation animation(parent,"windowOpacity");
animation.setDuration(100);
animation.setStartValue(0.8);
animation.setEndValue(0);
animation.start();
QEventLoop loop;
connect(&animation,SIGNAL(finished()),&loop,SLOT(quit()));
loop.exec();
parent->close();
});
closeButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(255,160,2,1); } QPushButton:hover{ \
border-radius: 10px;background-color:rgba(245,150,0,1)}QPushButton:pressed{border-radius: 10px;background-color:rgba(225,130,0,1)}"));
title = new QLabel(this);
title->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred);
title->setText("");
icon = new QLabel(this);
icon->setScaledContents(true);
icon->setFixedSize(24,22);
icon->setText("");
minButton->setFixedSize(20,20);
maxButton->setFixedSize(20,20);
closeButton->setFixedSize(20,20);
btnLayout=new QHBoxLayout;
btnLayout->setContentsMargins(0,0,0,0);
btnLayout->addWidget(minButton);
btnLayout->addWidget(maxButton);
btnLayout->addWidget(closeButton);
btnLayoutH = new QHBoxLayout;
btnLayoutH->setContentsMargins(6,0,6,0);
icon->hide();
title->hide();
btnLayoutH->addWidget(icon);
btnLayoutH->addWidget(title);
btnLayoutH->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding));
btnLayoutH->addLayout(btnLayout);
setLayout(btnLayoutH);
painter = new QPainter(this);
titleColor = QColor(10,141,169);
setMouseTracking(true);
}
void TitleWidget::paintEvent(QPaintEvent *)
{
setFixedHeight(height);
painter->begin(this);
painter->setPen(QPen(titleColor));
painter->setBrush(QBrush(titleColor));
painter->drawRect(rect());
painter->end();
}
void TitleWidget::setHeight(int height)
{
this->height = height;
repaint();
setIcon(strIcon);
}
void TitleWidget::setTitle(const QString &title)
{
this->title->setText(title);
if (title.isEmpty()){
this->title->hide();
}else{
this->title->show();
}
this->strTitle = title;
}
void TitleWidget::setIcon(const QString &fileName)
{
if (QFile::exists(fileName)){
icon->setPixmap(QPixmap(fileName));
icon->show();
}else{
icon->clear();
icon->hide();
}
strIcon = fileName;
}
QString TitleWidget::getTitle()
{
return this->strTitle;
}
QString TitleWidget::getIcon()
{
return strIcon;
}
QLabel *TitleWidget::getTitleLabel()
{
return title;
}
QLabel *TitleWidget::getIconLabel()
{
return icon;
}
QColor TitleWidget::getTitleColor()
{
return titleColor;
}
void TitleWidget::setTitleColor(const QColor &value)
{
titleColor = value;
repaint();
}