Cutom dialogs



  • Hello,
    I have a question about using dialogs created in designer.
    For example:
    class Keyboard: public QDialog, public BlurEffect
    {
    QPushButton b1;
    QPushButton b2;
    .
    .
    Ui::Keyboard *ui;
    }

    #include "Keyboard.h"
    class Dialog1: public QDialog, public BlurEffect
    {
    Keyboard *key;
    QPushButton b1;
    other components
    }
    key is created by new operator;
    Is it correct?

    Best regards


  • Moderators

    @wojj In this example you have Keyboard as a pointer, so you would have to use new to allocate it.

    So somewhere in your constructor add:

    key = new Keyboard(this);
    

    And you should be good to go.


  • Moderators

    @wojj If you only want to show the dialog as a modal dialog from, lets say a slot, then you can do it like this (without declaring the Keyboard *key pointer in the class):

    void Dialog1::on_button_pressed()
    {
        Keyboard keyboard;
        keyboard.exec();
    }
    


  • Thank you for answer.
    I initialize key as:

    key = new Keyboard;
    key->setParent(this);

    When I try to use
    key = new Keyboard(this);
    keyboard doesn't show after
    dialog1->show();
    To show keyboard I use a function
    void showKey()
    {
    key->show();
    key->activateWindow();
    key->raise();
    }
    I do not understand difference between
    key = new Keyboard(this);
    and
    key = new Keyboard;
    key->setParent(this);
    I think the result should be the same.
    Best regards


  • Moderators

    @wojj said in Cutom dialogs:

    class Keyboard: public QDialog, public BlurEffect
    {
    QPushButton b1;
    QPushButton b2;
    .
    .
    Ui::Keyboard *ui;
    }

    It would be however the code above isn't code that would work with that... Here is what it should look like:

    class Keybord : public QDialog, public BlurEffect
    {
       Q_OBJECT
    
    public:
       Keyboard(QWidget *parent = nullptr) : QWidget(parent);
    
    private:
       QPushButton b1;
       QPushButton b2;
       Ui::Keyboard *ui;
    };
    

    Then passing the this pointer to the constructor should work with keyboard->show() later on.



  • Hello,

    Can't make it work with this pointer in constructor.

    That's my keyboard.h
    class Keyboard : public QDialog, public BlurEffect
    {
    Q_OBJECT

    public:
    explicit Keyboard(QWidget *parent = 0);

    and keyboard.cpp

    Keyboard::Keyboard(QWidget *parent) :
    QDialog(parent), BlurEffect(),
    ui(new Ui::Keyboard)
    {
    ui->setupUi(this);

    The only way it work as I expect is to call empty constructor and then set parent
    key = new Keyboard;
    key->setParent(this);
    After that I can receive signals from keyboard and it's shown on the screen.
    Is anything incorrect in my code or is another way to create custom widgets I should use?
    Best regards


  • Moderators

    No that code is fine. Let me see the code where you instantiate the Keyboard object. That is where the this problem would show up.



  • This is the part of code:

    Dialog1::Dialog1(QWidget *parent) :
        QDialog(parent)
    {
        this->setWindowFlags(Qt::FramelessWindowHint);
        this->resize(800, 480);
        this->setStyleSheet(QString::fromUtf8("background-color: rgb(73, 76,69);"));
    
        labelList.clear();
        buttonList.clear();
        key = new Keyboard(this);
        //key = new Keyboard;
        //key->setParent(this);
        key->move(274, 5);
        connect(key, SIGNAL(key_pressed(int)), this, SLOT(key_pressed(int)));
        .
        .
        .
    }
    

    and Dialog1
    pDialog = new Dialog1();

    Dialog1 is a pointer in class that inherits QObject and contains gui pointer (pDialog), pointer to logic part for this gui and sends signal to higher level class. Generaly my application is built in that way. So I do not have one dialog where I change the widgets, I have many dialogs and I show and hide them if necessary.
    Best Regards

    @ambershark edit: added coded tags for easier reading.


  • Moderators

    Ok this is really weird..

    So what if you check the value of key->parent() right after you do a key = new Keyboard(this); and see if it matches the this pointer.

    Then do the alternate method using setParent(this) and test parent() again for it's value.

    There should not be any difference between setting the value for the parent in the constructor versus setting it with setParent() and if you are seeing differences that is weird.

    Also what happens if you add a key->show() right after key->move(...). Move should show it but maybe that is something that might help.

    The other part that concerns me is when you say you can't even receive signals. That shouldn't be affected by parenting at all. Setting a parent is optional. So it definitely wouldn't affect signal handling. That tells me something is very wrong in your app. None of the code you have posted shows any glaring issue though.



  • The function key->parent() returns value as expected, in both cases the same value this. When I call key->show() after key->move(...) the kayboard shows up but it shouldn't because all pDialog is hide and another dialog is processed (without keyboard). So the key object behaves like not part of pDialog.
    Everythig works ok when I use Keyboard without this pointer in contructor and then call setParent. So i think I will just accept this fact and use my custom dialogs in that way. Thank you for help ambershark.
    I didn't have problems with signals. I wrote: I can receive... (sorry bad English).
    Best regards


  • Moderators

    @wojj As long as setParent does what you need then go with that. It is not working properly though. That usually means there's either a bug in Qt or more than likely a bug in your code somewhere.

    You're welcome for the help, and your english was just fine. :)



  • Thank you for help.
    I will try to briefly explain my problem.
    My application seems to work correctly (I can switch between dialogs, communication ports works ok), but when I leave it working, it receives a segmentation fault after few hours. In the simplest case it sends and receives about 10 bytes on serial port every 300ms, and refreshes QLabel every 1 second with system time.
    Serial port I use is in main thread (it was in separate but the result was the same). I have some move serial's in separate threads but in the simplest case there are no communication.
    The application works on embedded linux system. Usually after SIGSEGV (or sometime SIGILL), the gdb backtrace doesn't help because it ends up with some disassembled code.
    All I can see are some functions that I do not use in my code ie.

    QPainter::drawImage(const QRectF &, const QImage &, const QRectF &, Qt::ImageConversionFlags 
    

    or

    QTextEngine::shapeLine(QScriptLine const&))
    #1  0xb6982534 in ?? () from /lib/libQt5Gui.so.5
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    

    On qDebug() logs "void LtimerTimeout()" is the last, so I think it stopped in timeLabel->setText(temp);

    void LoginDialog::timerTimeoutSlot()
    {
        qDebug() << "void LtimerTimeout()";
        if(!refreshTime)
            return;
        QString temp = QTime::currentTime().toString("hh:mm:ss");
        if(temp.size() != 8)
            return;
        for(int i = 0; i < temp.size(); i++)
        {
            if(i%2 != 0)
                temp.insert(i, " ");
        }
        timeLabel->setText(temp);
    }
    

    I asked about custom widgets because I suspected that maybe they are not initialized properly and may lead to segmentation fault (going to uninitialized memory). Do you have any suggestions how to solve this problem?

    Best regards


  • Moderators

    @wojj This is a lot to try to debug without actually having code/debugger..

    From what I can see though here's a few ideas:

    1. It's possible you have a corrupt stack like the debugger suggests. The usual culprit there is stack overflows. I don't see any stack memory being used in the code you shared, so there may be another reason for this.

    2. You mentioned threading at one point. This type of bug screams thread synchronization issues. If you are single threaded now then it's not it, but if you still have multiple threads I would look at your sync objects and make sure they are properly protecting your memory.

    3. Is it possible timeLabel has gone out of scope or is being accessed from another thread (other than the one it was created in)? That is the line probably causing the crash. A quick test could be to comment out the timeLabel->setText(temp) line and instead just throw it in a qDebug() << temp to test. If your crash stops you probably have a bad object there. It got cleaned up more than likely and is a dangling pointer.

    Hope that guides you a bit. Good luck! :)



  • The thread synchronization was the first point when I tried to find a bug. I use Queued connections between threads, and when I directly read/write between threads I use QReadWriteLocker object and it seems to work correct.
    timeLabel is simply the pointer to QLabel defined in LoginDialog class with new operator and it shouldn't go out of scope.
    But I found another problem which I think can leads to segmentation fault.
    I created a very simple example:

    #include "dialog.h"
    #include "obj.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Dialog w;
        Obj *pObj = new Obj;
    
        w.show();
    
        return a.exec();
    }
    

    where:
    Obj is:

    #include <QObject>
    
    class Obj : public QObject
    {
        Q_OBJECT
    public:
        explicit Obj(QObject *parent = nullptr);
    
    signals:
    
    public slots:
    };
    

    and empty constructor

    #include "obj.h"
    
    Obj::Obj(QObject *parent) : QObject(parent)
    {
    
    }
    

    I put breakpoint in main function in line Obj *pObj = new Obj; and then step into (F11), then in Obj constructor I've got gdb warning
    Can't find linker symbol for virtual table
    but only for crosscompiled Qt. For normal pc compilation I didn't get any warnings. So I hope the problem is in compilation options for Qt, but I will have to verify that.
    Best regards


  • Moderators

    @wojj Hmm, can you check which libs of Qt you are compiling against and which ones your app is using on the target? That warning is usually caused by differences in the version of Qt libs.

    You can use ldd yourapplicaton to show the libs. If they are system level or something you didn't expect, try having it use the libs you built against. Deploy it with them and set your LD_LIBRARY_PATH before launching.

    Here you can see a quick demo of ldd showing that I'm using a custom Qt at /usr/local/Qt:

    [shockwave] ~/tmp > ldd tmp
            linux-vdso.so.1 (0x00007fff1c2e0000)
            libQt5Widgets.so.5 => /usr/local/Qt/lib/libQt5Widgets.so.5 (0x00007f59a0d01000)
            libQt5Gui.so.5 => /usr/local/Qt/lib/libQt5Gui.so.5 (0x00007f59a0566000)
            libQt5Core.so.5 => /usr/local/Qt/lib/libQt5Core.so.5 (0x00007f599fe46000)
    

    Beyond that all I can say is moc can do weird things, lol. It wouldn't surprise me if it's just the debugger getting confused by the moc'd code. I would investigate the real reasons before writing that off though.

    Also, mixed Qt libs could indeed be causing your crashing issues that you are seeing.


Log in to reply
 

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