PDA

View Full Version : Making form translucent and an animated pop up while running QProcess



gfernandes
28th October 2013, 09:45
Hi,

I am running a QProcess that scans for available bluetooth devices. When this process is going on, I would like to make the QWidget form translucent and a pop up window with an animation like a sand watch moving in circles with a text saying scanning.. At the end of the process the pop up form should disappear and the QWidget should be in focus again. Is it possible to do it in QT? If so could you please direct me how to go about it. Maybe some examples?

Thank you so much in advance for your help

Giselle

anda_skoa
28th October 2013, 12:31
For the popup you could use a QDialog subclass with a QLabel and a QMovie for the animation.

You could connect the finished signal of your scanning to the dialog's close() slot and then call its exec() method.

Most system will apply some effect on the underlying window themselves, so I am not sure whether making it semi-transparent as well is a good idea.

Cheers,
_

gfernandes
29th October 2013, 10:42
Hi,

Thank you for your reply. I created a QDialog the way you told me to. It is working fine. The only problem is I do not know how to show it when the QProcess is running the scan. Following are the ways I followed and failed

1. I connected the QPushButton clicked() function that calls a function to start the QProcess with a function which calls the show() function for QDialog

This shows the QDialog after the scanning process is finished :(

2. In the function where the QProcess does the scanning of Bluetooth devices, at the start of the function I call another function to show() QDialog, at the end of the scanning function I call another function to close() QDialog.

This works the way I want. It opens the QDialog when I press the scan button and disappears when the function finishes,but it shows the QDialog as just a frame with nothing inside.

I do not know how to go about it

Please do help

Giselle

anda_skoa
29th October 2013, 12:34
That sounds like the event loop being blocked by something, e.g. the slot that starts the QProcess not returning.

Can you post that code?

Btw, one option to show the dialog when the process starts and hide it when it finishes is to connect the dialogs show/hide to the started/finished signals of the process.

Cheers,
_

gfernandes
29th October 2013, 12:53
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();
}



This is my code for the second method I told earlier

aamer4yu
29th October 2013, 12:57
An easy way would be to show a gif file as animation rather than doing it yourself.

Also is your scan dialog modal or non modal ??

gfernandes
29th October 2013, 13:47
scandialog.h



#ifndef SCANDIALOG_H
#define SCANDIALOG_H

#include <QDialog>

namespace Ui {
class scanDialog;
}

class scanDialog : public QDialog
{
Q_OBJECT

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

private:
Ui::scanDialog *ui;
};

#endif // SCANDIALOG_H


scandialog.cpp


#include "scandialog.h"
#include "ui_scandialog.h"
#include <QMovie>

#define PATH_TO_GIF "/root/QTProjects/GIF files/sandwatch.GIF"

scanDialog::scanDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::scanDialog)
{
ui->setupUi(this);
QMovie *movie = new QMovie(PATH_TO_GIF);
this->ui->movieLabel->setMovie(movie);
movie->start();
}

scanDialog::~scanDialog()
{
delete ui;
}


I set the modal property for scandialog as true in btconnect.cpp

Added after 35 minutes:

if I change show() to exec(), the scandialog is shown with the animated sandwatch.. but the QProcess does not start. How do I do both simultaneously? :confused:

Kindly please help

gfernandes
30th October 2013, 09:39
I asked the same question in stackoverflow.com and got an amazing solution

http://stackoverflow.com/questions/19661469/open-qdialog-and-run-the-qprocess-simultaneously/19664531?noredirect=1#19664531



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()));
}

anda_skoa
30th October 2013, 10:08
Yes, your problem was that you called waitForFinished(), which blocks the caller. Since the caller is the UI Thread, it can't process any UI events, like showing or updating the dialog.

Regarding your solution: I would recommend to connect the timer to the process, i.e. make the timer stop the scanning, and close the dialog when the process has finished.

Otherwise you close the dialog and needlessly keep scanning.

And do the connect in the constructor, otherwise each call to the "start scan" slot connects again, resulting in multiple invocations of the "scan finished" slot

Cheers,
_

gfernandes
4th November 2013, 10:44
Thank you.. Did all the modifications you suggested. :) Thank you so much. You're awesome!