Android的repaint函数

本文探讨了Android SDK中的repaint函数与invalidate()/postInvalidate()方法的区别及使用场景,详细解释了如何在不同线程中更新屏幕显示。
Android的repaint函数
2011年08月01日
  昨天安装了Android SDK1.5 和ADT0.9.1。
  在安装时发现,要在Eclipse安装ADT时还必须安装些其他的插件,自动寻找依赖关系后就必须联网安装这些插件。如果没有网络,貌似就不能安装成功了。
  以上为废话。
  写了一个View,在上面画了点东西,不过没有找到View有repaint函数,寒。
  event函数叫onDraw ,难道叫reDraw,查了下依然没有此函数。
  最后百度了下,终于找到了Android 的repaint函数。 内容如下:
  1、repaint()方法与invalidate()/postInvalidate()方法
  如果去读API,我们可以发现J2ME中Canvas的repaint()与Android 中View的invalidate()/postInvalidate()方法实现了相同的功能(连说明文字几乎都一样…),
  但是invalidate()/postInvalidate()两者却有着区别:invalidate() 只能在UI这个线程里通过调用onDraw (Canvas canvas)来update屏幕显示,
  而postInvalidate()是要在non-UI线程里做同样的事情的。这就要求我们做判断,
  哪个调用是本 线程的,哪个不是,这在做多线程callback的时候尤为重要。而在J2ME中,不管怎样直接调用repaint()就好了
  
  
