引言
创建一个基于QDialog的项目,自动生成ui文件,此时再添加新文件,创建一个基于QWidget的ui类,此类具有自定义标题栏,让该自定义类显示在窗口Dialog上,一开始具有红色的边框线,且四角围绕四个矩形,点击中间的自定义窗口时,窗口的边框线由黄色实线变为蓝色实线,再点击变为红色虚线,再点击变为蓝色实现,再点击红色虚线等等。此类是为了区分在整个窗口上绘制矩形与在窗口的子控件上绘制矩形的不同。
效果
以上就可以实现下面的效果:
程序刚开始运行:
点击中间的窗口后:
再点击后的效果:
项目的结构:
示例
下面是上述示例的代码。创建基于QDialog的项目,不去掉ui文件,自动生成ui文件,然后添加新文件基于QWidget类,在生成的QWidget类的ui文件中拖入其它控件,QWidget类的ui文件结构如下图:
除了widget_3控件栅格布局的上下左右边框设置了边距,所有布局之间的距离都为0。
ui文件如下:
当然上谜案直接设置了控件widget,widget_2以及label的样式。
下面是完整的代码:
自定义窗口类的代码。
form.h
#ifndef FORM_H
#define FORM_H#include <QWidget>namespace Ui {
class Form;
}class Form : public QWidget
{Q_OBJECTpublic:explicit Form(QWidget *parent = nullptr);~Form();protected:bool eventFilter(QObject *watched, QEvent *event);//在子控件上绘制边框void paintBorder(QWidget *widget);//绘制窗口的边框为其它颜色void paintEvent(QPaintEvent *event);//初始的时候绘制窗口的整体边框色void mousePressEvent(QMouseEvent *event);//点击鼠标的时候窗口微移,下次点击窗口复位
private:Ui::Form *ui;bool m_isNudge;//窗口是否微移bool m_isPress;//是否点击了子控件窗口
};#endif // FORM_H
form.cpp
#include "form.h"
#include "ui_form.h"
#include <QPainter>
#include <QPen>
#include <QMouseEvent>Form::Form(QWidget *parent) :QWidget(parent),ui(new Ui::Form)
{ui->setupUi(this);m_isNudge = false;m_isPress = false;ui->widget_3->installEventFilter(this);//安装事件过滤器
}Form::~Form()
{delete ui;
}bool Form::eventFilter(QObject *watched, QEvent *event)
{if (watched == ui->widget_3 && event->type() == QEvent::Paint) {paintBorder(ui->widget_3);//没有触发重绘事件,所以画笔没有被激活return true;}return false;
}void Form::paintBorder(QWidget *widget)
{if (!m_isPress) {return ;}QPainter painter(widget);QPen pen;QColor color;if (m_isNudge) {QColor cl(Qt::red);color = cl;pen.setStyle(Qt::DashDotLine);}else {QColor cl(Qt::darkBlue);color = cl;pen.setStyle(Qt::SolidLine);}pen.setColor(color);pen.setWidth(6);painter.setPen(pen);QRect rect = this->rect();painter.setRenderHint(QPainter::Antialiasing);painter.drawRect(rect.x(),rect.y(),rect.width(),rect.height());
}void Form::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);QPen pen;pen.setWidth(6);pen.setColor(QColor(Qt::yellow));painter.setPen(pen);painter.drawRect(ui->widget_3->x(),ui->widget_3->y(),ui->widget_3->width(),ui->widget_3->height());
}void Form::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {m_isPress = true;if (m_isNudge) {move(geometry().x() + 1,geometry().y() + 1);//通过移动触发重绘函数m_isNudge = false;}else {move(geometry().x() - 1,geometry().y() - 1);m_isNudge = true;}}
}
Dialog类的代码:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "form.h"QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();protected:void initChildControl();//初始化子控件void paintEvent(QPaintEvent *event);//绘制矩形
private:Ui::Dialog *ui;Form *m_form;//子窗口QVector<QRect> m_rectVec;//保存四个角的矩形
};
#endif // DIALOG_H
dialog,cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QPainter>
#include <QPen>
#include <QLabel>Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);initChildControl();
}Dialog::~Dialog()
{delete ui;
}void Dialog::initChildControl()
{m_form = new Form(this);m_form->setGeometry(width() / 4,height() / 4 - 20,m_form->width(),m_form->height());//初始化窗口上四个角上的矩形QRect rect1(2,2,180,180);QRect rect2(width()-182,2,180,180);QRect rect3(2,height()-182,180,180);QRect rect4(width()-182,height()-182,180,180);m_rectVec.append(rect1);m_rectVec.append(rect2);m_rectVec.append(rect3);m_rectVec.append(rect4);
}void Dialog::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;pen.setWidth(4);pen.setColor(QColor(85,85,255,255));painter.setPen(pen);painter.drawRects(m_rectVec);
}
main.cpp
#include "dialog.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Dialog w;w.show();return a.exec();
}
总结
在整个窗口上绘制矩形,需要重写paintEvent函数,在该函数中实现绘制矩形;在窗口的子控件上绘制矩形,需要在改类的构造函数中给该绘图的子控件安装事件过滤器,然后重写事件过滤函数,在该子控件的相应事件下实现绘制矩形。注意安装事件过滤器。