umbcom

C++博客 首页 新随笔 联系 聚合 管理
  2 Posts :: 0 Stories :: 12 Comments :: 0 Trackbacks

    在使用QT之前,或许我是习惯了MFC的消息传递机制,所以觉得事件伴随着全部的触发信息是理所当然,但这显然让我又让我自己欺骗了自己。在MFC下,通过分析事件传递的wParam和lParam就可以很方便的得到事件的信息,但在QT信号和槽的机制下,如果是初学者的您可能会跟我一样感到无所适从。
    大多使用过QT的人都知道,信号和槽的机制贯穿了整个QT的框架,虽说理解起来并不困难,但是在使用它的时候确是大有文章。例如,我们在单击了一个button时,我们想得到关于这个button的相关信息,比如button的text,icon,等等所有与这button相关的信息,下面我就举例说明一下我解决这问题的方法。您可能有更好的方法,如果您不介意的话,我希望您能奉献给大家,这其中当然包括我,或者给留下相关的链接地址,我十分高兴与您讨论。这种情况在MFC下通过映射之后利用wParam可能就能得到想要的结果,但是在QT中,好像表达的并没有那么明显。我就拿QPushButton来举例子,其他的类似。
    在QT助手中提供的信息是这样的,QPushButton提供了6个信号,分别为继承自QAbstractButton所拥有的
void clicked ( bool checked = false) //按钮被鼠标点击时的信号

void pressed ()                                 //按钮被按下时的信号

void released ()                                //按钮被释放时的信号

void toggled ( bool checked )           //按钮状态发生改变时的信号(一般也就指被按下或者被弹起)

    QWidget所拥有的void customContextMenuRequested ( const QPoint & pos )和QObject所拥有的void destroyed ( QObject * obj = 0 ),这两个是QWidget本身所拥有的属性,这里就不做讨论了。
    一看这四种信号只有两个传递了button的状态,而这两个状态也只是指示了按钮是否被按下的状态,但是我要得到按钮上的文字,这可怎么办呀?我是这么做的:
首先,我从QPushButton派生出一个自己的PushButton
//MyButton.h
#include <QtGui/QPushButton>
class MyButton : public QPushButton
{
   Q_OBJECT
public:
   MyButton(QWidget *parent = 0);
   ~MyButton();
signals:
   void ReturnText(const QString &itemtext);  //这里只能在头文件里面声明,cpp文件里不需定义
public slots:
   void SendItemText();                       //给自己的BUTTON多添加一个用于响应的槽
};

//MyButton.cpp
#include "MyButton.h"
MyButton::MyButton(QWidget *parent):QPushButton(parent)
{
    //在我的button初始化的时候就连接好clicked的事件,并对应自己所要响应的槽
   connect(this,SIGNAL(clicked()),this,SLOT(SendItemText()));
}

MyButton::~MyButton()
{

}
void MyButton::SendItemText()
{
    //当鼠标点击我的button时,button会做出响应并把自己的text发送到ReturnText的这个事件上
   emit ReturnText(this->text());
}

    在之前RuturnText上,QT会自动将你所发射的信息关联到所对应的信号上,如果你试图自己去写ReturnText的实现函数,那么程序将在编译时报错。

接下来我们就可以使用我们需要的东西了,我们先创建一个对话框:
//MyDialog.h
#include <QtGui/QDialog>
class QVBoxLayout;
class QLabel;
class MyButton;
class MyDialog :public QDialog
{
 Q_OBJECT
public:
 MyDialog(QWidget *parent = 0);
 ~MyDialog(void);
public slots:
 void LabelText(const QString &);
private:
    QVBoxLayout *layout;
    QLabel *label;
    MyButton *btn;
};

//MyDialog.cpp
#include "MyDialog.h"
#include "MyButton.h"
#include <QtGui/QVBoxLayout>
#include <QtGui/QLabel>
MyDialog::MyDialog(QWidget *parent):QDialog(parent)
{
 layout=new QVBoxLayout(this);
 label=new QLabel;
 btn=new MyButton(this);
 btn->setText("text");
 btn->setFixedSize(QSize(200,30));
 label->setFixedSize(QSize(200,30));
 layout->addWidget(label);
 layout->addWidget(btn);
 //在这里再与要显示的部件连接,这是就可以传递我们需要的信息了
 connect(btn,SIGNAL(ReturnText(const QString &)),this,SLOT(LabelText(const QString &)));
}

