Qt中不规则窗体和部件的实现

描述:a.png    窗口背景图

图片:

Qt中不规则窗体和部件的实现 - yanglichuancom - yanglichuancom的博客

描述:mask.png    窗口掩码图

图片:

Qt中不规则窗体和部件的实现 - yanglichuancom - yanglichuancom的博客

描述:toolbutton.png    按钮背景图

图片:

Qt中不规则窗体和部件的实现 - yanglichuancom - yanglichuancom的博客

描述:toolbutton_mask.png    按钮掩码图

图片:

Qt中不规则窗体和部件的实现 - yanglichuancom - yanglichuancom的博客

描述:runtime.png    示例运行时图

图片:

Qt中不规则窗体和部件的实现 - yanglichuancom - yanglichuancom的博客

#define  FORM_H

#include <QtGui/QWidget>

class Form : public QWidget

{

    Q_OBJECT

public:

    Form();

    ~Form();

};

#endif

form.cpp:

#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:

#define  TOOLBUTTON_H

#include <QtGui/QToolButton>

class ToolButton : public QToolButton

{

    Q_OBJECT

public:

    ToolButton(QWidget *parent=0);

    ~ToolButton();

};

#endif

toolbutton.cpp:

#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:

#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)。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值