• Qt Widget 自定义TitleBar带阴影窗口


    自定义一个titlebar窗口,

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

    1. 设置主窗口

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

    1. setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    2. setAttribute(Qt::WA_TranslucentBackground);
    3. QWidget *central_widget = new QWidget(this);
    4. setCentralWidget(central_widget);
    5. central_widget->setStyleSheet("background:transparent");
    6. QVBoxLayout *central_layout = new QVBoxLayout(central_widget);
    7. central_layout->setMargin(5); // 这个 margin 一般为effect的 一半
    8. QWidget *main = new QWidget(this);
    9. central_layout->addWidget(main);
    10. QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect(this);
    11. effect->setBlurRadius(10);
    12. effect->setColor(QColor("#373737"));
    13. effect->setOffset(0,0);
    14. main->setStyleSheet("background-color: black");
    15. main->setGraphicsEffect(effect);
    16. QVBoxLayout *vbox_main = new QVBoxLayout(main);
    17. vbox_main->setMargin(0);
    18. vbox_main->setSpacing(0);
    19. ...
    20. // 添加后续业务代码。

    2. 自定义右侧的按钮组

    1. QWidget *titlebar = new QWidget(this);
    2. titlebar->setStyleSheet("background-color: rgb(192,192,192)");
    3. titlebar->setMaximumHeight(28);
    4. vbox_main->addWidget(titlebar);
    5. QHBoxLayout *titlebar_layout = new QHBoxLayout(titlebar);
    6. titlebar_layout->setMargin(2);
    7. titlebar_layout->setSpacing(2);
    8. titlebar_layout->addStretch();
    9. QPushButton* min_button = new QPushButton(this);
    10. min_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMinButton));
    11. titlebar_layout->addWidget(min_button);
    12. connect(min_button, &QPushButton::pressed, this, [=]()
    13. {
    14. showMinimized();
    15. });
    16. QPushButton* max_button = new QPushButton(this);
    17. max_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
    18. titlebar_layout->addWidget(max_button);
    19. connect(max_button, &QPushButton::pressed, this, [=]()
    20. {
    21. showFullScreen();
    22. });
    23. QPushButton* normal_button = new QPushButton(this);
    24. normal_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton));
    25. titlebar_layout->addWidget(normal_button);
    26. connect(normal_button, &QPushButton::pressed, this, [=]()
    27. {
    28. showNormal();
    29. });
    30. normal_button->setVisible(false);
    31. QPushButton* close_button = new QPushButton(this);
    32. close_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
    33. titlebar_layout->addWidget(close_button);
    34. connect(close_button, &QPushButton::pressed, this, [=]()
    35. {
    36. close();
    37. });

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

    1. style()->standardIcon(QStyle::SP_TitleBarMinButton);
    2. SP_TitleBarMaxButton
    3. SP_TitleBarNormalButton
    4. SP_TitleBarCloseButton

    可通过QPainter来变色

    1. QIcon changeColor(const QIcon &icon, const QSize &size, const QColor &color)
    2. {
    3. QPixmap pixmap = new icon.pixmap(size);
    4. QPainter painter(&pixmap);
    5. painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    6. painter.fillRect(pixmap.rect(), color);
    7. return QIcon(pixmap);
    8. }

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

    1. void showMinimized();
    2. void showMaximized();
    3. void showFullScreen();
    4. void showNormal();
    5. bool close();

    3. 标题栏的拖动

    1. void QFramelessShadowWindow::mousePressEvent(QMouseEvent *event)
    2. {
    3. if (event->button() == Qt::LeftButton && event->x() < _max_button->x() - 30 && event->y() < 30)
    4. {
    5. _dragging = true;
    6. _mouse_position = event->globalPos();
    7. _window_position = geometry().topLeft();
    8. }
    9. }
    10. void QFramelessShadowWindow::mouseMoveEvent(QMouseEvent *event)
    11. {
    12. if (_dragging && !_is_fullscreen)
    13. {
    14. QPoint offset = event->globalPos() - _mouse_position;
    15. move( _window_position + offset);
    16. }
    17. }
    18. void QFramelessShadowWindow::mouseReleaseEvent(QMouseEvent *event)
    19. {
    20. if (event->button() == Qt::LeftButton)
    21. _dragging = false;
    22. }

    4. 最后一个问题

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

    1. void QFramelessShadowWindow::changeEvent(QEvent *event)
    2. {
    3. bool from_normal = false;
    4. if (QEvent::WindowStateChange == event->type())
    5. {
    6. QWindowStateChangeEvent *state_event = static_cast(event);
    7. if (Q_NULLPTR != state_event)
    8. {
    9. if (state_event->oldState() == Qt::WindowNoState)
    10. {
    11. from_normal = true;
    12. }
    13. else if (state_event->oldState() == Qt::WindowFullScreen)
    14. {
    15. _max_button->setVisible(true);
    16. _normal_button->setVisible(false);
    17. centralWidget()->layout()->setMargin(5);
    18. _is_fullscreen = false;
    19. }
    20. }
    21. }
    22. QMainWindow::changeEvent(event);
    23. Qt::WindowStates state = windowState();
    24. if (from_normal && state == Qt::WindowFullScreen)
    25. {
    26. _max_button->setVisible(false);
    27. _normal_button->setVisible(true);
    28. centralWidget()->layout()->setMargin(0);
    29. _is_fullscreen = true;
    30. }
    31. }

  • 相关阅读:
    ubuntu 内核版本
    灵性图书馆:好书推荐-《巴夏:来自未来的生命讯息》
    程序地址空间--Linux
    免费版Typora的使用
    vue模板语法上集
    iframe嵌套详解
    string的简单操作
    教育行业SaaS应用管理平台解决方案:助力企业实现经营、管理一体化
    语法基础(判断语句)
    python3.11教程1:python基础语法、程序控制、函数
  • 原文地址:https://blog.csdn.net/hellowithsmile/article/details/134465460