MyDialog::~MyDialog(void)
{
 delete btn;
 btn=NULL;
 delete label;
 label=NULL;
 delete layout;
 layout=NULL;
}

void MyDialog::LabelText(const QString &btnText)
{
 //将得到的信息显示出来
 this->label->setText(btnText);
}

最后,main函数,这个没什么特别:
#include <QtGui/QApplication>
#include "MyDialog.h"
int main(int argc,char** argv)
{
   QApplication app(argc,argv);
   MyDialog dialog;
   dialog.show();
   return app.exec();
}

好了,这里只传递了text,它还能做很多工作,您自己试试吧,希望对您有用并祝一切顺利。

以上程序在本机编译运行通过。vc2008+QT4.4.2.
posted on 2008-12-30 03:01 umbcom 阅读(3511) 评论(11)  编辑 收藏 引用 所属分类: QT

评论

# re: QWidget消息传递的一种方法 2008-12-30 03:07 陈梓瀚(vczh)
截然不同的消息都使用wparam和lparam从而使我们非得根据消息内容去查msdn之后执行强制类型转换,才应该是令人无所适从的。

除了MFC以外,几乎所有GUI库的消息参数都是不同类型的,会导致你在不具有相应知识的情况下程序不会通过编译,于是一切都很稳定。  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-30 03:25 umbcom
@陈梓瀚(vczh)
嘿嘿,多谢指教。这样看来的话,QT这种机制虽然要麻烦一点,但它就好像是个人定制的,我用多少拿多少,让思路又清晰一些。
没想到夜猫子也很多呀,哈哈 我先睡了。  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-30 07:36 过客
学习了,谢谢

http://www.vierit.com  回复  更多评论
  

# re: QWidget消息传递的一种方法[未登录] 2008-12-30 08:20 goodname
QString text = ((QPushButton *)sender())->text();

用这个看看  回复  更多评论
  

# re: QWidget消息传递的一种方法[未登录] 2008-12-30 10:19 tony
同意 goodname 的,你的这种需求,用sender()即可得到事件的触发者。  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-30 10:20 umbcom
@goodname
牛人啊,你说的方法果然可行,先膜拜一下,再嘴一个,哈哈。
我再把你的观点补充清晰一点,以免造成困惑。
将goodname这位仁兄的这种方法应用到以上程序里是这样的,
先将MyButton这个类就暂时先不需要了,将MyDialog类中的所有的MyButton替换成你想传递的部件,我这里用QPushButton.
将MyDialog的链接改为:
connect(btn,SIGNAL(clicked()),this,SLOT(LabelText()));
LabelText槽里面
void MyDialog::LabelText()
{
this->label->setText(((QPushButton*)sender())->text());
}
编译吧.
这里一定要在所控制部件的槽中进行强制转换,否则没人知道你传递的是那个部件,十分方便.
但前者也有前者的好处,例如要给所指定部件添加一些自己设定的属性,后者则无法办到,它只能利用现有的部件进行自身属性的消息传递,而前者则很直观。  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-30 12:18 qtopia
果然是新手,不知道sender()的用法  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-31 19:06 Yao
;-) 不过楼主看到sender这几个字确实应该有转换的冲动才对哈  回复  更多评论
  

# re: QWidget消息传递的一种方法 2008-12-31 23:56 umbcom
@Yao
那sender是QObject的 我之前并没有看到这个,:-)  回复  更多评论
  

# re: QWidget消息传递的一种方法 2009-03-26 10:16 aladdina
个人还是比较喜欢楼主的模式。况且Qt文档上有这么一句:Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

另外,(QPushButton*)sender()这种类型转换的方法应该尽量避免,C++已经提供了4个cast可以用,而且Qt也对cast做了扩展,这种危险的方式还是要避免。  回复  更多评论
  

# re: QWidget消息传递的一种方法 2009-03-26 14:00 umbcom
@aladdina
恩,是的.
最近写的这个程序使用sender这种方法时在批量控件快速切换并且机器显示芯片不怎好的情况下总会出现问题.我还是用了之前自己写的信号。
还有 谢谢提醒这类型转换,主要是看原来代码c风格的强制转换用得比较多,自己也不自主的用了。这个有类型的安全检查还是比没有的强。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理