Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化

这篇具有很好参考价值的文章主要介绍了Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化

1、main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

2、widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

// 重写窗口事件函数,实现鼠标选中边框拉大拉小
#include <windows.h>
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

protected:
    // 重写鼠标事件,实现(隐藏窗口,最大化/最小化窗口,关闭窗口)
    void mousePressEvent(QMouseEvent *event) override; // 重写鼠标按下事件
    void mouseMoveEvent(QMouseEvent *event) override; // 重写鼠标移动事件
    void mouseReleaseEvent(QMouseEvent *event) override; // 重写鼠标释放事件

    // 重写窗口事件函数,实现鼠标选中边框拉大拉小
    bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;

    // 双击titleBar切换窗口最大化和最小化,重写mouseDoubleClickEvent函数,这个函数会在鼠标双击事件发生时被调用
    void mouseDoubleClickEvent(QMouseEvent *event) override;

    /* 1、将函数声明为virtual的作用是允许这两个函数在派生类中被重写(override),
     * 因为resizeEvent()和moveEvent()是QWidget类中的虚函数,因此在派生类中也要将其声明为virtual,
     * 这样就可以在派生类中重新定义这两个函数,以实现派生类中对窗口大小改变和窗口移动事件的处理
     */
    virtual void resizeEvent(QResizeEvent *event);
    virtual void moveEvent(QMoveEvent *event);


private:
    QWidget *content;       // 中央控件
    QWidget *titleBar;      // 自定义标题栏

    bool isPressed;     // 鼠标是否按下
    QPoint startPos;    // 鼠标按下时的位置
    QPoint endPos;      // 鼠标释放时的位置
    int edge;           // 窗口边缘宽度


// 声明标题栏槽函数(隐藏窗口,最大化/最小化窗口,关闭窗口)
private slots:
    void on_tbn_min_clicked();
    void on_tbn_max_clicked();
    void on_tbn_close_clicked();



};
#endif // WIDGET_H

