来自 澳门金莎娱乐手机版 2019-11-14 16:49 的文章
当前位置: 金沙澳门官网网址 > 澳门金莎娱乐手机版 > 正文

Qt学习之路,点击判断

前面说了几个标准对话框,下面不打算继续说明一些组件的使用,因为这些使用很难讲完,很多东西都是与实际应用相关的。实际应用的复杂性决定了我们根本不可能把所有组件的所有使用方法都说明白。这次来说说Qt相对高级一点的特性:事件。   事件(event)是有系统或者Qt本身在不同的时刻发出的。当用户按下鼠标,敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在对用户操作做出响应的时候发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。   一般来说,使用Qt编程时,我们并不会把主要精力放在事件上,因为在Qt中,需要我们关心的事件总会发出一个信号。比如,我们关心的是QPushButton的鼠标点击,但我们不需要关心这个鼠标点击事件,而是关心它的clicked()信号。这与其他的一些框架不同:在Swing中,你所要关心的是JButton的ActionListener这个点击事件。   Qt的事件很容易和信号槽混淆。这里简单的说明一下,signal由具体对象发出,然后会马上交给由connect函数连接的slot进行处理;而对于事件,Qt使用一个事件队列对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件进行处理。但是,必要的时候,Qt的事件也是可以不进入事件队列,而是直接处理的。并且,事件还可以使用“事件过滤器”进行过滤。总的来说,如果我们使用组件,我们关心的是信号槽;如果我们自定义组件,我们关心的是事件。因为我们可以通过事件来改变组件的默认操作。比如,如果我们要自定义一个QPushButton,那么我们就需要重写它的鼠标点击事件和键盘处理事件,并且在恰当的时候发出clicked()信号。   还记得我们在main函数里面创建了一个QApplication对象,然后调用了它的exec()函数吗?其实,这个函数就是开始Qt的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt将创建一个事件对象。Qt的所有事件都继承于QEvent类。在事件对象创建完毕后,Qt将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。关于这一点,我们会在以后的章节中详细说明。   在所有组件的父类QWidget中,定义了很多事件处理函数,如keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等。这些函数都是protected virtual的,也就是说,我们应该在子类中重定义这些函数。下面来看一个例子。   图片 1#include <QApplication>
图片 2#include <QWidget>
图片 3#include <QLabel>
图片 4#include <QMouseEvent>
图片 5
图片 6class EventLabel : public QLabel
图片 7{
图片 8
图片 9protected:
图片 10        void mouseMoveEvent(QMouseEvent *event);
图片 11        void mousePressEvent(QMouseEvent *event);
图片 12        void mouseReleaseEvent(QMouseEvent *event);
图片 13};
图片 14
图片 15void EventLabel::mouseMoveEvent(QMouseEvent *event)
图片 16{
图片 17        this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>")
图片 18                                                        .arg(QString::number(event->x()), QString::number(event->y())));
图片 19}
图片 20
图片 21void EventLabel::mousePressEvent(QMouseEvent *event)
图片 22{
图片 23        this->setText(QString("<center><h1>Press: (%1, %2)</h1></center>")
图片 24                                                        .arg(QString::number(event->x()), QString::number(event->y())));
图片 25}
图片 26
图片 27void EventLabel::mouseReleaseEvent(QMouseEvent *event)
图片 28{
图片 29        QString msg;
图片 30        msg.sprintf("<center><h1>Release: (%d, %d)</h1></center>",
图片 31                                event->x(), event->y());
图片 32        this->setText(msg);
图片 33}
图片 34
图片 35int main(int argc, char *argv[])
图片 36{
图片 37        QApplication app(argc, argv);
图片 38        EventLabel *label = new EventLabel;
图片 39        label->setWindowTitle("MouseEvent Demo");
图片 40        label->resize(300, 200);
图片 41        label->show();
图片 42        return app.exec();
图片 43}   这里我们继承了QLabel类,重写了mousePressEvent、mouseMoveEvent和MouseReleaseEvent三个函数。我们并没有添加什么功能,只是在鼠标按下(press)、鼠标移动(move)和鼠标释放(release)时把坐标显示在这个Label上面。注意我们在mouseReleaseEvent函数里面有关QString的构造。我们没有使用arg参数的方式,而是使用C语言风格的sprintf来构造QString对象,如果你对C语法很熟悉(估计很多C+++程序员都会比较熟悉的吧),那么就可以在Qt中试试熟悉的C格式化写法啦!

