QGraphicsView框架的界面
在view中创建一个item,思路:相当于用qgraphicsItem绘制了一个边框,在自定义的item中添加一个总的QWidget,里面的控件可以通过stylesheet设置透明等等,这样就可以在qt的界面编辑器中进行界面布局,方便,效果如下
具体代码:
DialogItem类的.c文件
#include "MyGraphicsItem.h"
#include <QFontMetrics>
#include <QPainter>
#include <QMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsScene>
#include <QPushButton>
#include <QGraphicsProxyWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsLayout>
#include <QDebug>
TitleBarItem::TitleBarItem(qreal x,qreal y,qreal width,qreal height):
m_bInPath(false)
{
m_rect = QRectF(x,y,width,height);
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::LeftButton);
}
void TitleBarItem::updateGeometry()
{
prepareGeometryChange();
//setPos();
}
void TitleBarItem::setItemTitle(const QString &strText)
{
m_strtitle = strText;
}
void TitleBarItem::setItemTitleFont(QFont font)
{
m_font = font;
}
void TitleBarItem::setRect(qreal x, qreal y, qreal width, qreal height)
{
prepareGeometryChange();
m_rect = QRectF(x,y,width,height);
m_closeRect = QRectF(m_rect.right()-50,m_rect.top()+5,40,40);
}
void TitleBarItem::setMainWidget(QWidget *widget)
{
m_mainWidget = widget;
}
QRectF TitleBarItem::boundingRect() const
{
return m_rect;
}
void TitleBarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
m_font.setPointSize(22);
m_font.setBold(true);
painter->setFont(m_font);
QFontMetrics metrics(m_font);
QRectF rec= metrics.boundingRect(QRect(0,0,150,100), Qt::AlignLeft, m_strtitle);
m_titleRect = QRectF(m_rect.left()+m_rect.width()/2-rec.width()/2,m_rect.height()/4-rec.height()/6,rec.width(),rec.height());
//m_rect.width()/2,m_rect.height()/4;
m_titleRect.translate(5, 5);//移动,调整
m_closeRect = QRectF(m_rect.right()-50,m_rect.top()+5,40,40);
QPainterPath path;
path.moveTo(QPoint(m_rect.left(),m_rect.top()));
path.lineTo(QPoint(m_rect.left()+m_rect.width(),m_rect.top()));
path.lineTo(QPoint(m_rect.left()+m_rect.width(),(m_rect.top()+m_rect.height())/2));
path.lineTo(QPoint(m_titleRect.right()+60,(m_rect.top()+m_rect.height())/2));
path.lineTo(QPoint(m_titleRect.right()+40,m_rect.top()+m_rect.height()));
path.lineTo(QPoint(m_titleRect.right()+20,m_rect.top()+m_rect.height()));
path.lineTo(QPoint(m_titleRect.right()+16,m_rect.top()+m_rect.height()-5));
path.lineTo(QPoint(m_titleRect.left()-16,m_rect.top()+m_rect.height()-5));
path.lineTo(QPoint(m_titleRect.left()-20,m_rect.top()+m_rect.height()));
path.lineTo(QPoint(m_titleRect.left()-40,m_rect.top()+m_rect.height()));
path.lineTo(QPoint(m_titleRect.left()-60,(m_rect.top()+m_rect.height())/2));
path.lineTo(QPoint(m_rect.left(),(m_rect.top()+m_rect.height())/2));
path.lineTo(QPoint(m_rect.left(),m_rect.top()));
if(m_bInPath)
painter->setBrush(QColor(85,200,170));
else
painter->setBrush(QColor(85,153,170));//QColor(255, 255, 255) 248,222,254
painter->setPen(Qt::NoPen);
painter->drawPath(path);
m_path = path;
if(m_bInPath)
painter->setPen(QColor(Qt::green));
else
painter->setPen(QColor(Qt::darkGreen));
painter->drawText(m_titleRect, m_strtitle);
// painter->drawLine(QPoint(m_titleRect.left()-12,m_rect.height()-2),QPoint(m_titleRect.right()+12,m_rect.height()-2));
//painter->drawEllipse(m_titleRect.left(),m_rect.height()-2,m_titleRect.width(),2);
painter->setBrush(QColor(Qt::darkGreen));
painter->drawRoundRect(m_titleRect.left()-14,m_rect.height()-3,m_titleRect.width()+14*2,2,1);
painter->drawEllipse(m_closeRect);
}
void TitleBarItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(m_path.contains(event->pos())){
m_bMousePressed = true;
}
else{
m_bMousePressed = false;
}
if(m_closeRect.contains(event->pos())){
if(m_mainWidget){
m_mainWidget->close();
}
}
}
void TitleBarItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(m_path.contains(event->pos())&& m_bMousePressed){
//移动主窗口
if(m_mainWidget != NULL){
m_mainWidget->move(m_mainWidget->pos().x()+event->pos().x()-event->buttonDownPos(Qt::LeftButton).x()\
,m_mainWidget->pos().y()+event->pos().y()-event->buttonDownPos(Qt::LeftButton).y());
}
}
else{
m_bMousePressed= false;
}
}
void TitleBarItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
m_bMousePressed = false;
}
void TitleBarItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
if(m_path.contains(event->pos())){
m_bInPath = true;
}
else{
m_bInPath = false;
}
prepareGeometryChange();
}
void TitleBarItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if(m_path.contains(event->pos())){
m_bInPath = true;
}
else{
m_bInPath = false;
}
prepareGeometryChange();
}
void TitleBarItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
if(m_path.contains(event->pos())){
m_bInPath = true;
}
else{
m_bInPath = false;
}
prepareGeometryChange();
}
void TitleBarItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if(m_path.contains(event->pos())){
if(m_mainWidget != NULL){
if(m_mainWidget->isMaximized()){
m_mainWidget->showNormal();
}
else{
m_mainWidget->showMaximized(); //m_mainWidget->showFullScreen();
}
}
}
else{
m_bInPath = false;
}
//
//prepareGeometryChange();
}
DialogItem::DialogItem(qreal x, qreal y, qreal width, qreal height)
:m_bInPath(false)
,m_bIsPressed(false)
{
m_rect = QRectF(x,y,width,height);
//setTransformOriginPoint(100,100);
// m_btnOK = new QPushButton("确定");
// m_btnOK->setStyleSheet(" font-size: 16px;\
// color: #BDC8E2;\
// height: 30px; \
// width: 60px; \
// border-radius: 4px;\
// background-color: #2E3648;");
// m_btnCancel = new QPushButton("取消");
// m_btnCancel->setStyleSheet(" font-size: 16px;\
// color: #BDC8E2;\
// height: 30px; \
// width: 60px; \
// border-radius: 4px;\
// background-color: #2E3648;");
// m_graphWidget = new QWidget();
// m_graphWidget->setObjectName("mainWidget");
// m_graphWidget->setStyleSheet("QWidget#mainWidget{border-radius: 5px;\
// border:2px solid gray;\
// background-color: transparent}");//
// QVBoxLayout* vLayout = new QVBoxLayout();
// QHBoxLayout* hLayout = new QHBoxLayout();
// hLayout->addWidget(m_btnOK);
// hLayout->addWidget(m_btnCancel);
// vLayout->addStretch(6);
// vLayout->addLayout(hLayout,1);
// //vLayout->setMargin(0);
// vLayout->setContentsMargins(5,5,5,5);
// m_graphWidget->setLayout(vLayout);
m_timeline = new QTimeLine(1000);
m_timeline->setFrameRange(0, 100);
m_timeline->setLoopCount(1);
m_timeline->setCurveShape(QTimeLine::EaseInOutCurve); //frameChanged()发出的值像sin曲线一样,1,2,...,99,100,99,...,2,1
m_timeline->setUpdateInterval(25); //更新频率(也就是frameChanged(int)的执行速度),每25ms更新一次,相当于每秒40帧,
m_animation = new QGraphicsItemAnimation;
m_animation->setItem(this);
m_animation->setTimeLine(m_timeline);
//旋转的定时器
m_timeline1 = new QTimeLine(500);
m_timeline1->setFrameRange(0, 100);
m_timeline1->setLoopCount(1);
m_timeline1->setCurveShape(QTimeLine::EaseInOutCurve); //frameChanged()发出的值像sin曲线一样,1,2,...,99,100,99,...,2,1
m_timeline1->setUpdateInterval(25);
connect(m_timeline1, SIGNAL(frameChanged(int)), this, SLOT(scaleAnimation(int)));
m_rotate_type = Qt::ZAxis;
//刚开始播放缩放动画
m_timeline1->start();
}
void DialogItem::updateGeometry()
{
}
void DialogItem::setItemTitle(const QString &strText)
{
m_strtitle = strText;
}
void DialogItem::setItemTitleFont(QFont font)
{
}
void DialogItem::setRect(qreal x, qreal y, qreal width, qreal height)
{
m_rect = QRectF(x,y,width,height);
m_closeButtonRect = QRectF(m_rect.right()-35,m_rect.top()+10,35,35);
prepareGeometryChange();
}
void DialogItem::setDialogWidget(QWidget *widget)
{
if(scene())
m_pScene = scene();
m_graphWidget = widget;
m_widget = m_pScene->addWidget(m_graphWidget);
m_widget->setParentItem(this);
}
void DialogItem::setRotateType(Qt::Axis type)
{
m_rotate_type = type;
//开始动画
m_timeline1->start();
}
void DialogItem::xuanzhuan()
{
m_animation->clear();
m_animation->setRotationAt(1,360);
m_timeline->start();
}
void DialogItem::pingyi()
{
m_animation->clear();
m_animation->setTranslationAt(0.25, 200, 0);
m_animation->setTranslationAt(0.5, 0, 0);
m_animation->setTranslationAt(0.75, -200, 0);
m_animation->setTranslationAt(1.0, 0, 0);
m_timeline->start();
}
void DialogItem::fanzhuan(int flag)
{
}
void DialogItem::suofang()
{
m_animation->clear();
m_animation->setScaleAt(1,0,0);
m_timeline->start();
}
void DialogItem::cuoqie()
{
m_animation->clear();
m_animation->setShearAt(0.25,0.2,0);
m_animation->setShearAt(0.5,0,0);
m_animation->setShearAt(0.75,-0.2,0);
m_animation->setShearAt(1,0,0);
m_timeline->start();
}
QRectF DialogItem::boundingRect() const
{
return m_rect;
}
void DialogItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
m_font.setPointSize(15);
m_font.setBold(true);
painter->setFont(m_font);
QFontMetrics metrics(m_font);
QRectF rec= metrics.boundingRect(QRect(0,0,150,100), Qt::AlignLeft, m_strtitle);
m_titleRect = QRectF(m_rect.left()+m_rect.width()/2-rec.width()/2,m_rect.top()+rec.height()/4,rec.width(),rec.height());
//m_rect.width()/2,m_rect.height()/4;
m_titleRect.translate(5, 5);//移动,调整
if(m_graphWidget)
m_graphWidget->resize(m_rect.width()-30,m_rect.height()-m_titleRect.height()-30);
m_widget->setPos(m_rect.left()+15,m_titleRect.top()+m_titleRect.height()+10);
QPainterPath path;
/*
*/
path.moveTo(QPoint(m_rect.left()+15,m_titleRect.bottom()));
path.lineTo(QPoint(m_titleRect.left()-20,m_titleRect.bottom()));
path.lineTo(QPoint(m_titleRect.left()-10,m_titleRect.top()));
path.lineTo(QPoint(m_titleRect.right()+10,m_titleRect.top()));
path.lineTo(QPoint(m_titleRect.right()+20,m_titleRect.bottom()));
path.lineTo(QPoint(m_rect.right()-15,m_titleRect.bottom()));
path.lineTo(QPoint(m_rect.right(),m_titleRect.bottom()+15));
path.lineTo(QPoint(m_rect.right(),m_rect.bottom()-15));
path.lineTo(QPoint(m_rect.right()-15,m_rect.bottom()));
path.lineTo(QPoint(m_rect.left()+15,m_rect.bottom()));
path.lineTo(QPoint(m_rect.left(),m_rect.bottom()-15));
path.lineTo(QPoint(m_rect.left(),m_titleRect.bottom()+15));
path.lineTo(QPoint(m_rect.left()+15,m_titleRect.bottom()));
painter->setPen(QColor(Qt::gray));
QLinearGradient backgroundGradient(0.5, 0.0, 0.5, 1.0);
backgroundGradient.setColorAt(0.0,QColor(78,228,228,100) );//QRgb(0x4EE4E4)
backgroundGradient.setColorAt(1.0,QColor(58,96,249,100) );//QRgb(0x3A60F9)
backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
painter->setBrush(backgroundGradient);
painter->drawPath(path);
if(m_bIsPressed)
painter->setPen(QColor(Qt::yellow));
else
painter->setPen(QColor(Qt::darkYellow));
painter->drawText(m_titleRect, m_strtitle);
painter->drawEllipse(m_closeButtonRect);
}
void DialogItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//判断
if(m_titleRect.contains(event->pos())){
m_bIsPressed = true;
prepareGeometryChange();
}
if(m_closeButtonRect.contains(event->pos())){
//关闭按钮被点击
//qDebug()<<"关闭按钮被点击";
//suofang();
//hide();
//反向动画
m_timeline1->setDirection(QTimeLine::Backward);
m_timeline1->start();
}
}
void DialogItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(m_bIsPressed){
//qDebug()<<__FUNCTION__<<event->lastPos()<<event->pos();
this->moveBy(event->pos().x()-event->lastPos().x(),event->pos().y()-event->lastPos().y());
}
}
void DialogItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
m_bIsPressed = false;
prepareGeometryChange();
}
void DialogItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
}
void DialogItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if(m_titleRect.contains(event->pos())){
}
else{
}
}
void DialogItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
}
//缩放槽函数
void DialogItem::scaleAnimation(int frame)
{
QPointF pt = this->boundingRect().center();
qreal scaleX_Y = (frame) / 100.0;
QTransform tran;
tran.translate(pt.x(), pt.y());
tran.scale(scaleX_Y, scaleX_Y);
tran.rotate(frame*3.6,m_rotate_type);
//tran.shear(0.25,0);
this->setTransform(tran);
QTransform t;
t.translate(-pt.x(), -pt.y());
this->setTransform(t, true);
}
DialogItem类的 .h文件
#ifndef MYGRAPHICSITEM_H
#define MYGRAPHICSITEM_H
#include <QGraphicsItem>
#include <QPushButton>
#include <QGraphicsWidget>
#include <QWidget>
#include <QFont>
#include <QTimeLine>
#include <QGraphicsItemAnimation>
#include <QObject>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE
class TitleBarItem :public QObject,public QGraphicsItem
{
Q_OBJECT
public:
TitleBarItem(qreal x, qreal y, qreal width, qreal height);//QGraphicsItem *parent
void updateGeometry();
void setItemTitle(const QString &strText);
void setItemTitleFont(QFont font);
void setRect(qreal x, qreal y, qreal width, qreal height);
void setMainWidget(QWidget* widget);
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
private:
QRectF m_rect; //整个区域的rect
QRectF m_titleRect; //标题的绘制rect
QRectF m_closeRect; //关闭按钮的rect
QString m_strtitle;
QFont m_font;
QPainterPath m_path;
bool m_bInPath;
bool m_bMousePressed;
QWidget* m_mainWidget;
};
class DialogItem : public QObject,public QGraphicsItem{
Q_OBJECT
public:
DialogItem(qreal x,qreal y,qreal width,qreal height);
void updateGeometry();
void setItemTitle(const QString &strText);
void setItemTitleFont(QFont font);
void setRect(qreal x, qreal y, qreal width, qreal height);
//scene中additem调用后,再调用下面的函数(可以通过传一个QWidget的参数,实现通用)
void setDialogWidget(QWidget* widget);
void setRotateType(Qt::Axis type);
//
void xuanzhuan();
void pingyi();
void fanzhuan(int flag);
void suofang();
void cuoqie();//错切
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private slots:
void scaleAnimation(int frame);
private:
QRectF m_rect; //整个区域的rect
QRectF m_titleRect; //标题的绘制rect
QRectF m_closeButtonRect; //关闭按钮的rect
QString m_strtitle;
QFont m_font;
QPainterPath m_path;
bool m_bInPath;
bool m_bIsPressed;
QGraphicsScene * m_pScene;
QPushButton* m_btnOK;
QPushButton* m_btnCancel;
QGraphicsProxyWidget* m_widget;
QWidget * m_graphWidget;
QGraphicsItemAnimation* m_animation;
QTimeLine * m_timeline;
QTimeLine * m_timeline1;
Qt::Axis m_rotate_type;
};