PDA

View Full Version : On calling close() the ui does not close



gfernandes
26th February 2014, 10:46
In Qt I have a 2 forms say FirstUI and SecondUI. The main.cpp opens the FirstUI. Here I check if the databases needed for the application are present and if not present creates a new one. It also checks if there are any wifi network details stored in the database. If there are details of the last connected wifi, then the application scans for available networks and connects to the wifi network using the details from the database.

Now if there is no wifi detail in the database or if the network listed in the database is not present or if the application was unable to connect to the wifi network it will emit a signal WifiNotConnected();

I have connected the signal to a slot that opens the SecondUI.


connect(this,SIGNAL(WifiNotConnected()),this,SLOT( OpenSecondUI()));
.....

void FirstUI::OpenSecondUI()
{
SecondUI *sec = new SecondUI();
this->close();
sec->show();
}
The SecondUI opens, but this does not close the FirstUI.

EDIT 1: If the wifi details are present, I have a class (WifiBoot) that inherits QObject and does the connection tasks for me. Since I want the GIF file to be played in the GUI and the connection to occur same time I have instantiated the class (WifiBoot) that does the wifi connection and moved it to another thread. After the wifi is connected I emit the finished signal which is connected to the slot to open the SecondUI


connect(worker,SIGNAL(finished()),this,SLOT(Finish edConnection()));

void FirstUI::FinishedConnection()
{
OpenSecondUI();
}
Here it closes the FirstUI and opens the SecondUI. But in the first case it does not. Why is this happening? Is there a better way to go about it? Any help is appreciated

Any help is appreciated

EDIT 2
My code

main.cpp


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

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

return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMovie>
#include <QThread>
#include "databasemanager.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

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

private slots:
void openSecondUI();

void createDatabaseTables();

void ConnectWifi();

void DatabaseError(QString);

void NotConnected();

void FinishedConnecting();


signals:
void NoWifiConnection();

void CallSlotToConnectWifi();

private:
Ui::MainWindow *ui;

int value;

DataBaseManager *dbm;

QMovie *movie;

QThread *Connect_to_wifi_thread;
};

#endif // MAINWINDOW_H

mainwindow.c

#include <QTimer>
#include <QDebug>
#include <QFuture>
#include <QProcess>
#include "secondui.h"
#include "secondwindow.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "wificonnecting.h"
#include "wifibootconnect.h"

#define DATABASE_NAME "UniSettings"
#define NOT_CONNECTED "NA"
#define CONNECTED "Connected"
#define ASSIGN_NULL ""

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

//Play a gif movie on qlabel
movie = new QMovie(":/GIFfiles/GIFfiles/WelcomeCircular.GIF");
this->ui->GIFLabel->setMovie(movie);
movie->start();

//Initializing the int variable
value = 0;

connect(this,SIGNAL(NoWifiConnection()),this,SLOT( NotConnected()));

//Connecting to the database
//DataBaseManager class instantiation
dbm = new DataBaseManager;

if(!(dbm->ifopen()))
{
qDebug() << "Connecting";

//Open the database and return the status
bool checkOpen = dbm->openDB(DATABASE_NAME);

//If open display message connected
if(checkOpen)
{
qDebug() << "connected to database";
createDatabaseTables();
}
//else display message not exist
else
{
qDebug() << "Database does not exist";
}
}

//If any known wifi exists connect to it
QSqlQuery *qry = new QSqlQuery(dbm->db);

if(qry->exec("SELECT * FROM LastState WHERE name=\'Wifi\'"))
{
//If it matches then get all the data from that rowNotConnected();
if(qry->next())
{
QString Connection_State = qry->value(2).toString();
qDebug() << Connection_State;
QString Connection_essid = qry->value(3).toString();
qDebug() <<Connection_essid;

if(Connection_State== NOT_CONNECTED)
{
qDebug() << "Not connected to any wifi before shutdown";

emit NoWifiConnection();
}
else
{
//Call function to connect to wifi in another thread
qDebug() << "connected";
ConnectWifi();
}
}
}
else
{
qDebug() << dbm->lastError().text();
}



}

MainWindow::~MainWindow()
{
delete ui;

qDebug() << "Welcome";

qDebug() << "Closing the connection to the database";

//Close the database connection
dbm->closeDB();
}