1、QMouseEvent中的坐标
QMouseEvent中保存了两个坐标,一个是全局坐标,当然另外一个是局部坐标。
全局坐标(globalPos())即是桌面屏幕坐标(screen coordinates),这个跟windows下的调用getCursorPos函数得到的结果一致。
局部坐标(pos())即是相对当前active widget的坐标,左上角坐标为(0, 0)。

本文出自 “豆子空间” 博客,请务必保留此出处

补充一个公式:
this->mapFromGlobal(this->cursor().pos()) = event.pos()

...

2、鼠标跟踪
在qt中,鼠标跟踪对应函数mouseMoveEvent。但是,默认情况下他并不能如期象你想象的那样响应鼠标的移动。此时,你只需在合适的位置调用一下函数setMouseTracking(true)即可。
If mouse tracking is switched off, mouse move events only occur if a mouse button is pressed while the mouse is being moved.
If mouse tracking is switched on, mouse move events occur even if no mouse button is pressed.
默认情况下,mouseMoveEvent响应你按下鼠标的某个键(拖动,但不局限于左键拖动)的鼠标移动。

3、鼠标左键拖动和左键点击的判断
鼠标左键点击很容易判断,一般就是在重写mousePressEvent函数,示例如下:
void XXXWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
// todo ...
}
}
左键拖动的判断一般放在mouseMoveEvent函数中,但是你不能向上例一样来判断,因为该函数的event参数总是返回Qt::NoButton。你可以这样做:
void XXXWidget::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
// todo ...
}
}
参考教材实例,增加了注释和新功能,方便大家交流学习
// mouseevent.cpp
#include "mouseevent.h"
MouseEvent::MouseEvent( ):

QMainWindow()
{
setWindowTitle(tr("Get Mouse Event"));
setCursor(Qt::CrossCursor); //设置鼠标为十字星
labelStatus = new QLabel();
labelStatus->setMinimumSize(500,20);
labelStatus->setFrameShape(QFrame::WinPanel);//设置标签形状
labelStatus->setFrameShadow(QFrame::Sunken); //设置标签阴影;
labelStatus->setText(tr("Mouse Position:"));
labelStatus -> setFixedWidth (100);
labelMousePos = new QLabel();
labelMousePos->setText(tr(""));
labelMousePos -> setFixedWidth (100);
statusBar()->addPermanentWidget(labelStatus);//给状态栏添加永久的部件
statusBar()->addPermanentWidget(labelMousePos);
this->setMouseTracking ( true);//自动跟踪鼠标(默认情况下,mouseMoveEvent响应你按下鼠标的某个键的鼠标移动。)
}

MouseEvent::~MouseEvent(){

}

void MouseEvent::mouseMoveEvent ( QMouseEvent * e )//鼠标移动事件响应

//1.获取局部鼠标位置
labelMousePos ->setText("("+QString::number(e->x())+","+QString::number(e->y())+")");
//2.获取全局鼠标位置
QPoint coursePoint;
coursePoint = QCursor::pos();//获取当前光标的位置
labelMousePos ->setText("("+QString::number(coursePoint.x())+","+QString::number(coursePoint.y())+")");
}

void MouseEvent::mousePressEvent ( QMouseEvent * e )//鼠标单击事件响应
{
QString str="("+QString::number(e->x())+","+QString::number(e->y())+")";
if(e->button()==Qt::LeftButton){
statusBar()->showMessage (tr("Mouse Left Button Pressed:")+str);//显示临时信息
}
else if(e->button()==Qt::RightButton){
statusBar()->showMessage (tr("Mouse Right Button Pressed:")+str);
}
else if(e->button()==Qt::MidButton){
statusBar()->showMessage (tr("Mouse Middle Button Pressed:")+str);
}
}

本文由金沙澳门官网网址发布于澳门金莎娱乐手机版,转载请注明出处:Qt学习之路,点击判断

关键词: