gpt4 book ai didi

android - 为什么相同的代码在 QPushButton::clicked() 中有效而在 QAction::triggered() 中崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 11:30:11 25 4
gpt4 key购买 nike

我有一个非常简单的 Qt 程序,我正在通过 QtCreator 3.0.1 (Qt 5.2.1) 在 Android 4.4.2(Nexus 5 手机)上部署。

此程序创建一个虚拟文件,然后建议通过 Java SDK 调用使用用户的默认文件编辑器打开它。可以通过单击按钮或选择菜单项来打开文件。

  • 当使用按钮时,文件被打开
  • 使用菜单项时,文件打开,但应用程序崩溃。

当实际执行相同的代码时,为什么一个崩溃而另一个不崩溃?

来自按钮:

enter image description here

然后我按 F10 并继续。

enter image description here enter image description here

从菜单:

enter image description here

然后我按 F10,它崩溃了(我的程序结束了,但 Android 的文件查看器仍然打开):

enter image description here

Qt 应用程序日志报告:

F/libc    ( 6949): Fatal signal 11 (SIGSEGV) at 0x00000001 (code=1), thread 6971 (ample.MenuCrash)
"org.qtproject.example.MenuCrash" est mort.

enter image description here enter image description here

代码如下:

专业文件:

QT       += core gui androidextras widgets
TARGET = MenuCrash
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
CONFIG += mobility
MOBILITY =

主要.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void openFile();

private:
QString m_fileName;
};

#endif // MAINWINDOW_H

主窗口.cpp:

#include "mainwindow.h"
#include <fstream>
#include <QMenuBar>
#include <QMenu>
#include <QVBoxLayout>
#include <QAndroidJniObject>
#include <QPushButton>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_fileName = "/sdcard/Download/test_file.txt";

std::fstream file;
// create the file
file.open( m_fileName.toStdString().c_str(), std::ios_base::out );
if ( file.is_open() )
{
// Write something in the file
file << "Hello!!!" << std::endl;
file.close();

QWidget* parent = new QWidget( this );
QVBoxLayout* layout = new QVBoxLayout( parent );
setCentralWidget( parent );

QMenuBar* pBar = menuBar();
QMenu* pMenu = pBar->addMenu( "" );

QPushButton* button = new QPushButton( "Open file", this );
layout->addWidget( button );
QObject::connect( button, SIGNAL(clicked()), this, SLOT(openFile()) );

pMenu->addAction( "Open file now", this, SLOT(openFile()) );

QAction* action = pMenu->addAction( "Open file later" );
QObject::connect( action, SIGNAL(triggered()), this, SLOT(openFile()), Qt::QueuedConnection );
}
else
{
QMessageBox::critical(this,"Error","Unable to create file");
}
}

MainWindow::~MainWindow()
{

}

void MainWindow::openFile()
{
/* Translate this java code:
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
File file = new File( m_fileName );
intent.setDataAndType(Uri.fromFile(file), "text/plain");
myActivity.startActivity(intent);
*/
QAndroidJniObject activity =
QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
"activity",
"()Landroid/app/Activity;");
if ( activity.isValid() ) //activity is valid
{
QAndroidJniObject intent("android/content/Intent","()V");
if ( intent.isValid() )
{
QAndroidJniObject name = QAndroidJniObject::fromString(m_fileName);
QAndroidJniObject type = QAndroidJniObject::fromString("text/plain");
QAndroidJniObject action = QAndroidJniObject::fromString("android.intent.action.VIEW");

if ( type.isValid() && name.isValid() && action.isValid() )
{
QAndroidJniObject file( "java/io/File","(Ljava/lang/String;)V",name.object<jobject>());
if ( file.isValid() )
{
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "fromFile", "(Ljava/io/File;)Landroid/net/Uri;", file.object<jobject>());
if ( uri.isValid() )
{
intent.callObjectMethod("setDataAndType","(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;",uri.object<jobject>(),type.object<jobject>());
intent.callObjectMethod("setAction","(Ljava/lang/String;)Landroid/content/Intent;",action.object<jobject>());

if ( intent.isValid() )
{
activity.callObjectMethod("startActivity","(Landroid/content/Intent;)V",intent.object<jobject>());
}
}
}
}
}
}
}

注意:

  • 我尝试使用 Qt::QueuedConnection 延迟菜单项的执行,使用菜单时同样崩溃
  • 我尝试将 QAction::triggered() 连接到 QPushButton::click() (pMenu->addAction( "Open file now", button , SLOT(click()) );), 使用菜单时同样崩溃
  • 我尝试将 QPushButton::clicked() 连接到 QAction::trigger() (QObject::connect( button, SIGNAL(clicked() ), action, SLOT(trigger()) );), 点击按钮时不会崩溃。所以似乎可以触发 QAction。

...所以现在我试试 stackoverflow....;-)

刚刚创建了一个 Qt 错误报告:https://bugreports.qt-project.org/browse/QTBUG-41395

最佳答案

Qt 团队的 Christian 解决了这个问题......

参见 https://bugreports.qt-project.org/browse/QTBUG-41395

修复是替换

activity.callObjectMethod("startActivity","(Landroid/content/Intent;)V",intent.object<jobject>());

通过

activity.callMethod<void>("startActivity","(Landroid/content/Intent;)V",intent.object<jobject>());

因为 startActivity 是一个 void 方法...

关于android - 为什么相同的代码在 QPushButton::clicked() 中有效而在 QAction::triggered() 中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25075883/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com