Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Implementing signals / slots using QtDesigner - how to verify and what ?



  • As the title implies - how to verify that "connect" edited / build in QtDesigne - using "Edit Signals / slot" CODE actually exists (where?) and works.

    I am not asking for how to code "connect". That works fine.

    I build a simple push button -> clear "plain text" widget and it does not do as expected.

    I am looking for debugging , practical suggestions, not for "RTFM" references. Been there , done that.

    05264150-1fdc-41a6-a489-88c9c7744ecd-image.png


  • Lifetime Qt Champion

    Hi,

    What exactly does not work ?



  • Combining "go to slot .." with "Edit signal / slots" does not work.
    Got that fixed.

    The QtDesigner "edit signal/ slot" is limited to widget methods. That is fine.
    For example I can "connect" pushing button to zoom the text in "plain test" widget.
    To physically chnage the text cannot be done directly using "coonect" since QtDesigned has no method "setPlainText".

    So the qestion is how to combine QtDesifner "connect" to do MORE then QtWidget "minimal " methods.

    What does not work ?
    There is no visible means to check the QtDesigner "connect" call code.
    The whole QtDesigner GUI approach to edit slots / signals is "code invisible", hence hard to debug.
    .
    And I won't even mention trying to "connect" DIFFERENT objects using QtDesigner .


  • Lifetime Qt Champion

    What is generated by Designer can be found in the corresponding .ui file.

    Your requirements for setPlainText are not clear.


  • Lifetime Qt Champion

    Hi
    The possible features for visually connecting widgets is limited by nature. It cannot know custom signals etc so
    its mostly a convenient feature for straight cases.

    For production-quality apps, you should use code with the new syntax
    https://wiki.qt.io/New_Signal_Slot_Syntax
    That will inform you of issues compile-time and hence
    considered better than what is possible with Creator.

    It also makes it easier to debug as the compiler will warn you when it don't match up.

    So in short - don't use Designer for this. code is better for real apps.



  • Allow me to change the subject.

    My original post was directed to "connect" between objects.
    I have no issues "connect" in SAME object , such as MainWindow.
    ( I am not sure if signal /slot is not overkill in that case )
    I do undetstand the limits of QtDesigner and learning to tolerate that writing additional code. No big issue.

    I am still after how to have MainWindow in SAME ui with another widget.

    Short search uncovered something called "dock widget" (container widgets (?) which MAY be my answer.

    If I can translate the following into

    "usual way " ??

    "Since dock widgets are container widgets, they can be added to a form in the usual way. Once added to a form, dock widgets are not placed in any particular dock area by default; you need to set the docked property to true for each widget and choose an appropriate value for its dockWidgetArea property."

    I had to build the "dock object" from scratch , the "instructions"
    https://doc.qt.io/qt-5/designer-creating-mainwindows.html
    "drag and drops " do not quite make sense, perhaps my version of Qt ( current(?) and the doc do not match.

    So - I have "dock widget" form - WHAT is "the usual way " (?) to add it to MainWindow form ?



  • @mrjj said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    Hi
    The possible features for visually connecting widgets is limited by nature. It cannot know custom signals etc so
    its mostly a convenient feature for straight cases.

    For production-quality apps, you should use code with the new syntax
    https://wiki.qt.io/New_Signal_Slot_Syntax
    That will inform you of issues compile-time and hence
    considered better than what is possible with Creator.

    It also makes it easier to debug as the compiler will warn you when it don't match up.

    So in short - don't use Designer for this. code is better for real apps.

    Outch, yet another "socket".
    I admit not reading the article word by word , but did not see much of error checking.

    IMHO any time a connection is involved , no matter if software or hardware , checking for validity of the process is very helpful.
    Thankfully Qt will identify some obvious errors, but the fact that "connect" actually returns value seems to be forbidden to talk about.



  • @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    My original post was directed to "connect" between objects.

    So let's say your MainWindow is...well... your main window... And now you want to connect QObjects which are on your mainWindow form / inside your mainWindow class?
    It doesn't matter where the object actually is, as long as you have access to it, you can set up a connection.
    There are some "rules" or guidelines, of e.g. where you should set up your connection, because not every "dumb" object should know (= have pointers) about the rest of your program / classes. So not every connection in different directions is recommended, only because it would be possible.

    And for the rest, feel free to play around with different connections. If you create custom signals, you can nearly do whatever you like, as long as the class, where the connection is set, has a SENDER instance with a SIGNAL (your own or one of the standard ones) and a RECEIVER with a slot, which is called, when the signal "fires".

    To provide an example, because you dont want to read the manual :-)

    • pushButton_test is the name of a QPushButton, you've placed on your mainWindow form using QtDesigner
    • lineEdit_test is the name of your QLineEdit, you want to interact with, using your QPushButton

    In MainWindow Contructor (the place where you should set up such a connection):

    connect(ui->pushButton_test, &QPushButton::clicked, this, &MainWindow::buttonClicked);
    
    

    This connects the standard clicked-signal from QPushButton to your slot (function) buttonClicked (you can name it however you want ), but you need to declare it MANUALLY in your mainWindow header file and implement (define) it in your mainWindow.cpp

    Header

    public slots:
           void buttonClicked ( );
    

    There's is also a great feature in QtCreator, which will create the matching implementation to your function header (void buttonClicked () ). Right-Click your declaration and select Refactor -> Add definition in ... (your cpp)

    Your code file could look like this then:

    void MainWindow::buttonClicked()
    {
       // Here you can use your LineEdit
       // because you have still full access to everything, you've added with QtDesigner by using the "ui" pointer
    // which is basically your "mainWindow_ui.h"
    QString text = ui->lineEdit_test->text();
    if (text == "")
    {
    ui->lineEdit_test->setText("Button clicked");
    }
    else {
    ui->lineEdit_test->setText("");
    }
    }
    

    Every time you click your button, the displayed text in your QLineEdit will alternate between an empty QString (= nothing to see) and the text "Button clicked".

    To use a custom signal (because you want custom parameters), you simply add your signal to the object's header file.
    DO NOT implement signals. They just get declared and NEVER have any other return type than void.

    Could look like this:

    signals:
    
    void myAwesomeSignal(QString, int, qreal);
    

    This signal will transport a string, an integer and a double / float value to all its connected slots, which need to have the corresponding function header in order to accept all these three values, of course.

    Because Qt DOES NOT know about your custom signals (how should it?), you will need to emit them manually.
    So anywhere you want to use your signal and inform all connected objects, that e.g. a value has changed, you can do something like this:

    // [ . . . ]
    QString str = "Hello world!";
    int a = 42;
    qreal pi = 3.14;
    
    emit myAwesomeSignal (str, a, pi);
    
    // [ . . . ]
    

    I hope this will help (at least a bit).

    According your QDockWidget:
    I don't know if that is really the right widget in your case. Unless you want your sub-widgets of mainWindow in their own windows, which can be docked to the mainWindow or undocked to float around.



  • @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    Thankfully Qt will identify some obvious errors, but the fact that "connect" actually returns value seems to be forbidden to talk about.

    No, of course not. Of course you can check, if one of your connections failed, but in most cases the "reason" would make your program not compile.

    The "official" answer:

    The function returns a QMetaObject::Connection that represents a handle to a connection if it successfully connects the signal to the slot. The connection handle will be invalid if it cannot create the connection, for example, if QObject is unable to verify the existence of either signal or method, or if their signatures aren't compatible. You can check if the handle is valid by casting it to a bool.
    (From: https://doc.qt.io/qt-5/qobject.html#connect)



  • @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    I am still after how to have MainWindow in SAME ui with another widget.

    Took me a while to get what you are talking about.
    (Having multiple, designed widgets in one UI file and connect them with QtDesigner only)

    Don't do that and I think, it's not even possible.

    So forget about QDockWidget... actually don't forget about it, it's always good to know, what each QWidget is good for, but it's a wrong approach in this case.

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    I do undetstand the limits of QtDesigner and learning to tolerate that writing additional code. No big issue.

    C++ is still a programming language, where you have to write code. Otherwise it won't work. You can't learn a spoken language without saying or writing a word. Same here.
    There is no sign language for C++. Like I (and many others) have said in previous posts, QtDesigner is not meant for "coding". It's an auxiliary tool which should help you to design GUIs. Design, not to code whole apps. Every feature beyond that, is nice-to-have.

    If you just "tolerate" that you have to write some code (only a few lines, in your case), you should question your whole idea of starting to learn Qt / C++ and app development in general, even if your app are rather small.
    Programming GUI applications is not Photoshop nor MS Paint and if you stick to your "programming-in-QtDesigner" - method, you will never finish your programs (not even small ones).



  • @Pl45m4 said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    So forget about QDockWidget... actually don't forget about it, it's always good to know, what each QWidget is good for, but it's a wrong approach in this case.

    I am sorry I did not make it clearer - I am pretty conformable with signal/slot connection in SAME object. Perhaps I should have started new thread. Again - I do not need any more help with slots/ signals.

    If using QDocWidget is wrong approach ,
    the oblivious reply would be - what is correct approach?

    I did , for a change , read the manual, and it is clear to me that to have more than ONE object under the roof of MainWindow QDocWidget is way to go.
    I will say it again QtDesigner has limits , but I am not going to totally ignore it.

    I am not saying this just to ignore suggestions, been accused of that recently, but if the feature exists and is relatively well documented , why not use it ?

    That said , here is what is left to resolve

    1. Should DocWIdget be build in QtCreator or QtDesigner?
      The intend is to build the form and then transfer it to MainWindow as class / object.
    2. When the Dock Widget is build as form and is simply copied to MainWindow form - the location DOES not follow the changed location properties.
    3. The Dock Widget created as form has two buttons - maximize and clear . So far I am unable to remove them.


  • @Pl45m4 said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    This connects the standard clicked-signal from QPushButton to your slot (function) buttonClicked (you can name it however you want ), but you need to declare it MANUALLY in your mainWindow header file and implement (define) it in your mainWindow.cpp
    Header
    public slots:
    void buttonClicked ( );

    This process can be simplified, sort off.
    In QtDesigner select "Edit ->Edit widget" .
    Select widget and right click on it , then select "Go to slot..".
    From menu select " signal".
    DONE
    As pointed out the options are basic , but the process works.

    "connecting " signals and signals - using "Edit signals /slots " is a different story. Reminds me of "flying blindfolded " - but it also works - sort off.



  • @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    I am pretty conformable with signal/slot connection in SAME object.

    Connection by code or in QtDesigner?
    So why not use code? It would save you a lot of trouble.

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    what is correct approach?

    The correct approach would be to create a 2nd GUI class (.ui, .h, .cpp), design the form the way you want and then connect GUI elements in code. But it depends on what QWidgets we are talking about, since nearly everything in Qt is basically a QWidget or at least a QWidget- inherited subclass.

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    it is clear to me that to have more than ONE object under the roof of MainWindow QDocWidget is way to go.

    Where did you find that? QDockWidget is a container widget, which is a "window inside a window". QMainWindow has several DockingAreas, where you can dock your DockWidget window content or undock it, so you can move it around as separate window. Therefore it has this toolBar with maximize (undock) and close buttons. Everything happens at runtime

    I still don't think, that this is want you need :)

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    if the feature exists and is relatively well documented , why not use it

    I guess you misunderstood the use of QDockWidget

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    Should DocWIdget be build in QtCreator or QtDesigner?

    Both is possible, but if you use the designer way, the only thing you do there, is to place the widgets. All connections and logic stuff is done in code, unless you want to connect a QPushButton on this widget to the QWidget::close() slot (This is btw the only connection I would ever do in QtDesigner)

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    When the Dock Widget is build as form and is simply copied to MainWindow form - the location DOES not follow the changed location properties.

    Explain please. Copied to MainWindow form? Where? In QtDesigner?! What location and what properties it should follow? Do you use layouts?

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    The Dock Widget created as form has two buttons - maximize and clear . So far I am unable to remove them.

    Why you want to remove them? See first part of my answer.

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    This process can be simplified, sort off.
    In QtDesigner select "Edit ->Edit widget" .
    Select widget and right click on it , then select "Go to slot..".
    From menu select " signal".
    DONE

    I know that :)
    But what, if you haven't created your GUI element in QtDesigner and you still want to connect something?! :)
    The difference is that you want to use QtDesigner as much as possible, most people never use it or at least as rarely as possible.

    The learning effect is much higher when doing everything manually instead of just clicking some buttons in QtDesigner and dont understand what's going on... and coding two more lines doesn't hurt anyone :)

    @AnneRanch said in Implementing signals / slots using QtDesigner - how to verify and what ?:

    "connecting " signals and signals - using "Edit signals /slots " is a different story. Reminds me of "flying blindfolded " - but it also works - sort off.

    Yeah, because it's pain in the ass and not meant to be used for serious programs. I dont know why it's still there :)
    As soon as you want some extended / custom behavior, you reach the limit of what QtDesigner can do for you (apart from just placing widgets)... and this is the normal case.

    EDIT:

    Here is a demo of how QDockWidgets work:

    10 DockWidgets (1 - 10) with no content placed on a QMainWindow. After undocking, the blue areas will indicate where the DockingAreas are, to dock your widgets again. The DockWidgetContent can be everything

    DockWidget.gif

    (First try @mrjj ) :-)


Log in to reply