Qt学习(20)——Qt5中的事件和信号

事件是任何GUI程序中的重要部分,所有GUI应用程序都是事件驱动的。应用程序对在其生命周期中生成的不同事件类型作出反应。事件主要由应用程序的用户生成,但它们也可以通过其他方式生成,例如Internet连接,窗口管理器或计时器。在活动模型中,有三个参与者:

  • 事件来源
  • 事件对象
  • 事件目标

事件源是状态更改的对象,会生成事件。事件对象封装了事件源中的状态更改。事件目标是想要通知的对象。事件源对象将处理事件的任务委托给事件目标。
当调用应用程序的exec()方法时,应用程序进入主循环。主循环获取事件并将它们发送到对象。Qt具有独特的信号和槽机制,信号和槽机制是C ++编程语言的扩展。信号和槽用于对象之间的通信,发生特定事件时会发出信号。槽是普通的C ++方法;当槽连接到它的信号时调用它。

点击

第一个示例显示了一个非常简单的事件处理示例。我们有一个按钮,通过单击按钮终止应用程序。

//click.h
#pragma once

#include <QWidget>

class Click : public QWidget {

  public:
    Click(QWidget *parent = 0);
};
//click.cpp
#include <QPushButton>
#include <QApplication>
#include <QHBoxLayout>
#include "click.h"

Click::Click(QWidget *parent)
    : QWidget(parent) {

  QHBoxLayout *hbox = new QHBoxLayout(this);
  hbox->setSpacing(5);

  QPushButton *quitBtn = new QPushButton("Quit", this);
  hbox->addWidget(quitBtn, 0, Qt::AlignLeft | Qt::AlignTop);

  connect(quitBtn, &QPushButton::clicked, qApp, &QApplication::quit);
}
connect(quitBtn, &QPushButton::clicked, qApp, &QApplication::quit);

connect()方法将信号连接到槽。当我们点击退出按钮时,会生成单击的信号,qApp 是指向应用程序对象的全局指针。它在<QApplication>头文件中定义,发出单击信号时调用quit()方法。

//main.cpp
#include <QApplication>
#include "click.h"

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  Click window;

  window.resize(250, 150);
  window.setWindowTitle("Click");
  window.show();

  return app.exec();
}

按键

//keypress.h
#pragma once

#include <QWidget>

class KeyPress : public QWidget {

  public:
    KeyPress(QWidget *parent = 0);

  protected:
    void keyPressEvent(QKeyEvent * e);
};
//keypress.cpp
#include <QApplication>
#include <QKeyEvent>
#include "keypress.h"

KeyPress::KeyPress(QWidget *parent)
    : QWidget(parent)
{ }

void KeyPress::keyPressEvent(QKeyEvent *event) {

   if (event->key() == Qt::Key_Escape) {  
       qApp->quit();
   } 
}

如果按Esc键,应用程序将终止。在Qt5中处理事件的方法之一是重新实现事件处理程序。QKeyEvent是一个事件对象,它保存有关已发生事件的信息。在我们的例子中,我们使用事件对象来确定实际按下了哪个键。

//main.cpp
#include <QApplication>
#include "keypress.h"

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  KeyPress window;

  window.resize(250, 150);
  window.setWindowTitle("Key press");
  window.show();

  return app.exec();
}

QMoveEvent

QMoveEvent类包含移动事件的事件参数。移动事件将发送到已移动的窗口。

// move.h
#pragma once

#include <QMainWindow>

class Move : public QWidget {

  Q_OBJECT

  public:
    Move(QWidget *parent = 0);

  protected:
    void moveEvent(QMoveEvent *e);
};
// move.cpp
#include <QMoveEvent>
#include "move.h"

Move::Move(QWidget *parent)
    : QWidget(parent)
{ }

void Move::moveEvent(QMoveEvent *e) {

  // 使用QMoveEvent对象来确定x,y值。
  int x = e->pos().x();
  int y = e->pos().y();

  QString text = QString::number(x) + "," + QString::number(y); //将整数值转换为字符串。

  setWindowTitle(text);//setWindowTitle()方法将文本设置为窗口的标题。
}

在我们的代码编程示例中,对移动事件做出反应,确定窗口左上角的当前x,y坐标,并将这些值设置为窗口的标题。