3、widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QMouseEvent> // 1、包含QMouseEvent类的头文件
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QDesktopWidget>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    isPressed = false;
    edge = 5;

    // 设置窗口无边框和透明背景
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);

    // 2、去除默认的标题栏和边框
    // Qt::FramelessWindowHint:这是一个窗口提示,表示窗口没有边框
    // Qt::WindowMinimizeButtonHint:这是一个窗口提示,表示窗口有最小化按钮
    // Qt::WindowMaximizeButtonHint:这是一个窗口提示,表示窗口有最大化按钮
    // Qt::WindowCloseButtonHint:这是一个窗口提示,表示窗口有关闭按钮
    //this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);

    // 创建content容器,放到Widget窗口上
    content = new QWidget(this);
    // 设置 objectName 属性,QSS 文件中使用 #objectName 来定位到该控件
    content->setObjectName("content");
    // 设置content的大小策略,就是当窗口大小变化时,content怎么调整自己的大小,第一个参数是水平方向上的策略,第二个参数是垂直方向上的策略
    content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    // 设置content的位置和大小,参数是x坐标、y坐标、宽度和高度
    content->setGeometry(0, 0, width(), height());
    content->setStyleSheet("background-color:red;");

    // 在content上创建一个垂直布局,下面的2种方法都可以
    // content->setLayout(contentVLayout);
    QVBoxLayout *contentVLayout = new QVBoxLayout(content);

    // 3、自定义标题栏(隐藏窗口,最大化/最小化窗口,关闭窗口)
    // 创建titleBar容器,放到content容器里
    // titleBar = new QWidget(content);
    titleBar = new QWidget();
    titleBar->setObjectName("titleBar");
    titleBar->setStyleSheet("background-color:blue;");
    // 把titleBar添加到contentVLayout布局中
    contentVLayout->addWidget(titleBar);
    // 设置对齐方式为顶部对齐,让titleBar显示在垂直布局中的最上面
    contentVLayout->setAlignment(titleBar, Qt::AlignTop);
    // 设置内容边距为0,让它的子部件紧贴着它的边缘
    // 给contentVLayout这个垂直布局设置内边距为0,内边距是指布局和它的子部件之间的空隙
    // setContentsMargins()方法4个参数,分别表示左边距,上边距,右边距和下边距
    contentVLayout->setContentsMargins(0, 0, 0, 0);
    // 水平方向上可以自动扩展,在垂直方向上保持固定大小
    titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    // 设置标题栏控件的位置和大小
    titleBar->setGeometry(0, 0, width(), 60);

    // 在titleBar上创建一个水平布局
    QHBoxLayout *titleBarHLayout = new QHBoxLayout(titleBar);
    // Qt::AlignLeft    水平方向靠左
    // Qt::AlignRight   水平方向靠右
    // Qt::AlignHCenter 水平方向居中
    // Qt::AlignTop     垂直方向靠上
    titleBarHLayout->setAlignment(Qt::AlignHCenter);
    // 在titleBarHLayout上添加你想要的控件,比如图标、标题、最小化按钮、最大化按钮、关闭按钮等
    QLabel *iconLabel = new QLabel(titleBar); // 创建图标标签
    iconLabel->setPixmap(QPixmap(":/imagenns/icon.png")); // 设置图标标签的图片
    iconLabel->setScaledContents(true); // 设置图标标签的图片自动缩放
    iconLabel->setFixedSize(20, 20); // 设置图标标签的固定大小
    QLabel *titleLabel = new QLabel(titleBar); // 创建标题标签
    titleLabel->setText("QWidget布局"); // 设置标题标签的文本
    titleLabel->setFont(QFont("Arial", 12, QFont::Bold)); // 设置标题标签的字体
    QPushButton *minButton = new QPushButton(titleBar); // 创建最小化按钮
    minButton->setText("-"); // 设置最小化按钮的文本
    minButton->setFixedSize(20, 20); // 设置最小化按钮的固定大小
    QPushButton *maxButton = new QPushButton(titleBar); // 创建最大化按钮
    maxButton->setText("+"); // 设置最大化按钮的文本
    maxButton->setFixedSize(20, 20); // 设置最大化按钮的固定大小
    QPushButton *closeButton = new QPushButton(titleBar); // 创建关闭按钮
    closeButton->setText("x"); // 设置关闭按钮的文本
    closeButton->setFixedSize(20, 20); // 设置关闭按钮的固定大小
    // 将这些控件添加到水平布局中,并设置合适的间距和弹簧
    titleBarHLayout->addWidget(iconLabel); // 将图标标签添加到水平布局中
    titleBarHLayout->addSpacing(10); // 添加10像素的间距
    titleBarHLayout->addWidget(titleLabel); // 将标题标签添加到水平布局中
    titleBarHLayout->addStretch(); // 添加弹簧,使得后面的按钮靠右对齐
    titleBarHLayout->addWidget(minButton); // 将最小化按钮添加到水平布局中
    titleBarHLayout->addWidget(maxButton); // 将最大化按钮添加到水平布局中
    titleBarHLayout->addWidget(closeButton); // 将关闭按钮添加到水平布局中

    connect (minButton, SIGNAL (clicked ()), this, SLOT (on_tbn_min_clicked ())); // 连接最小化按钮的信号和槽
    connect (maxButton, SIGNAL (clicked ()), this, SLOT (on_tbn_max_clicked ())); // 连接最大化按钮的信号和槽
    connect (closeButton, SIGNAL (clicked ()), this, SLOT (on_tbn_close_clicked ())); // 连接关闭按钮的信号和槽
}

Widget::~Widget()
{
    delete ui;
}

// 最小化按钮的槽函数
void Widget::on_tbn_min_clicked()
{
    // 最小化窗口
    showMinimized();
}

// 最大化按钮的槽函数
void Widget::on_tbn_max_clicked()
{
   if (isMaximized()) {
        // 还原窗口
        showNormal();
        // 切换图标
        qobject_cast<QPushButton *>(sender())->setText("+"); // 使用qobject_cast转换类型,并修改文本

   } else {
        // 最大化窗口
        showMaximized();
        qobject_cast<QPushButton *>(sender())->setText("-");
   }
}

// 关闭按钮的槽函数
void Widget::on_tbn_close_clicked()
{
   close();
}

// 重写鼠标事件,实现窗口的移动
void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) // 如果是左键按下
    {
        isPressed = true; // 设置鼠标按下标志为真
        startPos = event->globalPos(); // 记录鼠标按下时的全局坐标
        endPos = this->frameGeometry().topLeft(); // 记录窗口左上角的坐标
    }
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (isPressed) // 如果鼠标按下
    {
        QPoint movePos = event->globalPos() - startPos; // 计算鼠标移动的偏移量
        this->move(endPos + movePos); // 移动窗口到新的位置
    }
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) // 如果是左键释放
    {
        isPressed = false; // 设置鼠标按下标志为假
        int x = this->x(); // 获取窗口当前的x坐标
        int y = this->y(); // 获取窗口当前的y坐标

        // 判断窗口是否超出屏幕边缘,如果超出则调整位置
        if (x < 0)
            x = 0;
        if (y < 0)
            y = 0;
        if (x + this->width() > QApplication::desktop()->width())
            x = QApplication::desktop()->width() - this->width();
        if (y + this->height() > QApplication::desktop()->height())
            y = QApplication::desktop()->height() - this->height();

        this->move(x, y); // 移动窗口到新的位置
    }
}
// 鼠标选中窗口边框拉大拉小
bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    MSG* msg = (MSG*)message;
    switch (msg->message)
    {
        case WM_NCHITTEST: // 处理鼠标在窗口边缘的事件
        {
            int xPos = GET_X_LPARAM(msg->lParam) - this->frameGeometry().x(); // 获取鼠标相对于窗口左上角的x坐标
            int yPos = GET_Y_LPARAM(msg->lParam) - this->frameGeometry().y(); // 获取鼠标相对于窗口左上角的y坐标

            // 根据鼠标位置判断返回值,改变鼠标样式和窗口拉伸方向
            if(xPos < edge && yPos < edge)                    // 左上角
                *result = HTTOPLEFT;
            else if(xPos < edge && yPos > height() - edge)   // 左下角
                *result = HTBOTTOMLEFT;
            else if(xPos > width() - edge && yPos < edge)     // 右上角
                *result = HTTOPRIGHT;
            else if(xPos > width() - edge && yPos > height() - edge)// 右下角
                *result = HTBOTTOMRIGHT;
            else if(xPos < edge)                                  // 左边
                *result = HTLEFT;
            else if(xPos > width() - edge)                        // 右边
                *result = HTRIGHT;
            else if(yPos < edge)                                  // 上边
                *result = HTTOP;
            else if(yPos > height() - edge)                       // 下边
                *result = HTBOTTOM;
            else              // 其他部分不做处理,返回false,留给其他事件处理器处理
                return false;

            return true;
        }
        default:
            break;
    }
    return QWidget::nativeEvent(eventType, message, result); // 将事件传递给父类处理
}


/* 如果要实现widget窗口跟随鼠标拖动并自动跟随窗口缩放,
 * 需要在QWidget类中重写resizeEvent()函数和moveEvent()函数
 */
// 在resizeEvent()函数中,重新设置widget窗口的大小和位置
void Widget::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event); // 调用父类的resizeEvent()函数
    if(this->content) // 判断是否有widget被添加到Material窗口中
    {
        // 获取Material窗口的大小
        int w = this->width();
        int h = this->height();
        // 设置widget的大小为Material窗口的大小
        this->content->setGeometry(0, 0, w, h);
    }
}
// 在moveEvent()函数中,重新设置widget窗口的位置
void Widget::moveEvent(QMoveEvent *event)
{
    QWidget::moveEvent(event);
    if(this->content)
    {
        this->content->move(0, 0);
    }
}

// 双击titleBar切换窗口最大化和最小化,重写mouseDoubleClickEvent函数,这个函数会在鼠标双击事件发生时被调用
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
    // 如果是左键双击
    if (event->button() == Qt::LeftButton)
    {
        // 获取父窗口的指针
        QWidget *pWindow = this->window();
        // 判断当前是否是最大化状态
        if (pWindow->isMaximized())
        {
            // 如果是,恢复到正常大小
            pWindow->showNormal();
        }
        else
        {
            // 如果不是,最大化窗口
            pWindow->showMaximized();
        }
    }
}

4、效果展示
qt重写标题栏,Qt,qt,ui

5、完成文章来源地址https://www.toymoban.com/news/detail-577034.html

到了这里,关于Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Qt获取鼠标移动事件,窗口内任意位置按下鼠标左键拖动窗口

    Qt获取鼠标移动事件,窗口内任意位置按下鼠标左键拖动窗口

    重写窗口的两个事件函数mousePressEvent和mouseMoveEvent即可: 在mousePressEvent 中,按下鼠标左键时,记录窗口坐标,其中窗口坐标的计算是由鼠标事件获取到鼠标在整个屏幕中的坐标(ev-globalpos()),然后再使用pos()获取到鼠标在窗口内的相对位置,两者之差就是窗口在整个屏幕上

    2024年02月12日
    浏览(15)
  • QGraphicsView中重写鼠标事件实现图片的移动

            本文讲的是如何在PyQt5的组件QGraphicsView中重写鼠标事件实现图片的移动。         PyQt5作为强大的GUI编程工具,免不了会拿来做一些图片的显示和处理问题,有的会使用QPainter作为动态显示图片的工具,QLabel是显示静态图片的主推。但是我在工作中遇到了超大

    2023年04月14日
    浏览(17)
  • Qt窗口设置无边框不能移动,鼠标穿透后不能响应点击事件

    Qt窗口设置无边框不能移动,鼠标穿透后不能响应点击事件

      最近在做一个迷你小工具,准备干点不可描述的事情,想要短小强悍,始终在最顶层显示,同时不要自带的关闭按钮和边框,百度一下,发现是需要设置如下两个属性:   那么问题来了,这样的话一运行窗体就在正中间,而且无法拖动,就像这样   哪怕对于我这种

    2024年02月10日
    浏览(12)
  • C# winform中无标题栏窗口如何实现鼠标拖动?

    在C#中,可以通过重写窗体的鼠标事件来实现无标题栏窗体的拖动。 具体步骤如下: 禁用窗体的默认标题栏:在窗体属性中设置FormBorderStyle为None。 重写鼠标事件:在窗体类中重写MouseDown、MouseMove和MouseUp事件。 定义变量存储鼠标点击时的坐标。 在MouseDown事件中记录鼠标的位

    2024年02月02日
    浏览(10)
  • VTK & QT QVTKWidget自定义鼠标和键盘交互事件

    目录 一、问题描述 二、代码实现 1. 自定义鼠标交互事件 2. 移除默认鼠标交互监听事件,塞入自定义监听事件 在使用VTK显示的过程中,通常会使用QT来进行界面设计。这里通常使用QVTKWidget将VTK的渲染窗口显示到QT的组件中。 QVTKWidget组件自带交互器vtkRenderWindowInteractor和Rende

    2024年02月14日
    浏览(16)
  • 【Qt】6.QTableWidget控件、其他控件、自定义控件封装、鼠标事件

    【Qt】6.QTableWidget控件、其他控件、自定义控件封装、鼠标事件

    目录 QTableWidget控件 代码 widget.cpp 结果 其他控件 stackWidget栈控件 下拉框 代码 widget.cpp 结果 自定义控件封装 代码 smallwidget.h smallwidget.cpp widget.cpp 结果 鼠标事件 代码 mylabel.h mylabel.cpp 结果 设置列数setColumnCount 添加水平头setHorizontalHeaderLabels 设置行数setRowCount 设置正文setItem(行号

    2024年02月07日
    浏览(12)
  • Qt自定义控件 —— 子控件与父控件的鼠标事件问题

    Qt自定义控件 —— 子控件与父控件的鼠标事件问题

    目录 0、引言: 1、问题描述: 2、解决方案: 3、解决后效果: 在 Qt自定义控件 —— 颜色选择组合控件 https://blog.csdn.net/YMGogre/article/details/128955257 一文中我们创建了自定义的组合控件,在该控件中包含了三个子控件 —— QGraphicsView 、 QLineEdit 和 QPushButton 。当我们通过 setIt

    2024年02月09日
    浏览(14)
  • 如何用Qt实现一个无标题栏、半透明、置顶(悬浮)的窗口

    如何用Qt实现一个无标题栏、半透明、置顶(悬浮)的窗口

    在Qt框架中,要实现一个无标题栏、半透明、置顶(悬浮)的窗口,需要一些特定的设置和技巧。废话不多说,下面我将以DrawClient软件为例,介绍一下实现这种效果的四个要点。 要点一:移除标题栏(去除关闭、最小化、最大化按钮) 在窗口的构造函数中设置窗口的样式,

    2024年02月19日
    浏览(11)
  • 06-5_Qt 5.9 C++开发指南_Splash 与登录窗口(MouseEvent鼠标事件;注册表;加密)

    06-5_Qt 5.9 C++开发指南_Splash 与登录窗口(MouseEvent鼠标事件;注册表;加密)

    一般的大型应用程序在启动时会显示一个启动画面,即 Splash 窗口。Splash 窗口是一个无边对话框,一般显示一个图片,展示软件的信息。Splash 窗口显示时,程序在后台做一些比较耗时的启动准备工作,Splash 窗口显示一段时间后自动关闭,然后软件的主窗口显示出来。Qt有一个

    2024年02月13日
    浏览(13)
  • TextBox添加鼠标按下、失去焦点、鼠标移动等事件及重写

    TextBox添加鼠标按下、失去焦点、鼠标移动等事件及重写 方法1: 方法2:    

    2024年02月15日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包