QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5034|回复: 5

基础篇 -- Qt 不规则窗体的实现

[复制链接]
发表于 2008-1-30 17:26:33 | 显示全部楼层 |阅读模式
准备两个图,一个是要显示在窗体的图片,一个是蒙板,蒙板的黑色部分是要保留的,白色是要去掉的。

我准备了2张图,要显示的图片是"tmp.png",蒙板是"mask.png".如图





下面的程序都有个毛病,不能拖出幕窗口以外,为什么呢?

请注意一个是窗口和MASK图片的大小问题,还有就是只有无拖动栏的窗体MASK成不规则窗体才允许拖出屏幕窗口以外。

GTK程序参考 gtk_widget_shape_combine_mask

Qt3 的手工代码实现:


  1. #include <qapplication.h>
  2. #include <qwidget.h>
  3. #include <qpixmap.h>
  4. #include <qbitmap.h>
  5. #include <qpoint.h>

  6. class myclass:public QWidget
  7. {
  8.     public:
  9.         myclass();
  10.     protected:
  11.         void mouseMoveEvent(QMouseEvent *e);
  12.         void mousePressEvent(QMouseEvent *e);
  13.     private:
  14.         QPixmap *pixmap;
  15.         QBitmap *bitmap;
  16.         QPoint last,pos0;
  17. };

  18. myclass::myclass()
  19. {
  20.     setGeometry(0,0,120,120);
  21.     pixmap=new QPixmap("/doc/test/a/tmp.png");
  22.     bitmap=new QBitmap("/doc/test/a/mask.png");
  23.     setPaletteBackgroundPixmap(*pixmap);
  24.     setMask(*bitmap);
  25. }
  26. void myclass::mouseMoveEvent(QMouseEvent *e)
  27. {
  28.     if(e->state()==LeftButton)
  29.     {
  30.     QPoint newpos = e->globalPos();
  31.     QPoint upleft = pos0 + newpos - last;
  32.     move(upleft);
  33.     }
  34. }

  35. void myclass::mousePressEvent(QMouseEvent *e)
  36. {
  37.     last = e->globalPos();
  38.     pos0 = e->globalPos() - e->pos();
  39. }
  40.          

  41. int main(int argc,char *argv[])
  42. {
  43.     QApplication a(argc,argv);
  44.     myclass w;
  45.     a.setMainWidget(&w);
  46.     w.show();
  47.     return a.exec();
  48. }
复制代码


Qt4.4 代码实现,注意后面介绍4.5.1以后的版本还有差别:

  1. #include <QApplication>
  2. #include <QWidget>
  3. #include <QPixmap>
  4. #include <QBitmap>
  5. #include <QPoint>
  6. #include <QPalette>
  7. #include <QMouseEvent>

  8. class myclass:public QWidget
  9. {
  10.     public:
  11.         myclass();
  12.     protected:
  13.         void mouseMoveEvent(QMouseEvent *e);
  14.         void mousePressEvent(QMouseEvent *e);
  15.     private:
  16.         QPixmap *pixmap;
  17.         QBitmap *bitmap;
  18.         QPoint last,pos0;
  19. };
  20. myclass::myclass()
  21. {
  22.     setGeometry(0,0,120,120);
  23.     pixmap=new QPixmap("/doc/test/a/tmp.png");
  24.     bitmap=new QBitmap("/doc/test/a/mask.png");
  25.     QPalette palette;
  26.     palette.setBrush(backgroundRole(), QBrush(*pixmap));
  27.     setPalette(palette);
  28.     setMask(*bitmap);
  29. }
  30. void myclass::mouseMoveEvent(QMouseEvent *e)
  31. {
  32.     if (!(e->buttons() & Qt::LeftButton))
  33.         return;
  34.     QPoint newpos = e->globalPos();
  35.     QPoint upleft = pos0 + newpos - last;
  36.     move(upleft);
  37. }
  38. void myclass::mousePressEvent(QMouseEvent *e)
  39. {   
  40.     if (e->button() == Qt::LeftButton)
  41.     last = e->globalPos();
  42.     pos0 = e->globalPos() - e->pos();
  43. }

  44. int main(int argc,char *argv[])
  45. {
  46.     QApplication a(argc,argv);
  47.     myclass w;
  48.     w.show();
  49.     return a.exec();
  50. }
复制代码


