【问题标题】:Open QDialog and run the QProcess simultaneously打开 QDialog 并同时运行 QProcess
【发布时间】:2013-10-29 14:46:41
【问题描述】:

这是我的 btconnect.h 文件

#ifndef BTCONNECT_H
#define BTCONNECT_H

#include "scandialog.h"

namespace Ui {
class BTConnect;
}

class BTConnect : public QWidget
{
    Q_OBJECT

public:
    explicit BTConnect(QWidget *parent = 0);
    ~BTConnect();

private slots:
    void on_ScanButton_clicked();

    void ScanBTDevices();

    //some slots here

    void ScanDialogShow();

    void ScanDialogClose();

public slots:
//some slots here

private:
    Ui::BTConnect *ui;

    QProcess BTscan_Process;

    scanDialog *scan;
};

#endif // BTCONNECT_H

btconnect.cpp

BTConnect::BTConnect(QWidget *parent) :
QWidget(parent),
ui(new Ui::BTConnect)
{
    //set the userinterface as BTConnect.ui
    ui->setupUi(this);

    scan = new scanDialog(this);
}


void BTConnect::ScanDialogShow()
{
    scan->show();
}

void BTConnect::ScanDialogClose()
{
    scan->close();
}

void BTConnect::ScanBTDevices()
{
    ScanDialogShow();

    //Command to scan nearby bluetooth devices
    //"hcitool scan"
    QString cmd("hcitool scan");

    //start the process
    BTscan_Process.start(cmd);

    //Wait for the processs to finish with a timeout of 20 seconds
    if(BTscan_Process.waitForFinished(20000))
    {
        //Clear the list widget
        this->ui->listWidget->clear();

        //Read the command line output and store it in QString out
        QString out(BTscan_Process.readAllStandardOutput());

        //Split the QString every new line and save theve in a QStringList
        QStringList OutSplit = out.split("\n");

        //Parse the QStringList in btCellsParser
        btCellsParser cp(OutSplit);

        for(unsigned int i = 0; i<cp.count(); i++)
        {
           //writing in listwidget
        }

    }

    ScanDialogClose();
}

void BTConnect::on_ScanButton_clicked()
{
    //Scan for available nearby bluetooth devices
    ScanBTDevices();
}

如果我使用上面的代码,qdialog scandialog 确实会在进程开始时打开并在 qlistwidget 中加载数据时关闭,但不会显示 qdialog scandialog 的内容。如果我将 show() 更改为 exec(),将显示内容,但 QProcess 在对话框关闭之前不会运行。

我希望对话框在 Qprocess 启动时打开,并在 qlistwidget 加载扫描数据时关闭。我希望显示 scandialog 的内容。它有两个标签。一个是 .GIF 文件,另一个是扫描文字。

感谢任何帮助。

【问题讨论】:

    标签: qt signals-slots qprocess qdialog


    【解决方案1】:

    当你做show时你永远不会返回到事件循环(因为waitForFinished)当你做exec时你永远不会继续处理代码

    您应该连接到finished 信号而不是waitForFinished 并在那里处理它,并使用将取消它的单次计时器:

    void BTConnect::on_BTscanFinished()//new slot
    {
       //Clear the list widget
        this->ui->listWidget->clear();
    
        //Read the command line output and store it in QString out
        QString out(BTscan_Process.readAllStandardOutput());
    
        //Split the QString every new line and save theve in a QStringList
        QStringList OutSplit = out.split("\n");
    
        //Parse the QStringList in btCellsParser
        btCellsParser cp(OutSplit);
    
        for(unsigned int i = 0; i<cp.count(); i++)
        {
           //writing in listwidget
        }
        ScanDialogClose();
    }
    
    void BTConnect::ScanBTDevices()
    {
        ScanDialogShow();
    
        //Command to scan nearby bluetooth devices
        //"hcitool scan"
        QString cmd("hcitool scan");
    
        //start the process
        connect(BTscan_Process, SIGNAL(finished()), this, SLOT(on_BTscanFinished()));
        BTscan_Process.start(cmd);
        QTimer::singleShot(20000, scan, SLOT(close()));
    }
    

    【讨论】:

    • 非常感谢!!你真棒! :)
    【解决方案2】:

    问题在于QDialog::execQProcess::waitForFinished 函数阻塞了事件循环。 永远不要阻塞事件循环。所以你只需要更异步地做事情。

    QProcess 类可以使用readReadStandardOutput 等信号异步处理。并且QDialog 可以使用open 插槽异步显示。

    例子:

    void ScanBTDevices() {
        // Open dialog when process is started
        connect(process, SIGNAL(started()), dialog, SLOT(open()));
    
        // Read standard output asynchronously
        connect(process, SIGNAL(readyReadStandardOutput()), SLOT(onReadyRead()));
    
        // Start process asynchronously (for example I use recursive ls)
        process->start("ls -R /");
    }
    
    void onReadyRead() {
        // Write to list widget
        dialog->appendText(QString(process->readAllStandardOutput()));
    }
    

    数据将在进程生成期间附加到对话框中。 也可以使用QProcess::finished 信号关闭对话框。

    【讨论】:

    • 谢谢你的回答:)
    最近更新 更多