Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Read variables between more than 2 forms

Read variables between more than 2 forms

Scheduled Pinned Locked Moved General and Desktop
25 Posts 2 Posters 7.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    avmg
    wrote on last edited by
    #1

    Hello,

    I know that many people ask this before but i tried to follow their answers without success... The question is how can i send data between forms. I tried with signals and slots, the problem i have is this:

    I have 3 forms:

    • In form1 i create form2.
    • In form2 i create form 3.

    And now in form3 i want to read one variable from the form 2, the problem is that from the form 3 i can't do something like:

    form2.get_variable();

    because form2 is created in the form1 and the command i write is already in form3. As i saw the solution must be solved with signals and slots, when i try the program compile but it crashes when tries to send the data...

    I don't know if i explained well, i hope it jeje

    Thanks!!
    avmg

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      There are many ways to solve this. It depends on the details.

      In the simplest case you don't need signals/slots at all. Just pass the stuff from Form2 to Form3 as the constructor param or a setter function.

      If it has to go the other way around then pass a pointer (this) in the constructor of Form3 and get data from Form2 through it, just like you wrote:
      form2ptr->get_variable()

      Example:
      @
      class Form3 : public QDialog {
      public:
      ...
      void setF2Ptr(Form2 * ptr) { f2 = ptr; }
      void whatever() { f2->get_stuf(); }
      private:
      Form2 * f2;
      }

      void Form2::foo {
      Form3 f3();
      f3.setF2Ptr(this);
      f3.exec();
      }
      @

      The same goes for Form1 and Form2 and however many links in chain you need.
      Signals are usually used to signal that something occurred. They are not a mean to retrieve a value (they are void). Slots on the other hand are used to react to these signals.

      1 Reply Last reply
      0
      • A Offline
        A Offline
        avmg
        wrote on last edited by
        #3

        Hi,

        I tried that, but it shows me the error: 'f2' does not name a type, (changing f2 by my form name obviusly)

        Thanks for reply.

        1 Reply Last reply
        0
        • Chris KawaC Offline
          Chris KawaC Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by
          #4

          This was an example. I omitted some stuff for brevity. I thought you could figure out that you need #include, not implement stuff in the header etc.

          @
          //Form3.h
          class Form2; //forward declaration

          class Form3 {
          ... //as before except those:
          void setF2Ptr(Form2 * ptr);
          void whatever();
          }

          //Form3.cpp
          #include "Form3.h"
          #include "Form2.h"

          void Form3::setF2Ptr(Form2 * ptr) { f2 = ptr; }
          void Form3::whatever() { f2->get_stuf(); }
          @

          1 Reply Last reply
          0
          • A Offline
            A Offline
            avmg
            wrote on last edited by
            #5

            Ok, i still have some problem and i think it's related with the place i created the forms:

            for example:

            //Form1.h
            public:
            Form2 * f2;

            //Form1.cpp
            //In the constructor:
            Form2 *f2= new Form2();

            I want to show f2 when i press one button, in the button action i wirte:

            f2.show();

            But when i press the button it crashes... Before i was creating f2 in the button action instead the constructor, but i changed because i thought is better create one time and show and hide.

            Which is the recomended way to create and show forms??

            1 Reply Last reply
            0
            • A Offline
              A Offline
              avmg
              wrote on last edited by
              #6

              Ok was crashing because i had something wrong on the constructor, but anyway i wish to know how is the properly way to do it.

              Thanks.

              1 Reply Last reply
              0
              • Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #7

                There's no "one size fits all". Proper way depends on what those forms are.
                For example if there's gonna be one of these shown and hidden all the time then it's pretty much like you did it, except you should give your forms a parent so that you don't need to manually delete them.

                If it's some sort of dialog then it's better not to keep it in memory and create/run it locally with its own event loop (via exec) eg.
                @
                void Form2::showSomeDialog() {
                Form3 dialog(this);
                dialog.exec();
                }
                @

                If there are gonna be lots of these forms, like in a cam monitoring app where each cam has a window, then a factory pattern with some managing object might be better.

                You don't find "the one" pattern and try to force your app into it. It's the other way around. Know what it's meant to do and then choose a pattern that fits.

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  avmg
                  wrote on last edited by
                  #8

                  Hi,

                  I tried what Chris explained me but without success...The program doesn't compile, maybe a tried to mix what Chris suggest me on his both answers but i did something wrong. I tried also with connect and signals, but even the program compiles, the fact is that nothing happens when execute the "emit" instruction, it's like not receiving on the other side. Anyway if i want to read vectors from other forms maybe this way is not the best...

                  So basically, i want to learn how to read data between forms, but also the problem can be in how i create them, and their pointers.

                  What i did was, i created the form2 on the form1.cpp, and when i press a button i show this form2, but to do this the form2 must be declared on form1.h beacuase if not it says that it wasn't declared on this scope. What i have not clear is how to create the forms pointers or instances to access to the other forms.

                  Thanks.

                  1 Reply Last reply
                  0
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    What is the intended lifespan of form2? If it's a modal dialog then you just need it in the local scope of execution of the button press, not in form1.h eg.
                    @
                    //form1.cpp
                    #include "form1.h"
                    #include "form2.h"

                    ...

                    void Form1::someButton_clicked() {
                    Form2 dialog(this);
                    auto result = dialog.exec();
                    ...//do something with result
                    }
                    @

                    If it's not a dialog, but a window that should be opened "in parallel" to form1 then this is one way:
                    @
                    //form1.h
                    class Form2; //forward declaration
                    class Form1 {
                    ... //constructor and other stuff
                    private:
                    Form2* window = nullptr;
                    };

                    //form1.cpp
                    #include "form1.h"
                    #include "form2.h"

                    void Form1::someButton_clicked() {
                    if(!window)
                    window = new Form2();
                    window->show();
                    }

                    Form1::~Form1() {
                    delete window; //remember to clean up
                    }
                    @

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      avmg
                      wrote on last edited by
                      #10

                      Ok, i did the second option, because it's a form very used and i prefer to hide and show when needed, therefore i create the Form2 in the Form1 constructor and show when clicking a button. It's the same as you did but creating the Form2 at the "beginning" instead each time the button is clicked.

                      And how i add the instances to access to the Form1 from the Form2??

                      Thanks!

                      1 Reply Last reply
                      0
                      • Chris KawaC Offline
                        Chris KawaC Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        It's more a matter of design then anything else. Should form2 "know" what form1 is or should it accept data from anywhere?
                        It's often a good idea to decouple classes from each other i.e. if form1 creates form2 then form2 should know nothing about form1.

                        It's also a matter of design if form2 should reach to form1 for data or should form1 set some data in form2. As before the second option often is preferable.

                        So for example this way only form1 knows form2, not the other way around:
                        @
                        //form2.h
                        class Form2 {
                        ...
                        public:
                        inline void setSomeData(SomeType data) { someData = data; }
                        private:
                        SomeType someData;
                        }

                        //form1.cpp
                        void Form1::someButton_clicked() {
                        auto foo = ...; //get it from wherever
                        form2->setSomeData(foo);
                        form2->show();
                        }
                        @

                        If on the other hand you really need to couple form1 and form2 so that they know about each other here's an example:
                        @
                        //form2.h
                        class Form1; //forward declaration
                        class Form2 {
                        ...
                        public:
                        void setForm1Ptr(Form1* ptr);
                        private:
                        Form1* f1 = nullptr;
                        }

                        //form2.cpp
                        #include "form2.h"
                        #include "form1.h"

                        void Form2::setForm1Ptr(Form1* ptr) {
                        f1 = ptr;
                        }

                        void Form2::doSomeStuff() {
                        if(f1) {
                        auto stuff = f1->getSomeStuff(); //here you access form1 from form2
                        }
                        }

                        //form1.cpp
                        //form1.cpp
                        void Form1::someButton_clicked() {
                        form2->setForm1Ptr(this); //you can put this anywhere, eg. in constructor
                        form2->show();
                        }
                        @
                        The second one is a bit messier. Usually a design where everything knows about everything complicates fast and is harder to maintain. You should strive for a directional tree-like design, where one class only reaches down, not up to the class that created the instance of it.

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          avmg
                          wrote on last edited by
                          #12

                          Hi,

                          I tried the second option, but the program crashes when executes f1 = ptr. It says:

                          The inferior stopped because it received a signal from the Operating System.

                          Signal name :
                          SIGSEGV
                          Signal meaning :
                          Segmentation fault

                          Also i add the next line to the .pro file to use the nullptr:

                          QMAKE_CXXFLAGS += -std=c++0x

                          What do you think?

                          1 Reply Last reply
                          0
                          • Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            [quote author="avmg" date="1403203760"]Also i add the next line to the .pro file to use the nullptr:
                            QMAKE_CXXFLAGS += -std=c++0x
                            [/quote]
                            This is not portable and will cause an error when used with compiler like MSVC. Use this instead:
                            @
                            CONFIG += c++11
                            @

                            As for the segfault - well then you're "doing something wrong"™ ;) Most likely calling setForm1Ptr on an uninitialized form2 pointer. Start your debugger and check. I'm not really good at "guess debugging" ;)

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              avmg
                              wrote on last edited by
                              #14

                              Ok i will check deeply but i found this problem debugging, if i not debug the program crashes and show on the application output:

                              The program has unexpectedly finished.

                              Does the f1 name be the same as the created at the begginig or it doesn't matter?

                              1 Reply Last reply
                              0
                              • Chris KawaC Offline
                                Chris KawaC Offline
                                Chris Kawa
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                [quote author="avmg" date="1403204829"]Does the f1 name be the same as the created at the begginig or it doesn't matter?[/quote]
                                I don't think I understand. f1 is the pointer to the first form. It's a member of Form2 class. I'm just using placeholder names. You can (and should) name them something meaningful.

                                The sequence of events should be as follows:

                                • you create a Form1 instance (form1)
                                • somewhere (eg. in the constructor of Form1) you create instance of Form2 (form2)
                                • somewhere(eg. right after the above) you use form2->setForm1Ptr to set pointer to form1 (f1) inside form2
                                • somewhere in form2 you use that pointer f1 to get data from form1

                                If you do it in any other order it will likely result in a segfault.
                                For example call to form2->setForm1Ptr when form2 is not yet created will segfault.
                                Using f1 before it was set will segfault.
                                Using f1 after form1 was destroyed will segfault.
                                Calling form2->setForm1Ptr after form2 was destroyed will segfault.
                                You get the picture ;)

                                [quote author="avmg" date="1403204829"] if i not debug the program crashes and show on the application output: The program has unexpectedly finished.[/quote]
                                That means you've got a bug. That's what you use a debugger for ;)

                                1 Reply Last reply
                                0
                                • A Offline
                                  A Offline
                                  avmg
                                  wrote on last edited by
                                  #16

                                  Solved!

                                  The problem was that i was creating the instance on the constructor like this:

                                  Form1* form1 = new Form1;

                                  instead:

                                  form1 = new Form1();

                                  Stupid mistake....

                                  Thank you so much Chris for help me!!

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    avmg
                                    wrote on last edited by
                                    #17

                                    Hi again,

                                    Finally i understood how to send data between forms and i could continue with my program. But i'm again in another trouble related with the same. I want to get a struct declared in another form. I did like this to get the struct:

                                    // Form1.h
                                    Public slots:
                                    mystruct return_struct(void);

                                    Private:
                                    struct mystruct{
                                    ...
                                    }

                                    mystruct new_mystruct;

                                    // Form1.cpp
                                    mystruct return_struct(void){
                                    return new_mystruct;
                                    }

                                    I've declared new_mystruct in Form1.h to have access to this data on every functions of this form. The problem is that it says in the Form1.h return_struct function:

                                    'mystruct' does not name a type.

                                    I think i should create new_mystruct on the Form1.cpp constructor but if i do this, i have not access to this on the functions...

                                    What do you recommend me?
                                    Thanks

                                    1 Reply Last reply
                                    0
                                    • Chris KawaC Offline
                                      Chris KawaC Offline
                                      Chris Kawa
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #18

                                      Please use code tags when posting code (last button on the right). It's easier to read.

                                      You haven't posted entire code but from what I see you declared your struct in the private section of Form1. As so it is not visible to outside classes and the compiler is right - there is no 'mystruct' outside of Form1.
                                      You need to declare it in a public section and refer to it as mystruct when inside Form1 members and as Form1::mystruct anywhere outside.

                                      Btw. It's a good convention to start type names with capital letter. That way people know right away what is what.

                                      As for where you create an instance of it. You don't say what the struct contains but if you return a local variable like you did you don't get chance to fill it with any meaningful data. So either fill it up with something before you return or make it a class member and fill it elsewhere.

                                      Example:
                                      @
                                      //Form1.h
                                      class Form1 {
                                      public:
                                      MyStruct {
                                      ...
                                      }
                                      MyStruct getStruct() const;

                                      private:
                                      MyStruct structInstance;
                                      };

                                      //Form1.cpp
                                      Form1::MyStruct getStruct() const { return structInstance; }

                                      //Somewhere else
                                      Form1* form1 = ... //form1 is some instance of Form1
                                      Form1::MyStruct data = form1->getStruct();
                                      @
                                      You can use structInstance in any of the Form1 members this way.

                                      Edit: Oh, and it's not an error, but it's unusual for a getter function to be a slot. Slots are meant as functions that modify your object in a reaction to a signal. They're not meant to return values as there is no object to give that value to in a connect statement. Getters like yours should not be slots.

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        avmg
                                        wrote on last edited by
                                        #19

                                        Hi Chris,

                                        I tried that but now the compiler says that 'structInstance' was not declared in this scope in the line:

                                        return structInstance;

                                        Ah! thanks for the advicements!

                                        1 Reply Last reply
                                        0
                                        • Chris KawaC Offline
                                          Chris KawaC Offline
                                          Chris Kawa
                                          Lifetime Qt Champion
                                          wrote on last edited by
                                          #20

                                          Sorry, getStruct is a class member function. I missed class specifier:
                                          @
                                          Form1::MyStruct Form1::getStruct() const { return structInstance; }
                                          @

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved