自定义一个titlebar窗口,
不带任何资源、QSS,纯代码
透明背景,让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);
-
- ...
- // 添加后续业务代码。
- 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();
- 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;
- }
当全屏后,会出现 放置实际的业务控件的区域显示不全,此时不需要显示dropshadow的阴影效果。可以响应主窗口的changeEvent事件,动态对layout的margin进行调整
- void QFramelessShadowWindow::changeEvent(QEvent *event)
- {
- bool from_normal = false;
- if (QEvent::WindowStateChange == event->type())
- {
- QWindowStateChangeEvent *state_event = static_cast
(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;
- }
- }