关于Qt透明效果以及border无法被绘制的问题

问题场景

mainwindow右键(重写了contextMenuEvent事件)需要弹出一个窗口,源生windonws窗口不符合UI,需要自定义式样(见填坑之路3 图片)。

实现方法

.h

#pragma once
#include “qdialog.h”
#include “ui_CommonMenuWidget.h”
#include
#include
#include
#include
#include

namespace Ui
{
class MenuWidget;
}

class FrameTitleBar : public QWidget
{
Q_OBJECT
public:
FrameTitleBar(QWidget *parent = 0);

protected:
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
private:
Q_SLOT void onCloseBtnClicked();
public:
QLabel* m_title;
private:
QPushButton* m_closeBtn;
QHBoxLayout* m_layout;

bool       m_isPressed;
QPoint     m_startMovePos;

};

class MenuWidget : public QDialog
{
Q_OBJECT
public:
MenuWidget(const QString& title, QWidget* parent = 0);
~MenuWidget();
Ui_CommonMenuWidget* ui;
void addMenuWidget(QWidget* widget);
void removeMenuWidget(QWidget* widget);
private:
void paintEvent(QPaintEvent* event) final;
FrameTitleBar* m_titleBar;
QHBoxLayout* m_menuLayout;
};

.cpp

#include “MenuWidget.h”
#include
#include <qdrawutil.h>

MenuWidget::MenuWidget(const QString& title, QWidget* parent / = 0/)
QDialog(parent)
, ui(new Ui_CommonMenuWidget)
{
ui->setupUi(this);
this->setObjectName(“menuwidget”);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
m_titleBar = new FrameTitleBar(this);
m_menuLayout = new QHBoxLayout;
m_titleBar->m_title->setText(title);
ui->verticalLayout->addWidget(m_titleBar);
ui->verticalLayout->addSpacing(10);
ui->verticalLayout->addLayout(m_menuLayout);
ui->verticalLayout->setContentsMargins(9, 9, 9, 9);
}

MenuWidget::~MenuWidget()
{
}

void MenuWidget::addMenuWidget(QWidget* widget)
{
m_menuLayout->addWidget(widget);
m_menuLayout->setContentsMargins(0, 0, 0, 10);
int width = widget->width() + 20;
int height = widget->height() + 66;
m_titleBar->setMinimumWidth(width);
resize(width, height);
}

void MenuWidget::removeMenuWidget(QWidget* widget)
{
ui->verticalLayout->removeWidget(widget);
}

void MenuWidget::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
qDrawBorderPixmap(&painter, rect(), QMargins(10, 38, 10, 10), QPixmap(":/background/BG.png"));
QDialog::paintEvent(event);
}

FrameTitleBar::FrameTitleBar(QWidget *parent) :
QWidget(parent),
m_isPressed(false)
{
m_title = new QLabel(this);
QFont font;
font.setPixelSize(12);
m_title->setFont(font);
m_title->setStyleSheet(“color:white”);
m_closeBtn = new QPushButton(this);
m_closeBtn->setObjectName(“closeBtn”);
m_closeBtn->setStyleSheet(“QPushButton#closeBtn{border-image:url(:/background/close.png)}”);
m_closeBtn->setFixedSize(17, 17);
m_layout = new QHBoxLayout;
m_layout->addWidget(m_title);
m_layout->addStretch();
m_layout->addWidget(m_closeBtn);
m_layout->setContentsMargins(25, 7, 10, 4);
setLayout(m_layout);
setMinimumHeight(28);
setMaximumHeight(28);
setObjectName(“titleBar”);
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);

connect(m_closeBtn, &QPushButton::clicked, this, &FrameTitleBar::onCloseBtnClicked);

}

void FrameTitleBar::mousePressEvent(QMouseEvent* event)
{
m_isPressed = true;
m_startMovePos = event->globalPos();

return QWidget::mousePressEvent(event);

}

void FrameTitleBar::mouseMoveEvent(QMouseEvent* event)
{
if (m_isPressed)
{
QPoint movePoint = event->globalPos() - m_startMovePos;

    if (parentWidget())
    {
        QPoint widgetPos = this->parentWidget()->pos();
        m_startMovePos = event->globalPos();
        parentWidget()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
    }
}

return QWidget::mouseMoveEvent(event);

}

void FrameTitleBar::mouseReleaseEvent(QMouseEvent* event)
{
m_isPressed = false;

return QWidget::mouseReleaseEvent(event);

}

//void FrameTitleBar::paintEvent(QPaintEvent* event)
//{
// QPainter painter(this);
// painter.drawPixmap(0, 0, width(), height(), QPixmap(":/background/titleBar_Bg.png"));
// QWidget::paintEvent(event);
//}

Q_SLOT void FrameTitleBar::onCloseBtnClicked()
{
parentWidget()->close();
}
代码解释 这是一个公共控件实现了最外层的边框窗体(采用Qt Designer) 半透明效果是图片自带的,但是直接设置到mainwindow上面会导致透明区域显示未白色,解决方法是重写paintEvent,将窗体背景直接绘制上去
新引入的问题 由于窗体是自适应里面窗口大小的,但是图片固定大小,所以再paint的时候导致了图片的缩放,猜想可能会导致边框失真, 解决方法是利用裁剪图片和重新拼接绘制。
实现原理:九宫格切割合并 1.将图片按需切割成9份, 其中1,3,7,9分别作为四个不可被拉伸变化的边角,其他位置或增或减来合并图片 例如
12222222223
45555555556
45555555556
45555555556
78888888889
QT已经实现了该方法:
void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)

The qDrawBorderPixmap function is for drawing a pixmap into the margins of a rectangle. Draws the given pixmap into the given target rectangle, using the given painter. The pixmap will be split into nine segments and drawn according to the margins structure.

猜你喜欢

转载自blog.csdn.net/weixin_41369611/article/details/94722910
今日推荐