[Solved] How to open a MainWindow child from a main MainWindow?



  • Hi everybody!!

    I need to develop an app composed of a main window, and several subwindows. The idea is to have a "Server window" with several independent subwindows using common functions, variables, etc from that "Server window".

    So I've made a simple example appl composed by two QMainWindows objects:

    • MainWindow, is the main window. It is composed by:

      • EditText2Copy, where the user enters a text
      • ButtonCopy2EditText (see below)
      • EditText, when ButtonCopy2EditText is pressed, the text from EditText2Copy is copied here
      • ButtonNewWindow, when pressed it should launch/show the subWindow object without closing this
        [There are other small objects, but I don't describe there in order to avoid losing focus]
    • SubWindow, is the child window. Its components are:

      • EditText2Copy, where the user enters a text
      • ButtonCopy2EditText, when pressed it should change MainWindow::EditText

    I clearly understand that child window must be connected to the parent one, and (probably) viceversa too. And I must keep subwindow in a variable from MainWindow, in order to launch the SubWindow, show it, and delete it when SubWindow closes.

    But when I try to create the subwindow object, I got a bunch of problems. I've spent two days trying to figure how to do so (no problem with simple dialogs or widgets, but MainWindows is a headache now), without success.

    I tried to post my code, but max allowed is 6000 chars long... will try to resume:

    mainwindow.h:
    @
    #include <subwindow.h>

    namespace Ui
    {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

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

    public slots:
    void setEditText(QString _txt);

    private slots:
    void on_ButtonCopy2EditText_clicked();
    void on_ButtonNewWindow_clicked();

    private:
    Ui::MainWindow *ui;
    Ui::SubWindow *subWindow;
    };
    @

    subwindow.h
    @
    namespace Ui
    {
    class SubWindow;
    }

    class SubWindow : public QMainWindow
    {
    Q_OBJECT

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

    private slots:
    void on_ButtonCopy2EditText_clicked();

    private:
    Ui::SubWindow *ui;
    };
    @

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

    return a.exec&#40;&#41;;
    

    }
    @

    mainwindow.cpp:
    @
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "subwindow.h"
    #include "ui_subwindow.h"

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

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::on_ButtonCopy2EditText_clicked()
    {
    this->setEditText(ui->EditText2Copy->text());
    }

    void MainWindow::setEditText(QString _txt)
    {
    ui->EditText->setText(_txt);
    }

    void MainWindow::on_ButtonNewWindow_clicked()
    {
    subWindow = Ui::SubWindow( this ); //HERE IS THE !"·$!"·$"E·YTTU&"·$%!!!
    }
    @

    subwindow.cpp:
    @
    SubWindow::SubWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::SubWindow)
    {
    ui->setupUi(this);

    connect(ui->ButtonClose,SIGNAL(clicked()),this,SLOT(close()));
    
    //connect(this,SLOT(close()),caller,SLOT(subWindowClosed()));
    

    }

    SubWindow::~SubWindow()
    {
    delete ui;
    }

    void SubWindow::on_ButtonCopy2EditText_clicked()
    {
    //caller->setEditText(ui->EditText2Copy->text());
    }
    @

    Great thanks in advance.


  • Moderators

    QMainWindow is main window. Why do you try to have two of them? Are you sure a dialog or a plain widget wouldn't be better?

    [quote author="Bullub" date="1362505248"]But when I try to create the subwindow object, I got a bunch of problems.[/quote]
    What problems exactly are you having?

    From what I see you have a Ui::SubWindow* subWindow member in your main main window(pun intended) and then instantiate Ui::SubWindow(this). Ui::SubWindow is the automatically generated ui class that shouldn't be used outside of your "full class". What you probably meant is SubWindow* (without the namespace), which is your implementation. Also, you're missing a 'new' keyword there.



  • You can use MDI or Tabbed window :)



  • Krzysztof Kawa:

    If possible, I'd prefer to open several QMainWindow objects, because they are plenty of functionality: menus with actions, central widget, and so on. But, as you say, perhaps it would be better to use a widget and add him the QMainWindow usual functionality. I'm just working my way in order to see what fits best to my needs.

    Well, let's write this funcion in MainWindow in order to get a new SubWindow:
    @
    void MainWindow::on_ButtonNewWindow_clicked()
    {
    subWindow = new Ui::SubWindow(this);
    subWindow-> ?? show ??
    }
    @

    Building this gives this output:
    ../MultiWindowApp/mainwindow.cpp: In member function 'void MainWindow::on_ButtonNewWindow_clicked()':
    ../MultiWindowApp/mainwindow.cpp:35:39: error: no matching function for call to 'Ui::SubWindow::SubWindow(MainWindow* const)'
    ../MultiWindowApp/mainwindow.cpp:35:39: note: candidates are:
    ./ui_subwindow.h:114:11: note: Ui::SubWindow::SubWindow()
    ./ui_subwindow.h:114:11: note: candidate expects 0 arguments, 1 provided
    ./ui_subwindow.h:114:11: note: Ui::SubWindow::SubWindow(const Ui::SubWindow&)
    ./ui_subwindow.h:114:11: note: no known conversion for argument 1 from 'MainWindow* const' to 'const Ui::SubWindow&'
    make: *** [mainwindow.o] Error 1

    And, let's suposse I can get my subWindow. How can I show it? It has no "show" method...

    mmallad:

    The final application will work with several images, and viewing all at same time with the ability of work independently in each one is a real thumb up for my purposes.


  • Moderators

    As I said - don't instantiate the Ui::<whatever> objects on your own, those are not for you to handle ;) It is the reason why you get these errors. The auto-generated class Ui::SubWindow is not a widget, it is generated to be a member of your own SubWindow implementation of a widget.

    In short - change this:
    @
    private:
    Ui::MainWindow *ui;
    Ui::SubWindow *subWindow;
    @
    to that:
    @
    private:
    Ui::MainWindow *ui;
    SubWindow *subWindow;
    @
    and then this:
    @
    void MainWindow::on_ButtonNewWindow_clicked()
    {
    subWindow = new Ui::SubWindow(this);
    subWindow-> ?? show ??
    }
    @
    to that:
    @
    void MainWindow::on_ButtonNewWindow_clicked()
    {
    subWindow = new SubWindow(this);

    //Ui::SubWindow isn't a widget so it doesn't have show()
    //SubWindow is a widget so it has show()
    subWindow->show();
    

    }
    @



  • Hly crp... you're right.

    I thought Ui::SubWindow was referencing a class SubWindow in the namespace Ui that I defined... I clearly misunderstood the propose of this.

    @
    namespace Ui
    {
    class SubWindow;
    }
    @

    I thought that Ui::SubWindow and SubWindow were exactly the same thing... urgh. This is due to proff. deformation from years of .NET, java, PHP, X++, etc.

    Thanks a lot, Krzysztof Kawa.

    I will continue dealing with the example application...



  • Oh man, I think I've understood it, after carefully reading (and metabolizing a certain qty of coffeine) this link: "Using a Designer UI File in Your Application":http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html

    So, in short terms: Ui::XXX does not point to my XXX class, it is instead like an alias to the class Ui_XXX auto-generated by compiler from the xxx.ui file.


  • Moderators

    Well, you got it close enough I guess, except the Ui::XXX is not an alias. It's just a regular class like any other. It's a little confusing at first because for some reason(not saying it's a bad one) Qt guys decided to name it exactly like your own class, except they put it in a namespace so the names wouldn't collide.

    To show this a little more clear(I hope) consider this code:

    @
    class UiImplementation {
    //defines widgets, layouts, positions, initialization and whatnot
    //this stuff is generated from the .ui file by the Qt uic compiler
    }

    namespace UiStuff {
    class UiWrapper: public UiImplementation {}
    }

    class MyAwesomeClass {
    // my stuff
    private:
    UiStuff::UiWrapper* myUi;
    }
    @

    Now just translate the names into what Qt does:

    @
    //ui_subwindow.h
    class Ui_SubWindow {
    }

    namespace Ui {
    class SubWindow: public Ui_SubWindow {}
    }

    //subwindow.h
    class SubWindow {
    private:
    Ui::SubWindow* ui;
    }
    @
    and hopefully this starts to make a lot of sense ;)



  • Thanks, you're right, it's not an alias; it was a sort-of-speaking.

    I've got a last question about this related to the SubWindow constructor; I've posted it in other thread because of its different nature:

    "How to cast my NewClass:Qwidget to QWidget in constructor?":http://qt-project.org/forums/viewthread/25572/

    Could you at least read it, please?

    Thanks by your assistance, effort and clearance, Krzysztof Kawa. I mark this thread as solved.


Log in to reply
 

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