Qt 4.5.1 以后的版本的一些改变使得代码又做出调整,不调整的代码也许可以在win上运行,但在Linux下就不行了

  1. #include <QApplication>
  2. #include <QWidget>
  3. #include <QPixmap>
  4. #include <QBitmap>
  5. #include <QPoint>
  6. #include <QPalette>
  7. #include <QMouseEvent>
  8. #include <QPainter>
  9. class myclass:public QWidget
  10. {
  11.     public:
  12.         myclass();
  13.     protected:
  14.         void mouseMoveEvent(QMouseEvent *e);
  15.         void mousePressEvent(QMouseEvent *e);
  16.         void paintEvent(QPaintEvent* e);
  17.     private:
  18.         QPixmap *pixmap;
  19.         QBitmap *bitmap;
  20.         QPoint last,pos0;
  21. };
  22. myclass::myclass()
  23. {
  24.     setGeometry(0,0,120,120);
  25.     bitmap=new QBitmap("/doc/test/a/mask.png");
  26.     setMask(*bitmap);
  27.     //setPalette(QPalette(Qt::blue));
  28.     //setWindowFlags(Qt::FramelessWindowHint);
  29. }
  30. void myclass::mouseMoveEvent(QMouseEvent *e)
  31. {
  32.     if (!(e->buttons() & Qt::LeftButton))
  33.         return;
  34.     QPoint newpos = e->globalPos();
  35.     QPoint upleft = pos0 + newpos - last;
  36.     move(upleft);
  37. }
  38. void myclass::paintEvent(QPaintEvent* e)
  39. {
  40.     pixmap=new QPixmap("/doc/test/a/tmp.png");
  41.     QPainter p(this);
  42.     p.drawPixmap(0,0,*pixmap);
  43. }
  44. void myclass::mousePressEvent(QMouseEvent *e)
  45. {
  46.     if (e->button() == Qt::LeftButton)
  47.     last = e->globalPos();
  48.     pos0 = e->globalPos() - e->pos();
  49. }

  50. int main(int argc,char *argv[])
  51. {
  52.     QApplication a(argc,argv);
  53.     myclass w;
  54.     w.show();
  55.     return a.exec();
  56. }
复制代码

Skin(表皮) 是制作比较酷的软件界面的有利工具. 一个软件可以同时使用多种Skin 以取得不同的外观, 使同一个软件有截然不同的风格. 用户可以根据自己的喜好选择 不同的风格. 本节介绍使用 Qt 制作 Skin 的方法.

软件界面的风格变化可以通过两种机制完成,一种是通过设置主题(Themes),它使用 界面库本身所具有的对界面组件(Components)的控制能力切换显示风格;另外一种是 通过提供不同系列的图片来切换显示界面,即这里所讲的 Skin。

制作表皮有几个重要的因素值得考虑:

1. 使用无边界的窗口
在 XWindow 下,无边界的窗口是指不受窗口管理器管理的边界不规则的窗口。由于不受窗口管理器管理管理,所以软件窗口界面没有附加的标题条(Title Bar)等。 在Qt中,建立无边界窗口的最简单的方法 是设置 QWidget 的 WFlags 的值是 WStyle_NoBorder。它定义在 qnamespace.h 中。不规则窗口的特点则要求对整个 窗口使用图像掩码。使用 X 窗口形状的扩展(X Shape Extension)来达到要求。在 Qt 中可以直接使用,


QBitmap bm;
bm = *(Pixmaps[MASK]);
setMask(bm);
setBackgroundPixmap(*Pixmaps[BACKGROUND]);


2. 窗口的移动
由于上述窗口不受窗口管理器的管理的特性,所以移动窗口需要特殊处理,一般的 方法是截取根Widget的鼠标按钮事件,自己处理鼠标点击和移动的事件。


void SkinDemo::mouseMoveEvent(QMouseEvent *e)
{
QPoint newpos = e->globalPos();
QPoint upleft = pos0 + newpos - last;
move(upleft);
}

void SkinDemo::mousePressEvent(QMouseEvent *e)
{
last = e->globalPos();
pos0 = e->globalPos() - e->pos();
}


这里我们取得的鼠标位置是绝对位置,即相对于根窗口的位置,同时也记录下窗口 左上角的位置,当鼠标移动时,取得新的绝对位置,则窗口左上角 的新位置应该 是原来位置与鼠标移动的位置之差。

3. 按钮的制作
在例子( qt-skin-example.tar.gz) 中,我们重新定义了鼠标按下和鼠标移动的事件处理 函数,并且含有按钮的所有信息,主工作区的所有信息等。主工作区的信息是它的位置和尺寸,主窗口的信息是它所使用的背景图片和图片的掩码(用来制造不规则窗口),所以整个主窗口的大小可以由图片的尺寸来决定。几个按钮的信息包含它们的 位置,它们的大小由图片的大小来决定。
对于表皮中的图像按钮,设置它的父类是 QButton,这种按钮由两幅图片构成,一幅图片是正常状态(Normal),一幅图片是按钮按下时的状态(Activated)。有时也可以设置成四种状态,即增加禁止状态(Disabled)和鼠标指针进入时的状态 (Hovered)。

[ 本帖最后由 haulm 于 2009-6-17 01:30 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2008-2-21 11:24:17 | 显示全部楼层
where is qt-skin-example.tar.gz, thx
回复

使用道具 举报

 楼主| 发表于 2008-3-12 19:23:29 | 显示全部楼层
原帖由 ashenix 于 2008-2-21 11:24 发表
where is qt-skin-example.tar.gz, thx


我也没有,也不需要这个压缩包。

[ 本帖最后由 haulm 于 2008-3-12 19:24 编辑 ]
回复

使用道具 举报

发表于 2008-5-2 10:59:52 | 显示全部楼层
问  :是继承么?    那 ::是什么   这个语言不懂
回复

使用道具 举报

 楼主| 发表于 2008-5-5 22:25:46 | 显示全部楼层
原帖由 bksy9 于 2008-5-2 10:59 发表
问  :是继承么?    那 ::是什么   这个语言不懂


某个类::后面跟着的是这个类的下属函数。
回复

使用道具 举报

 楼主| 发表于 2009-6-16 13:21:48 | 显示全部楼层
没办法,自己顶下,有些变化了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-4-24 22:09 , Processed in 0.083831 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表