How to display Label for 30 seconds and then hide it?



  • Hi. I make a RFID system. When the RFID card cross the RFID module the label shows welcome to users. but I want to show the label for 30-45 seconds.
    I write these codes:

    if (AcceptCard())
    {
         ui->lbl->setText("WELCOME");
         sleep(30);
         ui->lbl->setText("  ");
    }
    

    but it display text and hide it suddenly and difficult to see that. I want show the message for 30 seconds.
    Can I used timer and start it in if block or you suggest better way?

    thanks for your help :)


  • Lifetime Qt Champion

    Hi,

    Rather use a QTimer. Something like:

    QTimer::singleShot(30000, ui->lbl, &QLabel::hide);
    

    This means that you should also call ui->lbl->setVisible(true); before setText

    Or if you only want to set the text:

    QTimer::singleShot(30000, [&](){ ui->lbl->setText("   ")});
    


  • @SGaist :

    Thanks for answer. You mean I put this code in my if block and it shows my label in 30 second?is it?


  • Lifetime Qt Champion

    The first version will hide the label and the second will replace the text like your code samples after 30 seconds.



  • I did that. but not worked. This is my code in qt creator for embedded device. For embedded device I found this format : void QTimer::singleShot ( int msec, QObject * receiver, const char * member ) [static] (thanks for your suggestion to use QTimer::singleShot ) .REF:http://linux.die.net/man/3/qtimer

    //QTimer::singleShot(30000, ui->lbl_welcome,&QLabel::hide);
    QTimer::singleShot(30000,ui->lbl_welcome,SLOT(hide()));
    //I made slot for hide label (not worked) 
    //then I put your code in slot(SLOT(&QLabel::hide), but not worked) and show error on my ARM device as you can see in log
    

    it show the welcome but not hide it.
    these are my device log :

    [root@FriendlyARM /fgit]# ./TimeAssistent1 -qws -font 18
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    Object::connect: No such slot QLabel::hidelbl()
    Object::connect:  (receiver name: 'lbl_welcome')
    ^C
    [root@FriendlyARM /fgit]# ./TimeAssistent1 -qws -font 14
    ^C
    [root@FriendlyARM /fgit]# tftp -r TimeAssistent1 -g 192.168.101.4;chmod +x TimeAssistent1;
    TimeAssistent1       100% |*******************************| 70144  --:--:-- ETA
    [root@FriendlyARM /fgit]# ./TimeAssistent1 -qws -font 14
    Object::connect: Parentheses expected, slot QLabel::&QLabel::hide
    Object::connect:  (receiver name: 'lbl_welcome')
    [root@FriendlyARM /fgit]# ./TimeAssistent1 -qws -font 14
    -----> for the last code update does not show error but do not hide the lable (
    QTimer::singleShot(30000,ui->lbl_welcome,SLOT(hide()));)
    

  • Moderators

    Check again your code. This means you are trying to connect the signal to a slot hidelbl() in QLabel, but QLabel does not have such a slot. The correct name is hide().

    Object::connect: No such slot QLabel::hidelbl()
    

  • Moderators

    One note: the documentation you're using is for Qt 3.3.8!
    Current version is 5.6.0



  • @jsulm said:

    Check again your code. This means you are trying to connect the signal to a slot hidelbl() in QLabel, but QLabel does not have such a slot. The correct name is hide().

    Object::connect: No such slot QLabel::hidelbl()
    

    It does not accept QLabel::hide.
    hidelbl is my slot that i define in my project but also not worked.

    One note: the documentation you're using is for Qt 3.3.8!
    Current version is 5.6.0

    this format accept on my ARM Embedded device.
    NOTE:My Qt on my device is Qt4.8.3


  • Moderators

    Hi,

    What version of Qt are you using?

    @MhM93 said:

    It does not accept QLabel::hide.

    It should accept QLabel::hide(). Check your code again.

    If you can't get it to work, post your code and any error messages you see.

    hidelbl is my slot that i define in my project but also not worked.

    You can implement a new slot in your own class, but you cannot implement it in QLabel.



  • I created a slot (runread) and write this code to run my slot.
    ...
    QtConcurrent::run(this,&MainWindow::runread);
    ...
    In this slot I wrote
    ...
    QTimer::singleShot(200,ui->lbl_welcome,&QLabel::hide);
    ...
    I wrote above code in if block that accept RFID card.
    But it show this error:(also I have Qtopia 4.8
    )
    The error: In member function 'void MainWindow::runread()'
    No matching function for call to 'QTimer::singleShot(int,QObject*&,void(QWidget::)())'
    Candidates are : Static void QTimer::singleShot(int,QObject
    ,const char*) in qtimer.h


  • Moderators

    You're using new connect syntax which was invented in Qt 5 if I remember right.
    That's why @JKSH asked which Qt version you're using.
    Try the old syntax:

    Try QTimer::singleShot(200,ui->lbl_welcome,SLOT(hide()));
    


  • @jsulm said:

    You're using new connect syntax which was invented in Qt 5 if I remember right.
    That's why @JKSH asked which Qt version you're using.
    Try the old syntax:

    Try QTimer::singleShot(200,ui->lbl_welcome,SLOT(hide()));
    

    I try that , It works when I call the line in mainwindow block before QtConcurrent.But QTimer::singleshot not worked in runread function.

    //QTimer::singleShot(2000,ui->lbl_welcome,SLOT(hide()));    
    //when run this code in mainwindow function ,it was running 
    //but when this line in runread function it did not work.
    
        QtConcurrent::run(this,&MainWindow::runread);
    

  • Moderators

    @MhM93 said:

        QtConcurrent::run(this,&MainWindow::runread);
    

    What does MainWindow::runread() do? Can you show us its code?

    Note that QWidget is not thread-safe, so your code should not call QWidget functions from another thread. You should only call QWidget functions in the GUI thread. (Your MainWindow inherits QWidget, so it needs to follow thread rules too)



  • this is runread function :

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->statusBar->addWidget(ui->label,0);
        ui->label->setText("the status of device");
        ui->lbl_welcome->hide();
        //QTimer::singleShot(2000,ui->lbl_welcome,SLOT(hide()));
    
        QtConcurrent::run(this,&MainWindow::runread);
        //-----------------------
    
    }
    
    void MainWindow::runread()
    {
        //-----------------------
        fd=-1;
        db = QSqlDatabase::addDatabase("QSQLITE");//not dbConnection
        QString path = "VirtualDB";
        db.setDatabaseName(path);
    
        if(!db.open())
        {
            ui->label->setText("Error to open database");
        }
        else
        {
            QSqlQuery q;
            q.exec("create table IF NOT EXISTS Absent(card varchar(20) , "
                                    "DateTime varchar(50));");
            while(fd==-1)
            {
                openport();
    
                if (fd!=-1)
                {
                    configport();
                    ui->label->setText(" open port");
                    ui->label->setText("  Put your card please: ");
    
                    if(fd!=-1)
                    {
                        for(int i=0;i<100;i++)
                        {
                             if ((numbytes = read(fd,buf2, MAXDATASIZE)) != -1)
                             {
                                 ui->label->setText(" read card");
    
                                buf2[numbytes] = '\0';
                                usleep(10000);
                                QString s1(buf2);
                                memset(buf2,'\0',MAXDATASIZE);
                                read(fd,buf2, MAXDATASIZE-1) ;
                                QString s2(buf2);
                                memset(buf2,'\0',MAXDATASIZE);
                                string card=(s1+s2).toStdString();
                                QString dt=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
                                
                                q.prepare("insert into Absent(card,DateTime) values(?,?);");
                                q.bindValue(0,card.c_str());
                                q.bindValue(1,dt);
                                if(!q.exec())
                                    qDebug()<<q.lastError();
                                string result=(" WELL COME ");
                                
                                ui->lbl_welcome->show();
    //                            QTimer::singleShot(30000, ui->lbl_welcome,&QLabel::hide);
                                //QTimer::singleShot(2000,ui->lbl_welcome,SLOT(hide()));
                                hide();
    
                             }
                             else
                             {
                                 if(TransferDatatoUSB())
                                 {
                                     QString filename="save.txt";
                                     QFile file( filename );
    
                                    
                                     q.exec("select card,DateTime from Absent;");
    
                                         CreateFile();
                                         if ( file.open(QIODevice::ReadWrite) )
                                         {
                                             QTextStream stream( &file );
                                             while (q.next()) {
                                                 QString str=q.value(0).toString();
                                                 str.append("     ");
                                                 str.append(q.value(1).toString());
                                                 str.append(" ");
                                                 //o <<str.toStdString();
                                                 stream << str << endl;
                                         }
                                     }
                                     CopyToUSB();
                                 }
    
                             }
                        }
                    }
                }
            }
        }
    
    }
    
    // I do this instead of QTimer but I thinck it is not true.(but it works)
    void MainWindow::hide()
    {
        //QTimer::singleShot(2000,ui->lbl_welcome,SLOT(hide()));
        sleep(2);
        ui->lbl_welcome->hide();
    }
    

  • Lifetime Qt Champion

    You're doing it wrong. Like @JKSH wrote, don't call GUI function from another thread. But that's not all, you have a potential infinite loop, you are executing database queries without checking that they did indeed ran. You also don't warn when save.txt doesn't open and if you install your application in a system folder it will fail because you won't have the rights to do that.

    You MainWindow is doing way to many things.

    The first thing to do is to clean things a bit:

    • Get the database initialization out of there. You should do it somewhere else, e.g. before your widget creation in main.cpp
    • What does openport do ? Do you really need to call it each time you want to read something ? Depending on what it is, you should have a small helper class that handles the communication to that card reader. That helper class should emit signals that you connect your MainWindow to update your GUI.
    • Why mix std string and QString ? There's no real need in this case, just use QString.
    • Why do you need to sleep during 10ms ?
    • What do you use save.txt for ? Wouldn't a copy of your sqlite database make more sense ?
    • Hide is not a virtual function so your reimplementation in MainWindow is wrong.
    • What do you copy in CopyToUsb ?


  • @SGaist said:

    You're doing it wrong. Like @JKSH wrote, don't call GUI function from another thread. But that's not all, you have a potential infinite loop, you are executing database queries without checking that they did indeed ran. You also don't warn when save.txt doesn't open and if you install your application in a system folder it will fail because you won't have the rights to do that.

    You MainWindow is doing way to many things.

    The first thing to do is to clean things a bit:

    • Get the database initialization out of there. You should do it somewhere else, e.g. before your widget creation in main.cpp
    • What does openport do ? Do you really need to call it each time you want to read something ? Depending on what it is, you should have a small helper class that handles the communication to that card reader. That helper class should emit signals that you connect your MainWindow to update your GUI.
    • Why mix std string and QString ? There's no real need in this case, just use QString.
    • Why do you need to sleep during 10ms ?
    • What do you use save.txt for ? Wouldn't a copy of your sqlite database make more sense ?
    • Hide is not a virtual function so your re implementation in MainWindow is wrong.
    • What do you copy in CopyToUsb ?

    Hi and thanks for reply.
    I have a lot of question :

    1- You said :"don't call GUI function from another thread". but why? I need a thread to read data from serial port and listen on it. when receive data, send it to my database, so i decide to use fork. but fork not work in widget programing (as I see. It just works on console application.)
    If my code is wrong so how can I listen on port without hanging my embedded device?

    2- You said : " you have a potential infinite loop". my loop just listen the serial port and also check the USB port. If USB connected to device should get backup from database and save it in save.txt and copy that to USB.

    3- You said : "You also don't warn when save.txt doesn't open and if you install your application in a system folder it will fail because you won't have the rights to do that." . How to check that? I open the file with bash system command as root (the user is root in my embed). Is it possible to not opening the file as root? (So I should make admin rule while I create the file?)

    3- You said : " Get the database initialization out of there. You should do it somewhere else, e.g. before your widget creation in main.cpp" . Always the database should define in main.cpp? This is the best? And what happen if the database define in mainwindow.cpp?

    4- You said : "What does openport do ? Do you really need to call it each time you want to read something ? Depending on what it is, you should have a small helper class that handles the communication to that card reader. That helper class should emit signals that you connect your MainWindow to update your GUI." Openport is a function to open the device, when I want to listen the port I call it.( just one time I call this function ) could you give me a reference for define a helper class that you mentioned?

    5- You said : "Why mix std string and QString ? There's no real need in this case, just use QString." Sorry. I correct it. this cause my little experience in writing code with c++ and Qt.

    6- You said : " Why do you need to sleep during 10ms ?" . When I read data from RFID card with EM-18 module reader. It sends data in 2 part. for example like this :
    RFID MONITORING => '010B7528'
    RFID MONITORING => '297E'
    but the real card ID is : '010B7528297E'
    I put that sleep and read data again and attach the both. (I do not find the reason why my data comes in 2 part)

    7- You said : "What do you use save.txt for ? Wouldn't a copy of your sqlite database make more sense ?" I want to copy that to text file with a specific format to get data from another application for example win base program to save data in SQL or MySQL or etc.

    8- You said : "Hide is not a virtual function so your re implementation in MainWindow is wrong." Hide is just a simple function that I define instead of QTimer::singleShot(... , ... , ...) . I can change the name of my method. It is not re implementation .

    9-You said : "What do you copy in CopyToUsb ?" It is just copy save.txt to USB flash


  • Moderators

    Hi,

    @MhM93 said:

    1- You said :"don't call GUI function from another thread". but why?

    Because, like I wrote before, GUI classes are not thread safe. Their functions must only be called from one thread. This article should provide more info: http://doc.qt.io/qt-5/threads-reentrancy.html

    Let us know if something is not clear.

    I need a thread to read data from serial port and listen on it. when receive data, send it to my database, so i decide to use fork. but fork not work in widget programing (as I see. It just works on console application.)
    If my code is wrong so how can I listen on port without hanging my embedded device?

    First, learn how to use Qt's signals and slots: http://doc.qt.io/qt-5/signalsandslots.html

    Then, use signals to communicate between different threads. Do not call GUI class functions from another thread.

    2- You said : " you have a potential infinite loop". my loop just listen the serial port and also check the USB port.

    Is it guaranteed that fd == -1 at some point?

    3- You said : "You also don't warn when save.txt doesn't open and if you install your application in a system folder it will fail because you won't have the rights to do that." . How to check that?

    Check the return value of QFile::open().

    Also, think: What would you do if the program fails to open the file for some reason?

    3- You said : " Get the database initialization out of there. You should do it somewhere else, e.g. before your widget creation in main.cpp" . Always the database should define in main.cpp? This is the best?

    It doesn't have to be defined in main.cpp. You can also define it in another class.

    And what happen if the database define in mainwindow.cpp?

    Then your code becomes messy.

    Ideally, mainwindow.cpp should only contain code that is related to the GUI. The serial port and the database are not related to the GUI.

    4- You said : "What does openport do ? Do you really need to call it each time you want to read something ? Depending on what it is, you should have a small helper class that handles the communication to that card reader. That helper class should emit signals that you connect your MainWindow to update your GUI." Openport is a function to open the device, when I want to listen the port I call it.( just one time I call this function ) could you give me a reference for define a helper class that you mentioned?

    There is a simple example in the QThread documentation: http://doc.qt.io/qt-5/qthread.html

    8- You said : "Hide is not a virtual function so your re implementation in MainWindow is wrong." Hide is just a simple function that I define instead of QTimer::singleShot(... , ... , ...) . I can change the name of my method. It is not re implementation .

    It is best not to use the same name as an existing function.



  • Really really thanks.


  • Moderators

    @MhM93 said:

    Really really thanks.

    You're welcome, and good luck! :) Please let us know if you want anything clarified.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.