日志
Qt中不规则窗体和部件的实现
2012-05-31 14:58
from:http://topkung.blog.163.com/blog/static/10526804320092263522295/
描述:a.png 窗口背景图 图片: 描述:mask.png 窗口掩码图 图片: 描述:toolbutton.png 按钮背景图 图片: 描述:toolbutton_mask.png 按钮掩码图 图片: 描述:runtime.png 示例运行时图 图片:
form.cpp: <BLOCKQUOTE QPixmap> <QtGui> #include <QtGui/QBitmap> #include "toolbutton.h" #include "form.h" Form::Form() { QPalette p = palette(); QPixmap img("a.png"); QBitmap mask("mask.png"); p.setBrush(QPalette::Window, QBrush(img)); setPalette(p); setMask(mask); setWindowFlags(Qt::FramelessWindowHint); resize(600, 400); ToolButton *button = new ToolButton(this); button->move(200, 200); } Form::~Form() { } toolbutton.h:
toolbutton.cpp: <BLOCKQUOTE QPixmap> <QtGui> #include <QtGui/QBitmap> #include "toolbutton.h" ToolButton::ToolButton(QWidget *parent) : QToolButton(parent) { /* // 如果是非按钮类部件,则使用此段代码 QPalette p = palette(); p.setBrush(QPalette::Button, QBrush(QPixmap("toolbutton.png"))); setPalette(p); /*/ // 如果是按钮类部件,则使用此段代码 setIcon(QIcon("toolbutton.png")); setIconSize(QSize(48, 48)); //*********************************/ setMask(QBitmap("toolbutton_mask.png")); setFixedSize(48, 48); } ToolButton::~ToolButton() { } main.cpp: <BLOCKQUOTE <QtGui QApplication>> #include "form.h" int main(int argc, char **argv) { QApplication app(argc, argv); Form form; form.show(); return app.exec(); } 基础篇 -- Qt 不规则窗体的实现 准备两个图,一个是要显示在窗体的图片,一个是蒙板,蒙板的黑色部分是要保留的,白色是要去掉的。 我准备了2张图,要显示的图片是"tmp.png",蒙板是"mask.png".如图 下面的程序都有个毛病,不能拖出幕窗口以外,为什么呢? 请注意一个是窗口和MASK图片的大小问题,还有就是只有无拖动栏的窗体MASK成不规则窗体才允许拖出屏幕窗口以外。 GTK程序参考 gtk_widget_shape_combine_mask Qt3 的手工代码实现: 复制内容到剪贴板 代码: #include <qapplication.h> #include <qwidget.h> #include <qpixmap.h> #include <qbitmap.h> #include <qpoint.h> class myclass:public QWidget { public: myclass(); protected: void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); private: QPixmap *pixmap; QBitmap *bitmap; QPoint last,pos0; }; myclass::myclass() { setGeometry(0,0,120,120); pixmap=new QPixmap("/doc/test/a/tmp.png"); bitmap=new QBitmap("/doc/test/a/mask.png"); setPaletteBackgroundPixmap(*pixmap); setMask(*bitmap); } void myclass::mouseMoveEvent(QMouseEvent *e) { if(e->state()==LeftButton) { QPoint newpos = e->globalPos(); QPoint upleft = pos0 + newpos - last; move(upleft); } } void myclass::mousePressEvent(QMouseEvent *e) { last = e->globalPos(); pos0 = e->globalPos() - e->pos(); } int main(int argc,char *argv[]) { QApplication a(argc,argv); myclass w; a.setMainWidget(&w); w.show(); return a.exec(); }Qt4的手工代码实现,注意差别: 复制内容到剪贴板 代码: #include <QApplication> #include <QWidget> #include <QPixmap> #include <QBitmap> #include <QPoint> #include <QPalette> #include <QMouseEvent> class myclass:public QWidget { public: myclass(); protected: void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); private: QPixmap *pixmap; QBitmap *bitmap; QPoint last,pos0; }; myclass::myclass() { setGeometry(0,0,120,120); pixmap=new QPixmap("/doc/test/a/tmp.png"); bitmap=new QBitmap("/doc/test/a/mask.png"); QPalette palette; palette.setBrush(backgroundRole(), QBrush(*pixmap)); setPalette(palette); setMask(*bitmap); } void myclass::mouseMoveEvent(QMouseEvent *e) { if (!(e->buttons() & Qt::LeftButton)) return; QPoint newpos = e->globalPos(); QPoint upleft = pos0 + newpos - last; move(upleft); } void myclass::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) last = e->globalPos(); pos0 = e->globalPos() - e->pos(); } int main(int argc,char *argv[]) { QApplication a(argc,argv); myclass w; w.show(); return a.exec(); }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)。 |
下一篇: (Qt)板子上运行程序出现的错误
上一篇: 基于嵌入式Qt的车载GUI平台的设计