Откройте QDialog и одновременно запустите QProcess

Это мой файл 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, а другой с текстом, говорящим о сканировании.

Любая помощь приветствуется.


person gfernandes    schedule 29.10.2013    source источник


Ответы (2)


вы никогда не возвращаетесь в цикл обработки событий, когда делаете show (из-за waitForFinished), и вы никогда не продолжаете код обработки, когда делаете exec

вместо waitForFinished вы должны подключиться к сигналу finished и обработать его там и использовать таймер одиночного выстрела, который его отменит:

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()));
}
person ratchet freak    schedule 29.10.2013
comment
Большое спасибо!! Вы классные! :) - person gfernandes; 30.10.2013

Проблема в том, что функции QDialog::exec и QProcess::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 можно закрыть диалог.

person fasked    schedule 29.10.2013
comment
Спасибо за ваш ответ :) - person gfernandes; 30.10.2013