您现在的位置是:网站首页> C/C++
QT学习笔记归纳
- C/C++
- 2023-03-19
- 1285人已阅读
QT学习笔记归纳
QMediaPlayer视频没有画面显示,或播放卡顿问题解决(DirectShowPlayerService::doRender: Unresolved error code 80040266)
Qt宏判断平台
#if defined(Q_OS_ANDROID)
我们在使用QT编程的时候,有时会遇到跨平台的状况(毕竟QT本身就是因优秀的跨平台特性而出名),在这种情况下,判断当前是哪一种平台就非常必要了,这里介绍一下QT提供的各种判断操作系统和编译平台的做法:
1、如果仅仅想要当前是windows、mac还是linux系统的话,可以直接使用宏:
Q_OS_LINUX:定义在linux系统中
Q_OS_WIN:定义在windows系统中
Q_OS_OSX:定义在OS X系统中
2、如果还想更细致的判断系统,比如当前是windows 32位系统还是64位系统,是IOS系统还是Android系统,又或者当前是否在ARM环境中?当然也是可以的:
Q_OS_WIN64:定义在windows 64位系统中
Q_OS_IOS:定义在IOS系统中
Q_OS_ANDROID:定义在Android系统中
Q_PROCESSOR_ARM:是否为ARM处理器编译环境
3、如果还不满意,比如我想知道当前的windows系统是winXP、win7、还是win10,那肯定也是有的,不过这就不在预编译里面判断了,需要在代码中进行判断,相对于普通的C++,QT封装了很多好用的类,有些类可以帮助我们更快速更方便的使用C++,比如QString类,从此妈妈再也不用担心我不会用std::string,又比如QSysInfo类,看名字就知道这个类和系统信息有关,而我们用来识别操作系统就是用这个类进行判断的。首先看看QT文档中的介绍:
翻译:
QSysInfo类提供有关系统的信息。
WordSize:判断编译应用程序的平台的指针大小(注:不同操作系统和编译环境下指针大小不同)。
ByteOrder:判断当前平台是大端还是小端。
WindowsVersion:判断运行应用程序的Windows操作系统的版本。
MacintoshVersion:判断运行应用程序的Macintosh操作系统的版本。
某些常量仅在指定平台上定义。 您可以使用预处理器符号Q_OS_WIN和Q_OS_OSX来测试应用程序当前是在Windows还是OS X下编译。
看完上面的介绍大概就清楚了,利用QSysInfo可以得到各种操作系统的信息,比如,我最近想要将一个软件放在windows XP中运行,其中有一个dll库仅支持windows7及以上的windows版本,那么可以在代码中这样判断:
if(QSysInfo::windowsVersion() == QSysInfo::WV_XP) {
QMessageBox msgBox;
msgBox.setText(QStringLiteral("产品暂不支持windows XP操作系统"));
msgBox.exec();
return false;
}
这样就很方便的将不支持XP系统的功能避开,避免出现类似于【无法定位程序输入点XXX于动态链接库KERNEL32.dll上】这样的问题
ApplicationWindow {
visible: true
width: Qt.platform.os === "android"? Screen.width: 640
height: Qt.platform.os === "android"? Screen.height: 480
title: qsTr( "Android Camera" )
Qt pro平台判断
ios
{
LIBS += -framework Foundation -framework UIKit -framework Contacts -framework ContactsUI
OBJECTIVE_SOURCES += \
SamsonQt_IOS.mm
}
android:contains(QT_ARCH, arm) {
message("arm32!");
}
android:contains(QT_ARCH, arm64) {
message("arm64!");
}
unix
{
}
win32
{
contains(QT_ARCH, i386) {
message("32-bit")
}else {
message("64-bit")
}
}
Qt加库
向QT环境中添加FFMPEG的库和头文件
打开QT的工程文件(xx.pro),加入FFMPEG的库路径和头文件路径
#指定库文件的路径
unix:LIBS += -L$$PWD/so_file -lavcodec
unix:LIBS += -L$$PWD/so_file -lavfilter
unix:LIBS += -L$$PWD/so_file -lavutil
unix:LIBS += -L$$PWD/so_file -lavdevice
unix:LIBS += -L$$PWD/so_file -lavformat
unix:LIBS += -L$$PWD/so_file -lpostproc
unix:LIBS += -L$$PWD/so_file -lswscale
unix:LIBS += -L$$PWD/so_file -lswresample
#指定头文件的路径
INCLUDEPATH+=$$PWD/so_file/include
然后再做最重要的一步,向Android里添加用到的FFMPEG动态库:
如果这里不添加,当程序部署到Android设备上时,会因为找不到运行需要的动态库而崩溃。
添加成功之后,在xx.pro文件里会自动生成代码:(下面是我自己添加的库,需要用到 的库)
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_EXTRA_LIBS = \
$$PWD/so_file/libavcodec.so \
$$PWD/so_file/libavfilter.so \
$$PWD/so_file/libavformat.so \
$$PWD/so_file/libavutil.so \
$$PWD/so_file/libpostproc.so \
$$PWD/so_file/libswresample.so \
$$PWD/so_file/libswscale.so \
$$PWD/so_file/libavdevice.so \
/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.2/lib/linux/libclang_rt.ubsan_standalone-aarch64-android.so
库添加之后,就可以正常的开发程序了。
如果需要在代码里调用FFMPEG打开Android设备的摄像头,如果是直接打开/dev/videoX设备。在程序里是打不开的,需要使用ADB命令进入到Android设备里,修改/dev/videoX设备具有可读可写的权限,才能正常打开使用。
程序编译时,需要选择正确的编译器,FFMPEG库使用什么编译器版本,QT编译时就得对应。
比如: 编译FFMPEG时使用arm64-v8a 那么,QT的编译器也得一样,否则会导致库的版本不对,而链接失败
}
Qt Android基本配置
Qt 申请Android 权限的类是在 QtAndroid 中,要使用该类,首先需要在工程文件中声明该模块
QT += androidextras
动态获取权限的接口。
bool MainWindow::requestPermission()
{
QtAndroid::PermissionResult r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
if(r == QtAndroid::PermissionResult::Denied) {
QtAndroid::requestPermissionsSync(QStringList()<<"android.permission.WRITE_EXTERNAL_STORAGE");
r = QtAndroid::checkPermission("android.permission.CAMERA");
if(r == QtAndroid::PermissionResult::Denied) {
return false;
}
}
return true;
}
使用权限前调用函数requestPermission();就可以了
但是里面要修改成相应权限
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.CAMERA
Android常用权限:AndroidManifest.xml中
android:usesCleartextTraffic="true" // application内2、照相权限:<uses-permission android:name="android.permission.CAMERA"/>3、写权限:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>4、定位权限:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>其中照相和写权限仅仅这样声明是不可以的,还得在代码中动态申请权限
#include “permissions.h”
QtAndroid::PermissionResult r = QtAndroid::checkPermission(“android.permission.WRITE_EXTERNAL_STORAGE”);
if(r == QtAndroid::PermissionResult::Denied) {
QtAndroid::requestPermissionsSync( QStringList() << “android.permission.WRITE_EXTERNAL_STORAGE” );
r = QtAndroid::checkPermission(“android.permission.WRITE_EXTERNAL_STORAGE”);
if(r == QtAndroid::PermissionResult::Denied) {
return false;
}
}
QtAndroid::PermissionResult p = QtAndroid::checkPermission(“android.permission.CAMERA”);
if(p == QtAndroid::PermissionResult::Denied) {
QtAndroid::requestPermissionsSync( QStringList() << “android.permission.CAMERA” );
p = QtAndroid::checkPermission(“android.permission.CAMERA”);
if(p == QtAndroid::PermissionResult::Denied) {
return false;
}
QString中文乱码问题
QString中文乱码问题
乱码问题通常会在有中文的时候出现,有两种写法可以避免乱码:
QString str1 = QString::fromLocal8Bit("你好");
QString str2 = QStringLiteral("你好");
通常情况下,需要中文的QString串的时候会使用这两种写法,且比较推荐QStringLiteral宏的方式进行创建
fromLocal8Bit使用
在Qt中,fromLocal8Bit()是QString类的一个成员函数,用于将本地编码(Local 8-bit)的字符串转换为QString对象。它的使用方法如下:
QByteArray localData = "你好"; // 本地编码的字符串
QString str = QString::fromLocal8Bit(localData); // 将本地编码的字符串转换为QString对象
在上述示例中,我们首先将本地编码的字符串存储在QByteArray对象中,然后使用fromLocal8Bit()函数将其转换为QString对象。
该函数的目的是解决在不同平台和不同编译环境中使用本地编码时可能出现的字符集问题。它会自动根据当前环境的本地编码进行字符集转换,以正确地表示字符串。
需要注意的是,fromLocal8Bit()函数只能用于处理本地编码的字符串,而不适用于其他编码格式。如果您的字符串使用的是其他编码,例如UTF-8或GBK,可以使用其他适当的函数进行转换,如fromUtf8()或fromUtf16()。
QByteArray utf8Data = "你好"; // UTF-8编码的字符串
QString str = QString::fromUtf8(utf8Data); // 将UTF-8编码的字符串转换为QString对象
QByteArray gbkData = "你好"; // GBK编码的字符串
QString str = QString::fromLocal8Bit(gbkData); // 将GBK编码的字符串转换为QString对象
从不同编码转换为QString时,确保使用适当的函数来处理相应的编码格式,以保证正确的字符集转换。
QStringLiterial使用
QStringLiteral是Qt提供的一个宏,用于创建编译时优化的QString对象,以提高性能和减少内存使用。下面是QStringLiteral的使用方法:
创建QString对象:
QString str1 = QStringLiteral("Hello"); // 直接使用QStringLiteral创建字符串
QString str2 = QStringLiteral("World");
字符串拼接:
QString str = str1 + QStringLiteral(" ") + str2; // 字符串拼接
str.append(QStringLiteral(" Qt")); // 使用append()函数拼接字符串
使用QStringLiteral创建的字符串对象在编译时会进行优化,避免了运行时的内存分配和拷贝操作,提高了性能和效率。它特别适用于常量字符串的创建和使用,特别是在频繁创建和使用字符串对象的场景。
请注意,QStringLiteral只能用于创建静态字符串,不能用于动态生成的字符串。此外,在某些特定情况下,编译器可能会自动将字符串常量隐式转换为QStringLiteral,因此在使用QStringLiteral时应注意编译器的行为。
QString 转 char* 中文乱码解决
先将QString转换为标准库中的string类型,然后将string转换为char* ;
std::string str = filename.toStdString();
const char* ch = str.c_str();
Qt android调用jar包,字节数组参数类型的函数
带字节数组的jar包
jar包中字节数组参数的函数定义
Qt android调用jar包,字节数组参数类型的函数
该函数所在类的定义
调用jar包中的字节数组参数的函数
定义类的变量
QByteArray转换成jbyteArray
字节数组对于的signature为[B
使用callMethod方法调用函数
整体代码
Android Services
从Qt 5.7开始,你可以使用Qt创建Android服务。服务是一个在后台运行的组件,所以,它没有用户界面。它对于执行长期的操作非常有用,比如记录GPS,等待社交媒体通知等等。即使启动它的应用程序退出,一个服务也会继续运行。
组装服务
首先,按照Qt Creator:将应用程序部署到Android设备中的说明创建一个Android软件包目录。此目录包含 AndroidManifest.xml 文件。在包目录中,创建一个 src 目录,将在其中创建所有Java包和类。
创建服务类
您可以通过将类 QtService 或Android:Service扩展到Java类来创建服务。根据您是要在服务中使用Qt功能还是要从Java调用本机C ++函数,您需要扩展 QtService 或 Service 。让我们从一个简单的服务开始,如下所示:
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.qtproject.qt.android.bindings.QtService;
public class QtAndroidService extends QtService
{
private static final String TAG = "QtAndroidService";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Creating Service");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Destroying Service");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int ret = super.onStartCommand(intent, flags, startId);
// 做一些工作
return ret;
}
}
启动服务
Android允许按需或在启动时启动服务。你也可以使用Qt来实现这两点。
开始按需服务
您可以通过以下方式启动服务。
直接从 C++ 使用QAndroidIntent和QJniObject,通过创建服务Intent并调用应用程序的主要活动方法startService():
auto activity = QJniObject(QNativeInterface::QAndroidApplication:context());
QAndroidIntent serviceIntent(activity.object(),
"org/qtproject/example/qtandroidservice/QtAndroidService");
QJniObject result = activity.callObjectMethod(
"startService",
"(Landroid/content/Intent;)Landroid/content/ComponentName;",
serviceIntent.handle().object());
通过调用一个Java方法来启动服务。最简单的方法是在你的服务类中创建一个静态方法。
public static void startQtAndroidService(Context context) {
context.startService(new Intent(context, QtAndroidService.class));
}
你可以使用以下JNI调用从C++中调用它。
QJniObject::callStaticMethod<void>(
"org/qtproject/example/qtandroidservice/QtAndroidService",
"startQtAndroidService",
"(Landroid/content/Context;)V",
QtAndroid::androidActivity().object());
在启动时启动服务
要在引导时运行服务,您需要一个BroadcastReceiver。
创建一个自定义的Java类。
public class QtBootServiceBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, QtAndroidService.class);
context.startService(startServiceIntent);
}
}
在 AndroidManifest.xml 文件的 <manifest> 部分的正文中添加以下 uses-permission :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
另外,在 <application> 部分的正文中添加 receiver 方定义:
<receiver android:name=".QtBootServiceBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
注意: Android 8.0 对运行后台服务引入了一些限制,这意味着使用普通的 Service 类可能无法正常工作。有关更多信息,请参阅 Android 建议使用Foreground 服务或JobIntentService。
管理AndroidMnifest.xml中的服务。
为了使该服务在Android应用程序中可用,您必须在 AndroidManifest.xml 文件中对其进行声明。让我们从添加服务部分开始:
扩展 Service 时,只需将service部分声明为正常的Android服务。在 <application> 部分中添加以下内容:
<service android:name=".QtAndroidService">
<!-后台运行->
<meta-data android:name="android.app.background_running" android:value="true"/>
<!-后台运行->
</service>
这样,该服务将在与 QtActivity 相同的过程中启动,该过程使您可以使用Java代码中的本机C ++调用。您可以在一个单独的进程中运行它,但是那样一来您就不能使用任何本地调用进行通信,因为Qt库没有为该进程加载。要在单独的进程上运行,请将其添加到服务标签中:
android:process=":qt_service"
扩展 QtService 时,需要声明其他项来加载Qt所需的所有必需的库,这些项主要与 QtActivity 的 <activity> 部分中的项相同。添加以下内容:
<service android:process=":qt_service" android:name=".QtAndroidService">
<meta-data android:name="android.app.lib_name" android:value="service"/>
<meta-data android:name="android.app.background_running" android:value="true"/>
</service>
注意:确保定义以下内容以在后台运行服务:
<meta-data android:name="android.app.background_running" android:value="true"/>
关于如何声明服务,有一些变化。其中一些已经在前面的manifest片段中使用过了。根据你的用例,将服务运行在与QtActivity相同的进程中或单独的进程中。
与QtActivity在同一进程中的服务。
要在与QtActivity相同的进程中运行一个服务,声明服务头如下。
<service android:name=".QtAndroidService">
单独程序送达
要在专用进程中运行服务,请声明服务头如下。
<service android:process=":qt_service" android:name=".QtAndroidService">
Qt加载 android.app.lib_name meta-data 定义的 .so 文件,并使用 android.app.arguments meta-data 设置的所有参数调用 main() 函数。在单独的进程中运行时,可以使用与主要活动相同的lib文件或单独的lib文件启动服务。
使用相同的.so Lib文件
使用与主要活动相同的 .so lib文件意味着服务将使用带有额外参数的相同入口点来将其与主要活动区分开。您可以根据提供的参数在 main() 函数中处理应用程序的执行。将以下参数声明添加到您的服务主体:
<!-应用程序参数->
<meta-data android:name="android.app.arguments" android:value="-service"/>
<!-应用程序参数->
然后确保服务 android.app.lib_name 与主要活动相同,并添加以下内容:
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
当使用相同的 .so lib文件时,应用程序的 main() 函数将执行两次,一次是启动主活动,第二次是启动服务。因此,您必须根据提供的参数处理每次执行。实现这一目标的一种方法如下:
if (argc <= 1) {
//处理主要活动执行的代码
} else if (argc > 1 && strcmp(argv[1], "-service") == 0) {
qDebug() << "Service starting with from the same .so file";
QAndroidService app(argc, argv);
return app.exec();
} else {
qWarning() << "Unrecognized command line argument";
return -1;
}
使用单独的.so Lib文件
在这种情况下,您需要一个带有 lib 模板的子项目,该模板为服务提供不同的可执行文件。一个示例项目 .pro 是:
TEMPLATE = lib
TARGET = service
CONFIG += dll
QT += core core-private
SOURCES += \
service_main.cpp
HEADERS += servicemessenger.h
在 service_main.cpp 中,您可以具有以下内容:
#include <QDebug>
#include <QAndroidService>
int main(int argc, char *argv[])
{
qWarning() << "Service starting from a separate .so file";
QAndroidService app(argc, argv);
return app.exec();
}
在 AndroidManifest.xml 中为服务定义 android.app.lib_name :
<meta-data android:name="android.app.lib_name" android:value="service"/>
与该处的沟通
Qt for Android提供了多种进程间通信(IPC)方法来与Android服务进行通信。根据你的项目结构,你可以使用Java服务的本机C++调用或Android BroadcastReceiver。
来自Java服务的本地C++调用
即使 Service 已扩展,这也可以与以与 QtActivity 相同的进程运行的服务使用。
有关详细信息,请参阅Qt Android 通知程序示例。
使用Android BroadcastReceiver
Android BroadcastReceiver支持在Android系统,应用程序,活动和服务之间交换消息。与其他Android功能类似,Qt可以使用广播接收器在 QtActivity 和您的服务之间交换消息。让我们从发送服务消息的逻辑开始。将以下内容添加到您的服务实现中,该实现调用sendBroadcast():
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int ret = super.onStartCommand(intent, flags, startId);
Intent sendToUiIntent = new Intent();
sendToUiIntent.setAction(ActivityUtils.BROADCAST_CUSTOM_ACTION);
sendToUiIntent.putExtra("message", "simple_string");
Log.i(TAG, "Service sending broadcast");
sendBroadcast(sendToUiIntent);
return ret;
}
然后,您需要从Qt的主要活动中创建并注册广播接收器。最简单的方法是使用方法创建自定义类,并在Java中实现所有逻辑。在以下示例中,服务通过调用本机方法 sendToQt() 将消息 "simple_string" 发送到Qt :
public class ServiceBroadcastUtils {
private static native void sendToQt(String message);
private static final String TAG = "ActivityUtils";
public static final String BROADCAST_CUSTOM_ACTION = "org.qtproject.example.qtandroidservice.broadcast.custom";
public void registerServiceBroadcastReceiver(Context context) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BROADCAST_CUSTOM_ACTION);
context.registerReceiver(serviceMessageReceiver, intentFilter);
Log.i(TAG, "Registered broadcast receiver");
}
private BroadcastReceiver serviceMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "In OnReceive()");
if (BROADCAST_CUSTOM_ACTION.equals(intent.getAction())) {
String message = intent.getStringExtra("message");
sendToQt(data);
Log.i(TAG, "Service sent back message to C++: " + message);
}
}
};
}
要利用所有这些,请按启动服务中所示启动服务,然后通过调用方法 registerServiceBroadcastReceiver() 注册广播接收器:
QJniEnvironment env;
jclass javaClass = env.findClass("org/qtproject/example/qtandroidservice/ActivityUtils");
QJniObject classObject(javaClass);
classObject.callMethod<void>("registerServiceBroadcastReceiver",
"(Landroid/content/Context;)V",
QtAndroid::androidContext().object());
使用Qt远程对象
Qt远程对象提供了一种在Qt进程之间共享API的简便方法。主要概念是服务过程中的服务器,并在Qt应用程序中具有副本,然后这两个部分便能够使用信号和插槽在彼此之间交换数据。
准备好复制品
让我们考虑一个带有单独的 .so lib文件的服务示例。定义一个 .rep 文件,该文件定义我们的通信类:
class ServiceMessenger {
SLOT(void ping(const QString &message));
SIGNAL(pong(const QString &message));
}
在服务子项目中将类定义为 servicemessenger.h :
#include "rep_servicemessenger_source.h"
class ServiceMessenger : public ServiceMessengerSource {
public slots:
void ping(const QString &name) override {
emit pong("Hello " + name);
}
};
然后,在主应用程序中将 .rep 文件添加到主应用程序和service .pro 文件中:
QT += remoteobjects
REPC_REPLICA += servicemessenger.rep
而在服务子项目中。
QT += remoteobjects
REPC_SOURCE += servicemessenger.rep
连接源和副本
在服务子项目的 main() 函数中定义Qt Remote Objects源节点:
#include "servicemessenger.h"
#include <QDebug>
#include <QAndroidService>
int main(int argc, char *argv[])
{
qWarning() << "QtAndroidService starting from separate .so";
QAndroidService app(argc, argv);
QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
ServiceMessenger serviceMessenger;
srcNode.enableRemoting(&serviceMessenger);
return app.exec();
}
然后,在应用程序的 main() 函数中,连接到源节点:
QRemoteObjectNode repNode;
repNode.connectToNode(QUrl(QStringLiteral("local:replica")));
QSharedPointer<ServiceMessengerReplica> rep(repNode.acquire<ServiceMessengerReplica>());
bool res = rep->waitForSource();
Q_ASSERT(res);
QObject::connect(rep.data(), &ServiceMessengerReplica::pong, [](const QString &message){
qDebug() << "Service sent: " << message;
});
rep->ping("Qt and Android are friends!");
这个例子从主应用程序的进程向服务发送了一条消息。服务用同样的消息进行回复,并打印在debug logcat上。
注意:当使用相同的 .so lib文件时,可以使用相同的方法。有关更多信息,请参见使用相同的.so Lib文件。
Using QAndroidBinder
QAndroidBinder是一个便利类,它通过实现Android中最重要的方法 Binder 来实现进程间通信。它允许在进程之间发送QByteArray或QVariant对象。
QML ajax请求
function request() {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
//XMLHttpRequest.DONE为状态枚举值4
if(xhr.readyState === 4) {
print('request DONE',xhr.status);
if(xhr.status === 200){
txt.text = xhr.responseText.toString();
}
}
}
//【get】
//xhr.open("GET", "http://127.0.0.1:54321/text?arg=Haha");
//xhr.send();
//【post】
xhr.open("POST", "http://127.0.0.1:54321/text");
//如果要使用post提交数据,添加此行
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("arg=Xixi");
}
//请求网络数据
function request() {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
print('request DONE',xhr.status);
if(xhr.status === 200){
print(xhr.responseText.toString())
view.model = JSON.parse(xhr.responseText.toString());
}
}
}
xhr.open("POST", "http://127.0.0.1:54321/json");
xhr.setRequestHeader("Content-type", "application/json");
//xhr.send("['red','green','blue','orange','cyan']");
xhr.send(JSON.stringify(['red','green','blue','orange','cyan']));
}
//访问本地文件
function requestLocal() {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
print('request DONE',xhr.status);
if(xhr.status === 200){
print(xhr.responseText.toString())
view.model = JSON.parse(xhr.responseText.toString());
}
}
}
//json文件的文本内容,字符串双引号:["red","green","blue"]
xhr.open("GET", "qrc:/localfile.json");
xhr.send();
}
QMediaPlayer视频没有画面显示,或播放卡顿问题解决(DirectShowPlayerService::doRender: Unresolved error code 80040266)
原因
Qt 中的多媒体播放,底层是使用DirectShowPlayerService,所以安装一个DirectShow解码器,例如LAV Filters,或者k-lite解码器,就可以解决运行出错问题
推荐:下载安装K-Lite
安装k-lite解码器:
http://www.codecguide.com/download_k-lite_codec_pack_standard.htm