背景
目前我用的是Qt5.15.2来编写Qt程序,环境的配置看我这篇文章【Qt5.15.2配置Android开发环境】
项目中的一些配置的截图:


1.文件读写
假如直接用 QFileDialog::getExistingDirectory来获取路径的话,会得到类似这样的字符串
content://com.android.externalstorage.documents/tree/primary%3A下载
这样的假如直接利用这一串字符串在其他增加文件名来读写文件的话,是会失败的。
比如
QString dirStr = QFileDialog::getExistingDirectory(this, "dir", "");
// dir此时会是类似这样的字符串: content://com.android.externalstorage.documents/tree/primary%3A下载
QString fileName = dirStr + "/123.txt";
QFile file(fileName);
if(file.open(QFile::WriteOnly | QFile::Truncate))
{
}
else
{
// 百分百进来这里
}
经过查阅资料及自己的测试,正确的做法如下:
1.动态申请读写权限
2.将QFileDialog::getExistingDirectory得到的路径进行转换
3.将百分号相关字符转换为正常字符
相关代码如下
#ifdef Q_OS_ANDROID
#include <QtAndroid>
// 申请读写权限
bool checkPermission()
{
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;
}
}
r = QtAndroid::checkPermission("android.permission.READ_EXTERNAL_STORAGE");
if(r == QtAndroid::PermissionResult::Denied) {
QtAndroid::requestPermissionsSync( QStringList() << "android.permission.READ_EXTERNAL_STORAGE" );
r = QtAndroid::checkPermission("android.permission.READ_EXTERNAL_STORAGE");
if(r == QtAndroid::PermissionResult::Denied) {
return false;
}
}
return true;
}
// 路径的转换;这里后面可能还要考虑其他情况
QString androidUrlToLocalUrl(QString dirStr)
{
if(dirStr.startsWith("content://com.android.externalstorage.documents/tree/primary%3A"))
{
dirStr = dirStr.replace("content://com.android.externalstorage.documents/tree/primary%3A",
"/storage/emulated/0/");
}
dirStr = QByteArray::fromPercentEncoding(dirStr.toUtf8());
return dirStr;
}
#endif
void test()
{
#ifdef Q_OS_ANDROID
bool ret = checkPermission();
if(ret == false)
{
// 一定要有权限,没有的话,软件可以退出了
return;
}
#endif
QString dirStr = QFileDialog::getExistingDirectory(this, "dir", "");
#ifdef Q_OS_ANDROID
dirStr = androidUrlToLocalUrl(dirStr);
#endif
QString fileName = dirStr + "/123.txt";
QFile file(fileName);
if(file.open(QFile::WriteOnly | QFile::Truncate))
{
}
else
{
}
}
2.QComboBox的下拉列表不显示或者显示为黑

一开始查看debug输出,以为是opengl的问题

结果一通测试后,还是不行:
// QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
// QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
// // 配置OpenGL格式
// QSurfaceFormat format;
// format.setRenderableType(QSurfaceFormat::OpenGLES);
// format.setVersion(3, 0); // 尝试2.0或3.0版本
// format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
// format.setSwapInterval(0); // 交换间隔设为0或1
// QSurfaceFormat::setDefaultFormat(format);
后来经过查找资料、经过测试,发现好像是样式的问题。【C0004.Qt中QComboBox设置下拉列表样式后,下拉列表样式无效的解决办法】
不用设置样式表,只要setItemDelegate即可
comboBox->setItemDelegate(new QStyledItemDelegate(comboBox));
但是这样一个个设置,工作量太大,因此可以全局地处理
// 这样没用
// QApplication::setStyle(QStyleFactory::create("android"));
// QApplication::setStyle(QStyleFactory::create("Fusion"));
// QApplication::setStyle(QStyleFactory::create("windowsvista"));
// QApplication::setStyle(QStyleFactory::create("windows"));
QApplication a(argc, argv);
MainWindow w;
w.show();
// 遍历所有QObject,找到属于QComboBox的对象
QList<QComboBox*> comboBoxList = w.findChildren<QComboBox*>();
foreach (QComboBox* comboBox, comboBoxList) {
// 对每个QComboBox执行操作
comboBox->setItemDelegate(new QStyledItemDelegate(comboBox));
}
return a.exec();
这样操作后便正常了。

参考:
【Qt Android 申请写文件到内部存储】
【QT Android开发 URL转本地路径】
【Qt for android 之 QFileDialog正确使用方式】