简体   繁体   English

QThread的复杂用法-

[英]Complex use of QThread -

I have wrote an app in QT/C++. 我已经用QT / C ++编写了一个应用程序。 This app have multiple classes to manage window, treewidget.. and a custom class. 这个应用程式有多个类别来管理视窗,treewidget ..和一个自订类别。

The goal of the app is to be android file transfer -like in QT/c++ on MacOSx. 该应用程序的目标是实现Android文件传输-类似于MacOSx上的QT / c ++。

Currently the entire app is working in one thread which include the UI management and the android device management. 目前,整个应用程序都在一个线程中运行,其中包括UI管理和android设备管理。 The android device access is managed by a class named DeviceManager. android设备访问由名为DeviceManager的类管理。 This class will mostly open the device, read it, add/delete files.... 此类主要是打开设备,读取设备,添加/删除文件...。

What I want to do is to create a thread which will handle all method defined in the DeviceManager. 我想做的是创建一个线程,该线程将处理DeviceManager中定义的所有方法。 I want the UI on one thread and the devicemngr in a separate thread. 我希望UI在一个线程上,而devicemngr在单独的线程上。

Here is my current code : 这是我当前的代码:

main.cpp main.cpp中

int main(int argc, char *argv[])
{
    PULS_mtp_error_t error = ERROR_GENERAL;
    QThread PulsDeviceThread;

    QApplication app(argc, argv);

    DeviceMngr *MyMtp = new DeviceMngr;
    error = MyMtp->OpenDevice();
    ...
    MainUI MyWindow(*MyMtp);
    MyWindow.show();
    return app.exec();

}

the MainUI class is defined as below MainUI类的定义如下

MainUI::MainUI(DeviceMngr& device) :
    m_device(device)
{

    m_closing = false;

    setWindowTitle(QString::fromUtf8("PULS"));
    resize(800,600);
    setUnifiedTitleAndToolBarOnMac(true);
    /* Creation of the Top bar section */
    createBackForwardButton();
    createLogoSection();
    createAddFolder();

    QWidget *TopBarWidget = new QWidget();
    TopBarWidget->setFixedHeight(61);
    QHBoxLayout *TopBarLayout = new QHBoxLayout(TopBarWidget);
    TopBarLayout->addWidget(BackForwardSection);
    TopBarLayout->addWidget(LogoSection);
    TopBarLayout->addWidget(AddFolderSection);

    /* Creation of Tree View Section */
    createTreeView();

    /* Creation of the bottom bar section */
    createInfoSection();

    /*about*/
    aboutAction = new QAction(tr("&About"),this);
    connect(aboutAction, SIGNAL(triggered()),this ,SLOT(aboutPuls()));

    QMenu *helpMenu = new QMenu("Help", this);
    helpMenu->addAction(aboutAction);
    menuBar()->addMenu(helpMenu);

    /*Overall Layout*/
    QWidget *MainWindowWidget = new QWidget();
    QVBoxLayout *MainWindowLayout = new QVBoxLayout(MainWindowWidget);

    MainWindowLayout->setSpacing(0);
    MainWindowLayout->addWidget(TopBarWidget);
    MainWindowLayout->addWidget(TreeViewSection);
    MainWindowLayout->addWidget(CreateInfoSection);

    setCentralWidget(MainWindowWidget);

    PulsUnplugged = false;
#if 1
    activeTimer = new QTimer(this);
    activeTimer->setSingleShot(false);
    activeTimer->setInterval(200);
    connect(activeTimer, SIGNAL(timeout()), this, SLOT(PulsDetection()));
    activeTimer->start();
#endif
    show();
}

Some of the method such as createTreeView will use the m_device to access also to the device. 某些方法(例如createTreeView)将使用m_device来访问该设备。

void MainUI::createTreeView()
{

    TreeViewSection = new QWidget();

    QVBoxLayout *TreeViewLayout = new QVBoxLayout(TreeViewSection);

    MyTreeWidget = new MyNewTreeWidget(m_device, *this);

    TreeViewLayout->addWidget(MyTreeWidget);
}

MyNewTreeWidget will also need to access to the DeviceMngr class. MyNewTreeWidget也将需要访问DeviceMngr类。

Most of class used for the UI management can access to the DeviceMngr class. 用于UI管理的大多数类都可以访问DeviceMngr类。 I don't know how to use the QThread to make sure that all UI classes can access to the DeviceMngr class. 我不知道如何使用QThread来确保所有UI类都可以访问DeviceMngr类。

I was thinking to create a Qthread in the main.cpp but I do not see how to add slots/signals in the main.cpp and DeviceMngr will have signals/slots to discuss with all other thread. 我正在考虑在main.cpp中创建一个Qthread,但是我看不到如何在main.cpp中添加插槽/信号,DeviceMngr将具有与所有其他线程讨论的信号/插槽。 the main will need for example to open the device and receive the result. 例如,主机将需要打开设备并接收结果。

Do I need to create all signal/slot connection in the main or I can just add what I need in the different classes and create the connections when needed. 我是否需要在主体中创建所有信号/插槽连接,还是可以在不同的类中添加所需的内容,并在需要时创建连接。

Any idea ? 任何想法 ? I have tried a first implementation but it not really working fine. 我已经尝试了第一个实现,但实际上效果不佳。

Thanks 谢谢

I would suggest creating the worker thread and moving your DeviceMngr to it. 我建议创建工作线程并将DeviceMngr移到该线程。 Its slots (and whole event loop) will run in the context of the thread and you must use Qt's signal/slot mechanism that will ensure thread safe access to DeviceMngr from other QObjects. 它的插槽(和整个事件循环)将在线程的上下文中运行,并且您必须使用Qt的信号/插槽机制,以确保线程安全地从其他QObject访问DeviceMngr

int main(...) {
    // ...
    QThread MtpThread;
    DeviceMngr MyMtp;
    MyMtp.moveToThread(&MtpThread);

    // connect signals/slots of DeviceMngr
    // ...

    // launch the thread
    MtpThread.start();

    // should you need to call slots of DeviceMngr from main use metacalls
    QMetaObject::invokeMethod(&MyMtp, "nameOfSlot");

    // run application

    // in the end join
    MtpThread.quit(); // stop event queue
    MtpThread.wait(); // join the thread
}

I hope you get the idea. 希望您能明白。 Key is moveToThread() and metacalls. 关键是moveToThread()和metacalls。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM