现在的位置: 首页 > 综合 > 正文

Qt中如何利用 png 图片来实现自定义形状的窗口

2013年12月04日 ⁄ 综合 ⁄ 共 3139字 ⁄ 字号 评论关闭
  • Qt 中 QWidget::setMask() 的用法
  • 把 QWidget 自定义成各种形状,使用 png 透明图片作为窗体显示,效果如下

2012-10-29_1903

2012-10-29_1902 2012-10-29_1904 2012-10-29_1905


关键知识:

  1. 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 使窗口永远在最前端等。
  2. Qt::WidgetAttribute 使窗口支持透明背景以及在关闭后主动销毁。其它一些常用的 Attribute 有:Qt::WA_AcceptDrops 使 widget 支持拖拽操作,Qt::WA_MouseTracking 使 widget 及时响应鼠标移动事件(MouseMoveEvent)。
  3. Qt::setMask() 函数对窗口进行部分区域遮掩来实现各种形状的窗口。[From Qt Doc:Causes only the pixels of the widget for whichbitmap 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.]。
  4. Qt::ContextMenuPolicy 来配置窗口的右键菜单方案。[From Qt Doc:This enum type defines the various policies a widget can have with respect to showing a context menu.]。
  5. paintEvent() 回调函数来对窗口进行绘制。
  6. 重写
    mousePressEvent()
    mouseMoveEvent() 函数来实现窗口的拖拽移动(无边框窗口没有标题栏,默认拖拽窗体是没法移动窗口的)。


部分代码解释:

头文件:

   1: #ifndef SHAPEDWIDGET_H
   2: #define SHAPEDWIDGET_H
   3:  
   4: #include <QWidget>
   5: class QPoint;
   6: class QPixmap;
   7: class ShapedWidget : public QWidget
   8: {
   9:     Q_OBJECT
  10: public:
  11:     explicit ShapedWidget(QWidget *parent = 0);    
  12:     ~ShapedWidget();
  13:  
  14: private slots:
  15:     void changeSkin();
  16:  
  17: protected:
  18:     void mousePressEvent(QMouseEvent *);
  19:     void mouseMoveEvent(QMouseEvent *);
  20:     void paintEvent(QPaintEvent *);
  21:  
  22: private:
  23:     void initData();
  24:     void initVisualComponents();
  25:     void setupContextMenu();
  26:  
  27:     QPoint*     dragPos_;
  28:     QPixmap*    backgroundPixmap_;
  29: };
  30:  
  31: #endif // SHAPEDWIDGET_H

构造:

   1: ShapedWidget::ShapedWidget(QWidget *parent) :
   2:     QWidget(parent, Qt::FramelessWindowHint) //无边框窗体
   3: {
   4:     initData(); //初始化数据,这个demo里面就两个,具体下面有解释
   5:     initVisualComponents(); //初始化私有可视部件,这个demo里面没有私有的其它部件,所以只做了窗口的一些属性设置
   6:     setupContextMenu(); //设置右键菜单,分配各种QAction内存空间以及连接SIGNALS和SLOTS
   7:     setAttribute(Qt::WA_DeleteOnClose); //关闭事件发生后就主动从内存中销毁窗口
   8:     setAttribute(Qt::WA_TranslucentBackground); //透明背景支持
   9: }

 

拖拽移动窗体(下面有图示):

   1: void ShapedWidget::mousePressEvent(QMouseEvent *event)
   2: {
   3:     if(event->button() == Qt::LeftButton)
   4:     {
   5:         *dragPos_ = event->globalPos() - frameGeometry().topLeft();
   6:         event->accept();
   7:     }
   8: }
   9:  
  10: void ShapedWidget::mouseMoveEvent(QMouseEvent *event)
  11: {
  12:     if(event->buttons() & Qt::LeftButton)
  13:     {
  14:         move(event->globalPos() - *dragPos_);
  15:         event->accept();
  16:     }
  17: }

2012-10-29_2020

 

窗口绘制:

   1: void ShapedWidget::paintEvent(QPaintEvent *)
   2: {
   3:     QPainter painter(this);
   4:     painter.fillRect(0, 0, backgroundPixmap_->width(), backgroundPixmap_->height(), *backgroundPixmap_);
   5: }
 
更换皮肤:
   1: void ShapedWidget::changeSkin()
   2: {
   3:     QAction* source = qobject_cast<QAction*>(sender()); //获取发送该信号的信号源,并转换对象
   4:     backgroundPixmap_->load(source->data().toString()); //因为给每个 QAction 赋了图片的地址的字符串
   5:                                                         //所以可以通过 data() 来获取该值,并更新背景图片的内容
   6:     resize(backgroundPixmap_->width(), backgroundPixmap_->height()); //窗口大小尽可能小,尽管在 mask 外的窗体不会响应 mouse event
   7:     clearMask(); //清除原来的 mask
   8:     setMask(backgroundPixmap_->mask()); //根据新的背景图片来重新设置 mask
   9:     update(); //更新窗口
  10: }

 


katoon Netease Sina QQ CSDN
@Ggicci 本文属于个人学习笔记,如有错误,希望您能指正!转载请注明出处,谢谢 :) [CSDN博客]

抱歉!评论已关闭.