Qt 信号与事件

事件

  • GUI 应用程序都是事件驱动的
  • 事件主要有用户生成,但也可以通过 internet 连接,计时器等生成
  • 应用进入主循环,主循环获取事件并发送到对象

信号与槽

  • Qt 独有的机制,是对 C++ 的拓展
  • 信号与槽用于对象之间的通信
  • slot(槽)是一种普通 C++ 函数,在连接的信号发出时被调用

信号与槽的连接方法

成员函数指针(connect)

优点:

  • 允许编译器检查信号是否与槽的参数兼容
  • 编译器可以隐式转换参数

Qt::ConnectionType 参数:

  • Qt::AutoConnection // 自动确定
  • Qt::DirectConnection // 信号与槽同一线程
  • Qt::QueuedConnection // 信号与槽不同线程
  • Qt::BlockingQueueConnection // 阻塞信号线程

槽函数中获得 sender 指针

  • QSpinBox* spinbox = qobject_cast<QSpinBox*>(sender());

自定义信号与槽

  • 信号函数必须无返回值,但可以有输入参数
  • 信号函数无需实现,只需在某些条件下发射信号

键盘事件

  • 要重写 QWidget 基类中的 keyPressedEvent 方法
  • 在 Qt Creator 中,可以右键基类 -> Refactor -> Insert Virtual Functions of Base Classes 插入要重写的函数
  • 查看事件中按下的键:event->key()
  • 在 Qt 中,按键表示为:Qt::Key_Escape
void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Escape)
    {
        qApp->quit();
    }
}

鼠标事件

  • 要重写 QWidget 基类中的 mouseMoveEvent 方法
  • 获得鼠标的 x 和 y 坐标:event->pos().x()event->pos().y()
  • QMainWindow 中在状态栏显示信息:this->statusBar()->showMessage("Hi");
  • 将数字转换成 QString:QString::number(10);
  • 如果要让鼠标不按下按键也追踪,需要在构造函数中添加:setMouseTracking(true);
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int y = event->pos().y();
    QString text = "Coordinate: " + QString::number(x) + ", " + QString::number(y);
    this->statusBar()->showMessage(text);
}

计时器事件

  • 继承自 QObject 基类中的 timerEvent 方法
  • 开始计时器用:startTimer(int millisec) 方法
  • 获取当前时间字符串:QTime::currentTime().toString()
void MainWindow::timerEvent(QTimerEvent *event)
{
    label->setText(QTime::currentTime().toString());  // 用 QTime 获取当前时间
}

QMainWindow 案例

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* widget = new QWidget(this);
    setCentralWidget(widget);

    clickBtn = new QPushButton("点击", widget);
    cb = new QCheckBox("Connect", widget);
    cb->setCheckState(Qt::Checked);
    label = new QLabel(QTime::currentTime().toString(), widget);

    QHBoxLayout* hbox = new QHBoxLayout(widget);
    hbox->addWidget(clickBtn);
    hbox->addWidget(cb);
    hbox->addWidget(label);
}