/*
*@brief: Function to open the SecondUI class
*
*/
void MainWindow::openSecondUI()
{
//Instantiate the SecondUI class
SecondUI *sec = new SecondUI();

//Show the SecondUI ui
sec->show();

//Close MainWindow class
this->close();
}

void MainWindow::createDatabaseTables()
{
bool success = dbm->createBTDeviceTable();
qDebug() << success;

success = dbm->createBTPairedDeviceTable();
qDebug() << success;

......

success = dbm->create_LastState_Table();
qDebug() << success;
}

void MainWindow::DatabaseError(QString err)
{
qDebug() << "Database error EMITTED: " << err;
}

void MainWindow::NotConnected()
{
qDebug() << "Not connected EMITTED" ;
openSecondUI();
}

void MainWindow::FinishedConnecting()
{
qDebug() << "Finished emitted by boot up wifi process";
openSecondUI();
}

void MainWindow::ConnectWifi()
{
qDebug() << "I am here";
Connect_to_wifi_thread = new QThread;

WifiBootConnect *worker = new WifiBootConnect();

worker->moveToThread(Connect_to_wifi_thread);

//SIGNALS AND SLOTS
connect(worker,SIGNAL(DataBaseError(QString)),this ,SLOT(DatabaseError(QString)));
connect(worker,SIGNAL(NotConnected()),this,SLOT(No tConnected()));
connect(worker,SIGNAL(finished()),this,SLOT(Finish edConnecting()));
connect(Connect_to_wifi_thread,SIGNAL(started()),w orker,SLOT(ConnectWifiProcess()));
connect(worker,SIGNAL(finished()),Connect_to_wifi_ thread,SLOT(quit()));
connect(worker,SIGNAL(finished()),worker,SLOT(dele teLater()));
connect(Connect_to_wifi_thread,SIGNAL(finished()), Connect_to_wifi_thread,SLOT(deleteLater()));

//Start the thread
Connect_to_wifi_thread->start();
}

ttimt
26th February 2014, 10:54
How bout disconnecting your signal and slot?












Don't trust me. My rank's novice

anda_skoa
26th February 2014, 13:20
The SecondUI opens, but this does not close the FirstUI. Why is this happening? Is there a better way to go about it?


Nothing obvious wrong with the presented code.
Have you tried hide() instead of close()?

Since FirstUI seems to be your primary UI, it might actually make sense to keep it around to the time SecondUI is finished, no?

Cheers,
_

gfernandes
26th February 2014, 14:13
Dear Anda_skoa,

Thank you for your reply. I have tried hide(); it does not work either. I checked the return value of this->close(); and it is true

Basically I have 30+ ui which have QWidget as the base class designed using QtDesigner.

I will never return back to the FirstUI, because I start my application there by loading all the possible databases required for the application. Then I moved ahead with the SecondUI which is the user login.

Once logged in I have a selectionMenu which has 4 pushbuttons.

The link shows the flow
http://stackoverflow.com/questions/21040657/switching-between-multiple-ui-forms-in-qt

Now the simplest way to go about is using this->close and showing the nextUI

Is it a bad approach?

I am a java/android developer and this project is my first with Qt. I am not very sure how to go about it.

Added after 5 minutes:

@ttimt
thank you for your reply. I tried that, does not work either

anda_skoa
26th February 2014, 19:38
One problem that I can see is the emit in the constructor.

If you program reaches that emit, it will invoke the slot and show the second UI.
The close is meaningless at this point because "this" has not be shown yet.
In fact the close at this point is followed by a show() in main().

My suggestion is to make sure the window is up and running before attempting any thing else.

To do that move any constructor code after


connect(this,SIGNAL(NoWifiConnection()),this,SLOT( NotConnected()));

into a new slot and call this slot "delayed", i.e. after the event loop has started processing events


QTimer::singleShot(0, this, SLOT(theNewSlot()));


Actually you can remove the signal and the connect and just call openSecondUI() directly when you encouter you need it.
I.e. no need to send a signal to "yourself".

Cheers,
_

P.S.: if you run all your UIs "full screen" on the device, then the suggestion on stackoverflow to use a QStackedWidget is indeed the way to go unless each UI is so large on memory consumption that you need to get rid of the previous screen when you show a new one.

gfernandes
27th February 2014, 08:31
@anda_skoa

YAYYY :) You are awesome!! How I wish I had a guide like you, a recent college graduate like me would actually be a better programmer..

Thank you so much :) yayyy :)

Giz