Qt中如何利用 png 图片来实现自定义形状的窗口
http://ggicci.blog.163.com/blog/static/21036409620129299159298/
|举报|字号 订阅
- Qt 中 QWidget::setMask() 的用法
- 把 QWidget 自定义成各种形状,使用 png 透明图片作为窗体显示,效果如下
关键知识:
- Qt::WindowFlags 使窗口支持无边框 [From Qt Doc:This enum type is used to specify various window-system properties for the widget. They are fairly unusual but necessary in a few cases. Some of these flags depend on whether the underlying window manager supports them.]。使用 Qt::WindowFlags 可以实现一些不同类型的窗口,如:用 Qt::FramelessWindowHint 来实现无边框窗口,用 Qt::Popup 来实现弹出式的窗口,用 Qt::Tool 来实现工具窗口,用Qt::CustomizeWindowHint 来关闭窗口标题栏以及与 Qt::WindowCloseButton(添加关闭按钮),Qt::WindowMaximumButtonSize(添加最大化按钮)联用来建立只有关闭按钮和最大化按钮的窗口,用 Qt::WindowStaysOnTopHint 使窗口永远在最前端等。
- Qt::WidgetAttribute 使窗口支持透明背景以及在关闭后主动销毁。其它一些常用的 Attribute 有:Qt::WA_AcceptDrops 使 widget 支持拖拽操作,Qt::WA_MouseTracking 使 widget 及时响应鼠标移动事件(MouseMoveEvent)。
- Qt::setMask() 函数对窗口进行部分区域遮掩来实现各种形状的窗口。[From Qt Doc:Causes only the pixels of the widget for which bitmap has a corresponding 1 bit to be visible. If the region includes pixels outside the rect() of the widget, window system controls in that area may or may not be visible, depending on the platform.]。
- Qt::ContextMenuPolicy 来配置窗口的右键菜单方案。[From Qt Doc:This enum type defines the various policies a widget can have with respect to showing a context menu.]。
- paintEvent() 回调函数来对窗口进行绘制。
- 重写 mousePressEvent() 和 mouseMoveEvent() 函数来实现窗口的拖拽移动(无边框窗口没有标题栏,默认拖拽窗体是没法移动窗口的)。
部分代码解释:
main.cpp-------------------开始
#include <QtGui/QApplication>
#include "shapedwidget.h"
#include <QPoint>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ShapedWidget *widget = new ShapedWidget;
widget->show();
return a.exec();
}
#include "shapedwidget.h"
#include <QtGui>
#include <assert.h>
/** public: */
ShapedWidget::ShapedWidget(QWidget *parent) :
QWidget(parent, Qt::FramelessWindowHint)
{
initData();
initVisualComponents();
setupContextMenu();
setAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_TranslucentBackground);
}
ShapedWidget::~ShapedWidget()
{
delete dragPos_;
delete backgroundPixmap_;
}
/** private slots: */
void ShapedWidget::changeSkin()
{
QAction* source = qobject_cast<QAction*>(sender());
backgroundPixmap_->load(source->data().toString());
resize(backgroundPixmap_->width(), backgroundPixmap_->height());
clearMask();
setMask(backgroundPixmap_->mask());
update();
}
/** private: */
void ShapedWidget::initData()
{
dragPos_ = new QPoint;
backgroundPixmap_ = new QPixmap(":/images/yoda.png");
}
void ShapedWidget::initVisualComponents()
{
this->setObjectName(tr("Shaped Widget"));
this->setWindowTitle(tr("Shaped widget using setMask() function"));
this->resize(backgroundPixmap_->width(), backgroundPixmap_->height());
this->setMask(backgroundPixmap_->mask());
}
void ShapedWidget::setupContextMenu()
{
setContextMenuPolicy(Qt::ActionsContextMenu);
QAction *act_yoda = new QAction(QIcon(":/images/yoda.png"), tr("Yoda"), this);
act_yoda->setData(tr(":/images/yoda.png"));
QAction *act_rabbit = new QAction(QIcon(":/images/rabbit.png"), tr("Rabbit"), this);
act_rabbit->setData(tr(":/images/rabbit.png"));
QAction *act_cyclops = new QAction(QIcon(":/images/cyclops.png"), tr("Cyclops"), this);
act_cyclops->setData(tr(":/images/cyclops.png"));
QAction *act_star_beast = new QAction(QIcon(":/images/star_beast.png"), tr("Star Beast"), this);
act_star_beast->setData(tr(":/images/star_beast.png"));
QAction *act_quit = new QAction(tr("&Quit"), this);
addAction(act_yoda);
addAction(act_rabbit);
addAction(act_cyclops);
addAction(act_star_beast);
addAction(act_quit);
connect(act_yoda, SIGNAL(triggered()), this, SLOT(changeSkin()));
connect(act_rabbit, SIGNAL(triggered()), this, SLOT(changeSkin()));
connect(act_cyclops, SIGNAL(triggered()), this, SLOT(changeSkin()));
connect(act_star_beast, SIGNAL(triggered()), this, SLOT(changeSkin()));
connect(act_quit, SIGNAL(triggered()), this, SLOT(close()));
}
/** protected: */
void ShapedWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
*dragPos_ = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
}
void ShapedWidget::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
move(event->globalPos() - *dragPos_);
event->accept();
}
}
void ShapedWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(0, 0, backgroundPixmap_->width(), backgroundPixmap_->height(), *backgroundPixmap_);
}
#ifndef SHAPEDWIDGET_H
#define SHAPEDWIDGET_H
#include <QWidget>
class QPoint;
class QPixmap;
class ShapedWidget : public QWidget
{
Q_OBJECT
public:
explicit ShapedWidget(QWidget *parent = 0);
~ShapedWidget();
private slots:
void changeSkin();
protected:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
private:
void initData();
void initVisualComponents();
void setupContextMenu();
QPoint* dragPos_;
QPixmap* backgroundPixmap_;
};
#endif // SHAPEDWIDGET_H