Qt在QTabWidget上绘图

先介绍下Qt事件过滤器。

Qt事件过滤器

Qt 事件模块有一个强大的特性,就是可以设置一个QObject的实例1去监测另一个QObject实例2的事件,在被监测控件QObject实例2能看到事件之前,就先被监测的控件QObject实例1看到(拦截)并处理。

QObject有一个eventFilter()函数,用于建立事件过滤器:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

参数watched为被监测的控件,参数 event为发生的事件,所有监测的控件,发生的所有事件都会先执行这个函数,这个函数返回一个 bool 类型,如果你想将参数 event 过滤出来,比如,不想让它继续转发,就返回 true,否则返回 false。事件过滤器的调用时间是目标对象(也就是参数里面的watched对象)接收到事件对象之前。也就是说,如果你在事件过滤器中停止了某个事件,那么,watched对象以及以后所有的事件过滤器根本不会知道这么一个事件。

然后我们将被监测的QObject实例安装到这个过滤器:

void QObject::installEventFilter ( QObject * filterObj );

注意:事件过滤器和被安装过滤器的组件必须在同一线程,否则,过滤器将不起作用。另外,如果在安装过滤器之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候过滤器才会有效。

Qt在QTabWidget上绘图

Qt绘图事件必须在paintEvent事件下绘图,我们不能在Qt设计师界面拖拽的控件上写paintEvent函数,因此不能在拖拽的控件上绘图,但是可以自定义一个类,继承某一个控件,在里面写绘图事件函数,但是这个比较麻烦。

我们可以借助事件过滤器完成绘图:

  1. 主控件重写eventFilter
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::Paint)
    {
        if(ui->tab_0 == ui->tabWidget->currentWidget())
        {
            drawTab0(ui->tab_0);
        } else if(ui->tab_1 == ui->tabWidget->currentWidget())
        {
            drawTab1(ui->tab_1);
        } else if(ui->tab_2 == ui->tabWidget->currentWidget())
        {
            drawTab2(ui->tab_2);
        }
    }
    return QMainWindow::eventFilter(watched, event);
}

void MainWindow::drawTab0(QWidget *widget)
{
    QPainter painter(widget);
    if ((pancamImage.size().width() > 0) && (e_connectStatus_connected == pancam_connectStatus))
    {
        drawImage(&painter, ui->pancam, pancamImage);
    }

    if ((closeupImage.size().width() > 0) && (e_connectStatus_connected == closeup_connectStatus))
    {
        drawImage(&painter, ui->closeup, closeupImage);
    }

    if(showTrackPoint)
    {
        //画黄点
        painter.setPen(QColor(Qt::yellow));
        painter.setBrush(QBrush(Qt::yellow));
        painter.drawEllipse(absX - 5,absY - 5,10,10);
        //画坐标
        painter.setFont(QFont("Arial", 15));
        QString x = QString::number(relativeX);
        QString y = QString::number(relativeY);
        painter.drawText(QRect(20+5, 20 + 11 + 5, 50, 30), Qt::AlignJustify, x+","+y);
    }

    drawCenterPont(&painter, ui->pancam);
    drawCenterPont(&painter, ui->closeup);
}
  1. 安装事件过滤器
    ui->tab_0->installEventFilter(this);
    ui->tab_1->installEventFilter(this);
    ui->tab_2->installEventFilter(this);
  1. 实时调用update
void MainWindow::slotGetOneFrame(QImageInfo imgInfo)
{
    if(imgInfo.image.isNull())
    {
        qDebug() << "slotGetOneFrame failed, image is null";
        return;
    }

    if(e_stream_pancam == imgInfo.index)
    {
        pancamImage = imgInfo.image.copy();

    } else if (e_stream_closeup == imgInfo.index)
    {
        closeupImage = imgInfo.image.copy();
    }

    update(); //调用update将执行,发出绘图事件
}

QPainter 接收一个 QPaintDevice*类型的参数。QPaintDevice 有很多子类,比如 QImage,以及QWidget。QPaintDevice 可以理解成要在哪里去画,而现在我们希望在这个 QTabwidget的页面上画,因此此处传入的是tab指针,而不是MainWindow。

在paintEvent绘制tab页面会报错,但在eventFilter里绘制可以,至于为什么,还不清楚。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值