//main.cpp
#include <QApplication>
#include "move.h"

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  Move window;

  window.resize(250, 150);
  window.setWindowTitle("Move");
  window.show();

  return app.exec();
}

断开信号

可以通过槽断开信号。

//disconnect.h
#pragma once

#include <QWidget>
#include <QPushButton>

class Disconnect : public QWidget {

  Q_OBJECT  

  public:
    Disconnect(QWidget *parent = 0);

  private slots:
    void onClick();
    void onCheck(int);

  private:
    QPushButton *clickBtn;
};

在头文件中,声明了两个槽。槽不是C++关键字,它是Qt5扩展。在编译代码之前,这些扩展由预处理器处理。当我们在类中使用信号和槽时,我们必须在类定义的开头提供一个Q_OBJECT宏。

//disconnect.cpp
#include <QTextStream>
#include <QCheckBox>
#include <QHBoxLayout>
#include "disconnect.h"

Disconnect::Disconnect(QWidget *parent)
    : QWidget(parent) {

  QHBoxLayout *hbox = new QHBoxLayout(this);
  hbox->setSpacing(5);        

  clickBtn = new QPushButton("Click", this);
  hbox->addWidget(clickBtn, 0, Qt::AlignLeft | Qt::AlignTop);

  QCheckBox *cb = new QCheckBox("Connect", this);
  cb->setCheckState(Qt::Checked);
  hbox->addWidget(cb, 0, Qt::AlignLeft | Qt::AlignTop);

  //在这里将信号连接到用户定义的槽。
  connect(clickBtn, &QPushButton::clicked, this, &Disconnect::onClick);
  connect(cb, &QCheckBox::stateChanged, this, &Disconnect::onCheck);  
}

//如果点击Click按钮,会将“Button clicked”文本发送到终端窗口。
void Disconnect::onClick() {

  QTextStream out(stdout);
  out << "Button clicked" << endl;
}

//在onCheck()插槽内,根据收到的状态连接或断开onClick()槽与Click按钮。
void Disconnect::onCheck(int state) {

  if (state == Qt::Checked) {
    connect(clickBtn, &QPushButton::clicked, this, &Disconnect::onClick);
  } else {
    disconnect(clickBtn, &QPushButton::clicked, this, 
        &Disconnect::onClick);
  }
}

在我们的示例中有一个按钮和一个复选框。该复选框用于连接和断开按钮单击信号的槽,必须从命令行执行此示例。

//main.cpp
#include <QApplication>
#include "disconnect.h"

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  Disconnect window;

  window.resize(250, 150);
  window.setWindowTitle("Disconnect");
  window.show();

  return app.exec();
}

时间

计时器用于实现单次或重复性任务。我们使用计时器的一个例子是时钟:每一秒都必须更新显示当前时间的标签。

//timer.h
#pragma once

#include <QWidget>
#include <QLabel>

class Timer : public QWidget {

  public:
    Timer(QWidget *parent = 0);

  protected:
    void timerEvent(QTimerEvent *e);

  private:
    QLabel *label;
};
//timer.cpp
#include "timer.h"
#include <QHBoxLayout>
#include <QTime>

Timer::Timer(QWidget *parent)
    : QWidget(parent) {

  QHBoxLayout *hbox = new QHBoxLayout(this);
  hbox->setSpacing(5);               

  label = new QLabel("", this); //为了显示时间使用QLable。
  hbox->addWidget(label, 0, Qt::AlignLeft | Qt::AlignTop);

  //确定当前的当地时间,将事件显示在QLable控件上
  QTime qtime = QTime::currentTime();
  QString stime = qtime.toString();
  label->setText(stime);

  startTimer(1000); //启动计时器,每1000毫秒生成一个计时器事件。
}

//要使用计时器事件,必须重新实现timerEvent()方法。
void Timer::timerEvent(QTimerEvent *e) {

  Q_UNUSED(e);

  QTime qtime = QTime::currentTime();
  QString stime = qtime.toString();
  label->setText(stime);
}
\\main.cpp
#include <QApplication>
#include "timer.h"

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  Timer window;

  window.resize(250, 150);
  window.setWindowTitle("Timer");
  window.show();

  return app.exec();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值