当前位置: 首页 > article >正文

Qt Widget 自定义TitleBar带阴影窗口

自定义一个titlebar窗口,

不带任何资源、QSS,纯代码

1. 设置主窗口

透明背景,让central_widget透明方式显示,给后续main添加dropshadow效果,用于放置实际的业务控件。

setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground);

    
QWidget *central_widget = new QWidget(this);
setCentralWidget(central_widget);
central_widget->setStyleSheet("background:transparent");

QVBoxLayout *central_layout = new QVBoxLayout(central_widget);
central_layout->setMargin(5);  // 这个 margin 一般为effect的 一半

QWidget *main = new QWidget(this);
central_layout->addWidget(main);

    QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect(this);
    effect->setBlurRadius(10);
    effect->setColor(QColor("#373737"));
    effect->setOffset(0,0);

main->setStyleSheet("background-color: black");
main->setGraphicsEffect(effect);

QVBoxLayout *vbox_main = new QVBoxLayout(main);
vbox_main->setMargin(0);
vbox_main->setSpacing(0);

...
// 添加后续业务代码。

2. 自定义右侧的按钮组

QWidget *titlebar = new QWidget(this);
titlebar->setStyleSheet("background-color: rgb(192,192,192)");
titlebar->setMaximumHeight(28);
vbox_main->addWidget(titlebar);

QHBoxLayout *titlebar_layout = new QHBoxLayout(titlebar);
titlebar_layout->setMargin(2);
titlebar_layout->setSpacing(2);

titlebar_layout->addStretch();


QPushButton* min_button = new QPushButton(this);
min_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMinButton));
titlebar_layout->addWidget(min_button);
connect(min_button, &QPushButton::pressed, this, [=]()
{
    showMinimized();
});

QPushButton* max_button = new QPushButton(this);
max_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
titlebar_layout->addWidget(max_button);
connect(max_button, &QPushButton::pressed, this, [=]()
{
    showFullScreen();
});

QPushButton* normal_button = new QPushButton(this);
normal_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton));
titlebar_layout->addWidget(normal_button);
connect(normal_button, &QPushButton::pressed, this, [=]()
{
    showNormal();
});
normal_button->setVisible(false);

QPushButton* close_button = new QPushButton(this);
close_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
titlebar_layout->addWidget(close_button);
connect(close_button, &QPushButton::pressed, this, [=]()
{
    close();
});

其中,最小化、全屏化、正常化、关闭按钮,可以取 Qt内置的标准icon,

style()->standardIcon(QStyle::SP_TitleBarMinButton);
SP_TitleBarMaxButton
SP_TitleBarNormalButton
SP_TitleBarCloseButton

可通过QPainter来变色

QIcon changeColor(const QIcon &icon, const QSize &size, const QColor &color)
{
    QPixmap pixmap = new icon.pixmap(size);
    QPainter painter(&pixmap);
    painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    painter.fillRect(pixmap.rect(), color);
    return QIcon(pixmap);
}

通过获取topLevelWidget, 然后调用下列方法

    void showMinimized();
    void showMaximized();
    void showFullScreen();
    void showNormal();

    bool close();

3. 标题栏的拖动

void QFramelessShadowWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && event->x() < _max_button->x() - 30 && event->y() < 30)
    {
        _dragging = true;
        _mouse_position = event->globalPos();
        _window_position = geometry().topLeft();
    }
}

void QFramelessShadowWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (_dragging && !_is_fullscreen)
    {
        QPoint offset = event->globalPos() - _mouse_position;
        move( _window_position + offset);
    }
}

void QFramelessShadowWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        _dragging = false;
}

4. 最后一个问题

当全屏后,会出现 放置实际的业务控件的区域显示不全,此时不需要显示dropshadow的阴影效果。可以响应主窗口的changeEvent事件,动态对layout的margin进行调整

void QFramelessShadowWindow::changeEvent(QEvent *event)
{
    bool from_normal = false;
    if (QEvent::WindowStateChange == event->type())
    {
        QWindowStateChangeEvent *state_event = static_cast<QWindowStateChangeEvent *>(event);
        if (Q_NULLPTR != state_event)
        {
            if (state_event->oldState() == Qt::WindowNoState)
            {
                from_normal = true;
            }
            else if (state_event->oldState() == Qt::WindowFullScreen)
            {
                _max_button->setVisible(true);
                _normal_button->setVisible(false);
                centralWidget()->layout()->setMargin(5);
                _is_fullscreen = false;
            }
        }
    }

    QMainWindow::changeEvent(event);
    Qt::WindowStates state = windowState();
    if (from_normal && state == Qt::WindowFullScreen)
    {
        _max_button->setVisible(false);
        _normal_button->setVisible(true);
        centralWidget()->layout()->setMargin(0);
        _is_fullscreen = true;
    }
}


http://www.kler.cn/a/137210.html

相关文章:

  • 算法学习(十六)—— 综合练习
  • 嵌入式单片机的运行方式详解
  • Unbuntu下怎么生成SSL自签证书?
  • 【人工智能】用Python实现图卷积网络(GCN):从理论到节点分类实战
  • 轻松上手:使用 Vercel 部署 HTML 页面教程
  • 【返璞归真】score检验:似然比的得分检验(Likelihood Ratio Score Test)
  • 3PC(三阶段提交)
  • redis运维(七)基础通用命令
  • Flutter笔记:使用相机
  • 数字IC前端学习笔记:时钟切换电路
  • Idea2023 Springboot web项目正常启动,页面展示404解决办法
  • 论文《A recurrent latent variable model for sequential data》笔记:详解VRNN
  • 京东商品详情数据接口【京东API接口开发系列】,监控京东价格走势,接口代码示例,可高并发批量获取
  • 二百零四、Flume——登录监听窗口报错Ncat: bind to :::44444: Address already in use. QUITTING.
  • 005 OpenCV直方图
  • 【Spring】SpringBoot的扩展点之ApplicationContextInitializer
  • INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能
  • 基于java的学生考勤信息管理系统设计【附源码】
  • 面向未来的自动化:拥抱机器人即服务(RaaS)
  • Linux:动静态库
  • FlinkCDC数据实时同步Mysql到ES
  • MQTT.js
  • 鸿蒙:Harmony开发基础知识详解
  • 使用Grpc实现高性能PHP RPC服务
  • 智慧安防监控系统EasyCVR(v3.4)开放协议的介绍及使用
  • Qt专栏3—Qt项目创建Hello World