#include "cameracontroller.h" #include <QMediaDevices> #include <QVideoWidget> #include <QDebug> #include <QImageCapture> #include <QTimer> #include <QMediaFormat> #ifdef Q_OS_ANDROID #include <QCoreApplication> #include <QJniObject> #include <QJniEnvironment> #endif CameraController::CameraController(QObject *parent) : QObject(parent) , m_camera(nullptr) , m_captureSession(nullptr) , m_imageCapture(nullptr) , m_hasCamera(false) , m_videoOutput(nullptr) { qDebug() << "=== 初始化USB摄像头控制器(Android优化版)==="; //连接视频输出状态信号 //QTimer::singleShot(100, this, &CameraController::initializeCamera); initializeCamera(); } CameraController::~CameraController() { stopCamera(); delete m_imageCapture; delete m_captureSession; delete m_camera; } void CameraController::initializeCamera() { qDebug() << "=== 初始化摄像头硬件 ==="; auto cameras = QMediaDevices::videoInputs(); m_hasCamera = !cameras.isEmpty(); if (!m_hasCamera) { qDebug() << "❌ 未找到任何摄像头"; emit errorOccurred("未检测到USB摄像头"); return; } //输出所有可用摄像头信息 for (const auto &camera : cameras) { qDebug() << "可用摄像头:" << camera.description() << "ID:" << camera.id() << "位置:" << camera.position(); } //优先选择USB摄像头 获取不到usb摄像头 QCameraDevice selectedCamera; for (const auto &camera : cameras) { if (isUSBCamera(camera)) { selectedCamera = camera; qDebug() << "✅ 找到USB摄像头:" << camera.description(); break; } //如果没有USB摄像头,选择第一个 if (selectedCamera.isNull()) { selectedCamera = cameras.first(); } } m_cameraDevice = selectedCamera; m_currentCameraDescription = selectedCamera.description(); qDebug() << "选择摄像头:" << m_currentCameraDescription << "ID:" << selectedCamera.id(); // 创建摄像头和会话 m_camera = new QCamera(selectedCamera); m_captureSession = new QMediaCaptureSession(); m_imageCapture = new QImageCapture(); // 配置摄像头参数 if (!configureCamera()) { qDebug() << "⚠️ 摄像头配置可能不理想,但继续尝试..."; } // 设置会话 m_captureSession->setCamera(m_camera); m_captureSession->setImageCapture(m_imageCapture); // 连接信号 connect(m_camera, &QCamera::errorOccurred, this, &CameraController::handleCameraError); connect(m_camera, &QCamera::activeChanged, this, &CameraController::onCameraActiveChanged); qDebug() << "✅ 摄像头硬件初始化完成"; emit statusChanged("摄像头硬件准备就绪"); } void CameraController::onVideoFrameChanged(const QVideoFrame &frame) { qDebug()<<"接受到帧数据"; static int frameCount = 0; frameCount++; if (frameCount % 30 == 0) { // 每30帧输出一次,避免日志过多 qDebug() << "📹 接收到视频帧 #" << frameCount << "尺寸:" << frame.size() << "格式:" << frame.pixelFormat() << "有效:" << frame.isValid(); } } bool CameraController::configureCamera() { //完全不配置 // qDebug() << "=== 使用系统自动摄像头配置 ==="; // // 不设置任何格式,让系统和摄像头硬件自动协商最佳配置 // // 这样可以完全避免 setParameters failed 错误 // qDebug() << "让系统自动选择摄像头格式"; // // 延迟检查系统选择的格式 // QTimer::singleShot(2000, this, [this]() { // if (m_camera && m_camera->isActive()) { // QCameraFormat actualFormat = m_camera->cameraFormat(); // qDebug() << "系统自动选择的摄像头格式:"; // qDebug() << " 分辨率:" << actualFormat.resolution(); // qDebug() << " 像素格式:" << actualFormat.pixelFormat(); // qDebug() << " 帧率范围:" << actualFormat.minFrameRate() << "-" << actualFormat.maxFrameRate(); // // 根据实际格式优化显示 // if (m_videoOutput) { // QSize resolution = actualFormat.resolution(); // if (resolution.width() > 1280) { // qDebug() << "高分辨率模式,优化显示性能"; // // 可以在这里进行高分辨率特定的优化 // } // } // } // }); return true; } bool CameraController::isUSBCamera(const QCameraDevice &camera) { // USB摄像头通常有特定的描述或ID特征 QString description = camera.description().toLower(); QString id = camera.id().toLower(); // 检测USB摄像头的常见特征 bool isUSB = description.contains("usb") || id.contains("usb") || description.contains("external") || camera.position() == QCameraDevice::UnspecifiedPosition; qDebug() << "摄像头检测 - 描述:" << description << "ID:" << id << "位置:" << camera.position() << "是USB摄像头:" << isUSB; return isUSB; } bool CameraController::startCamera() { qDebug() << "=== 启动USB摄像头 ==="; if (!m_camera) { qDebug() << "❌ 摄像头未初始化"; emit errorOccurred("USB摄像头未初始化"); return false; } if (m_camera->isActive()) { qDebug() << "USB摄像头已在运行"; return true; } // Android平台:先检查权限 if (!checkAndroidCameraPermission()) { qDebug() << "Android摄像头权限未授予"; emit errorOccurred("请授予摄像头权限后重试"); return false; } try { // 启动摄像头 m_camera->start(); qDebug() << "USB摄像头启动命令已发送"; emit statusChanged("正在启动USB摄像头..."); return true; } catch (const std::exception& e) { qDebug() << "启动摄像头异常:" << e.what(); emit errorOccurred(QString("启动摄像头异常: %1").arg(e.what())); return false; } } bool CameraController::checkAndroidCameraPermission() { // 在Qt 6.2中,我们可以使用JNI来检查权限 QJniObject permission = QJniObject::fromString("android.permission.CAMERA"); QJniObject activity = QJniObject::callStaticObjectMethod( "org/qtproject/qt/android/QtNative", "activity", "()Landroid/app/Activity;"); if (!activity.isValid()) { qDebug() << "无法获取Android Activity"; return false; } jint result = activity.callMethod<jint>( "checkSelfPermission", "(Ljava/lang/String;)I", permission.object<jstring>()); // PERMISSION_GRANTED = 0 if (result == 0) { qDebug() << "Android摄像头权限已授予"; return true; } else { qDebug() << "Android摄像头权限未授予,需要请求权限"; // 请求权限 QJniObject::callStaticMethod<void>( "org/qtproject/qt/android/QtNative", "requestPermission", "(Ljava/lang/String;)V", permission.object<jstring>()); // 在真实应用中,您需要处理权限请求的回调 // 这里简化处理,假设权限会被授予 return false; } } void CameraController::stopCamera() { qDebug() << "停止USB摄像头"; if (m_camera && m_camera->isActive()) { m_camera->stop(); emit statusChanged("USB摄像头已停止"); qDebug() << "USB摄像头已停止"; } } void CameraController::handleCameraError(QCamera::Error error, const QString &errorString) { QString errorMsg; switch (error) { case QCamera::NoError: return; case QCamera::CameraError: errorMsg = "摄像头错误: " + errorString; break; } qDebug() << "❌ USB摄像头错误:" << errorMsg; if (errorString.contains("Permission", Qt::CaseInsensitive) || errorString.contains("permission", Qt::CaseInsensitive)) { errorMsg = "摄像头权限被拒绝,请重启应用并授予权限"; } else if (errorString.contains("format", Qt::CaseInsensitive) || errorString.contains("pixel", Qt::CaseInsensitive)) { errorMsg = "视频格式不兼容,尝试使用基本模式"; } emit errorOccurred(errorMsg); } void CameraController::onCameraActiveChanged(bool active) { if (active) { qDebug() << "✅ USB摄像头已激活"; qDebug() <<" 摄像头活动状态:"<<m_camera->isActive(); //qDebug() << "会话活动状态:" << m_captureSession->isActive(); qDebug() << "视频输出:" << m_captureSession->videoOutput(); emit statusChanged("USB摄像头运行中"); emit cameraReady(); // 摄像头激活后,强制刷新视频输出 if (m_videoOutput) { qDebug() << "强制刷新视频输出控件"; m_videoOutput->setVisible(true); m_videoOutput->update(); m_videoOutput->repaint(); // 多次刷新确保显示 QTimer::singleShot(100, [this]() { if (m_videoOutput) { m_videoOutput->update(); m_videoOutput->repaint(); } }); } } else { qDebug() << "USB摄像头已停用"; emit statusChanged("USB摄像头已停止"); } } void CameraController::setVideoOutput(QVideoWidget* videoOutput) { if (!videoOutput) { qDebug() << "❌ 视频输出为nullptr"; return; } m_videoOutput = videoOutput; if (m_captureSession) { qDebug() << "=== 设置视频输出 ==="; m_captureSession->setVideoOutput(videoOutput); qDebug() << "✅ 视频输出设置为QVideoWidget"; // 获取 VideoSink 并连接帧信号 QVideoSink *sink = videoOutput->videoSink(); m_captureSession->setVideoSink(sink); if (sink) { connect(sink, &QVideoSink::videoFrameChanged, this, &CameraController::onVideoFrameChanged); qDebug() << "✅ 视频帧监听已连接"; } else { qDebug() << "❌ 无法获取 VideoSink"; } if (m_captureSession && videoOutput) { m_videoOutput = videoOutput; m_captureSession->setVideoOutput(videoOutput); qDebug() << "✅ 视频输出设置为QVideoWidget"; // 详细调试信息 qDebug() << "视频输出对象:" << videoOutput; qDebug() << "会话视频输出:" << m_captureSession->videoOutput(); // 优化视频显示设置 videoOutput->setAspectRatioMode(Qt::KeepAspectRatio); videoOutput->setAttribute(Qt::WA_AcceptTouchEvents, true); videoOutput->setAttribute(Qt::WA_OpaquePaintEvent, true); videoOutput->setAttribute(Qt::WA_NoSystemBackground, true); // 设置黑色背景 videoOutput->setStyleSheet("QVideoWidget { background-color: black; }"); // 强制启用原生渲染 videoOutput->setAutoFillBackground(false); // 连接视频输出的信号 // connect(videoOutput, &QVideoWidget::nativeObjectChanged, this, [this]() { // qDebug() << "QVideoWidget native对象已改变"; // }); } } } //QStringList CameraController::getCameraInfo() const //{ // QStringList info; // if (!m_camera) { // info << "摄像头: 未初始化"; // return info; // } // info << "设备: " + m_currentCameraDescription; // info << "状态: " + QString(m_camera->isActive() ? "运行中" : "已停止"); // info << "显示: QVideoWidget (Android优化版)"; // info << "QT版本: 6.2兼容"; // // 添加格式信息 // if (!m_cameraDevice.videoFormats().isEmpty()) { // auto format = m_camera->cameraFormat(); // info << "分辨率: " + QString::number(format.resolution().width()) + "x" + QString::number(format.resolution().height()); // info << "帧率: " + QString::number(format.minFrameRate()) + "-" + QString::number(format.maxFrameRate()); // } // return info; //} 你帮我看看代码,这个视频帧不会触发,调试信息是这样的D USBCameraApp: UI初始化完成 D USBCameraApp: === 初始化摄像头控制器 === D USBCameraApp: === 初始化USB摄像头控制器(Android优化版)=== D USBCameraApp: === 初始化摄像头硬件 === D USBCameraApp: 可用摄像头: "Rear-facing camera" ID: "back" 位置: QCameraDevice::BackFace D USBCameraApp: 摄像头检测 - 描述: "rear-facing camera" ID: "back" 位置: QCameraDevice::BackFace 是USB摄像头: false D USBCameraApp: 选择摄像头: "Rear-facing camera" ID: "back" D USBCameraApp: ✅ 摄像头硬件初始化完成 D USBCameraApp: MainWindow初始化完成 D mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, egl_color_buffer_format *, EGLBoolean) returns 0x3000 D : set stream to NULL D : set stream to NULL D : set stream to NULL D : set stream to NULL D USBCameraApp: === 设置视频输出 === D USBCameraApp: ✅ 视频输出设置为QVideoWidget D USBCameraApp: ✅ 视频帧监听已连接 D USBCameraApp: ✅ 视频输出设置为QVideoWidget D USBCameraApp: 视频输出对象: QVideoWidget(0xadbd0430, name="videoWidget") D USBCameraApp: 会话视频输出: QVideoWidget(0xadbd0430, name = "videoWidget") D USBCameraApp: ✅ 摄像头控制器初始化成功 W System.err: java.lang.RuntimeException: setParameters failed W System.err: at android.hardware.Camera.native_setParameters(Native Method) W System.err: at android.hardware.Camera.setParameters(Camera.java:2110) D USBCameraApp: ✅ USB摄像头已激活 D USBCameraApp: 摄像头活动状态: true D USBCameraApp: 视频输出: QVideoWidget(0xadbd0430, name = "videoWidget") D USBCameraApp: USB摄像头状态: "USB摄像头运行中" D USBCameraApp: 摄像头准备就绪,可以显示视频 D USBCameraApp: 强制刷新视频输出控件 W System.err: java.lang.RuntimeException: setParameters failed W System.err: at android.hardware.Camera.native_setParameters(Native Method) W System.err: at android.hardware.Camera.setParameters(Camera.java:2110) I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080. I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080. I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080. I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080. I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080. D USBCameraApp: 显示摄像头预览 - 视频控件可见性: true D USBCameraApp: 视频控件尺寸: QSize(1301, 651) D USBCameraApp: 视频控件实际尺寸: QSize(-1, -1) D USBCameraApp: 显示摄像头预览 - 视频控件可见性: true D USBCameraApp: 视频控件尺寸: QSize(1301, 651) D USBCameraApp: 视频控件实际尺寸: QSize(-1, -1) 为什么显示不了视频画面呢
最新发布
11-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值