How to change my GUI Base Class (QWidget => QMainWindow) ?



  • Hi All,

    I would like to change my GUI base class , for example from QWidget to QMainWindow.
    If this feature does not exist in Qt Creator what is the best workaround ? I
    I would like to avoid doing it manually as changing my xxx.ui in XML may not be that easy.

    Thanks in advance

    Gilles


  • Moderators

    Just change it in c++ header...
    @
    class MyWidget : public QWidget
    // should now become
    class MyWidget : public QMainWindow
    @

    And then update the constructors, too. Last step would be to do a full rebuild. Details depend on what your code actually looks like, though.



  • That's what i did. it compiled. But my QWidget GUI designed with Qt Designer is lost. When I open xxx.ui (generated by Qt Designer in XML), it still contain tens of QWidget and in QT Creator/Designer, my parent object is still QWidget.

    PS: As far as my other post about clone project is concerned, it worked. I just had to rename the .pro file too (and the TARGET inside). Thanks .


  • Moderators

    You're welcome.

    OK, so your setup is probably not a standard one. It would be really helpful if we could see some code here (your new QMainWindow class declaration, at least a part of the .ui file).



  • ok. Here you are. This is a simple calculator (i am new in Qt)

    calculator.h
    @
    #ifndef CALC1_H
    #define CALC1_H

    #include <QMainWindow>

    namespace Ui {
    class calc1;
    }

    class StateCal;

    class Calculator : public QMainWindow {
    Q_OBJECT
    public:
    explicit Calculator(QMainWindow *parent = 0);
    ~Calculator();
    void setCurrentState(StateCal *);
    void displayScreen();

    private slots:
    void on_pushButCE_clicked();
    void on_pushButC_clicked();
    void on_pushButDot_clicked();
    void on_pushBut0_clicked();
    void on_pushBut1_clicked();
    void on_pushBut2_clicked();
    void on_pushBut3_clicked();
    void on_pushBut5_clicked();
    void on_pushBut4_clicked();
    void on_pushBut6_clicked();
    void on_pushBut7_clicked();
    void on_pushBut8_clicked();
    void on_pushBut9_clicked();
    void on_pushButTimes_clicked();
    void on_pushButDivide_clicked();
    void on_pushButPlus_clicked();
    void on_pushButMinus_clicked();
    void on_pushButEqual_clicked();

    private:
    Ui::calc1 *ui;
    StateCal *currentState;
    };

    #endif // CALC1_H

    @

    but it does not change anything in calculator.ui which still contains QWidget.

    @
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>calc1</class>
    <widget class="QWidget" name="calc1">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>338</width>
    <height>206</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>calc1</string>
    </property>
    <layout class="QVBoxLayout" name="verticalLayout">
    <item>
    <widget class="QLCDNumber" name="lcdResult">
    <property name="midLineWidth">
    <number>1</number>
    </property>
    <property name="smallDecimalPoint">
    <bool>false</bool>
    </property>
    <property name="numDigits">
    <number>8</number>
    </property>
    <property name="mode">
    <enum>QLCDNumber::Dec</enum>
    </property>
    <property name="value" stdset="0">
    <double>0.000000000000000</double>
    </property>
    </widget>
    </item>
    <item>
    <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
    <widget class="QPushButton" name="pushButCE">
    <property name="text">
    <string>CE</string>
    </property>
    </widget>
    </item>

    .....

    @

    This GUI contains only pushButton , label and LCD.

    The main :

    @
    #include <QtGui/QApplication>
    #include "calculator.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Calculator w1;
    w1.show();

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

    }
    @

    and calcu2.pro :
    @
    QT += core gui
    TARGET = calcu2
    TEMPLATE = app
    SOURCES += main.cpp calculator.cpp statecal.cpp
    HEADERS += calculator.h statecal.h
    FORMS += calculator.ui
    @


  • Moderators

    Just change QWidget from line 4 of the .ui file into a QMainWindow.



  • Sierdzio, just hold on a moment.
    I just realized that when i renamed calc1->calculator, some calc1 remain like in
    @
    namespace Ui {
    class calc1;
    }
    @
    i will try your method on a new project with just a pushbutton.


  • Moderators

    Sure, take your time.



  • So, forget about my project. I just would like to validate your method now. So I created a QWidget with just one pushbutton. Then i tried to switch to a QMainWindow by renaming every i could but i can't even compile now. Below are all my files and the compile errors.
    As you can see, the errors comes from the UIC generated file ui_mainwindow.h which i can't control because Qt Designer does not let me change QWidget to QMainWindow.

    bid3.pro :
    @
    QT += core gui

    TARGET = bid3
    TEMPLATE = app

    SOURCES += main.cpp
    mainwindow.cpp

    HEADERS +=
    mainwindow.h

    FORMS +=
    mainwindow.ui
    @

    mainwindow.h :
    @
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

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

    private:
    Ui::MainWindow *ui;
    };

    #endif // MAINWINDOW_H

    @

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

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

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

    main.cpp :
    @
    #include <QtGui/QApplication>
    #include "mainwindow.h"

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

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

    }

    @

    mainwindow.ui :
    @
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>Widget</class>
    <widget class="QWidget" name="Widget">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>Widget</string>
    </property>
    <widget class="QPushButton" name="pushButton">
    <property name="geometry">
    <rect>
    <x>160</x>
    <y>150</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>PushButton</string>
    </property>
    </widget>
    </widget>
    <layoutdefault spacing="6" margin="11"/>
    <resources/>
    <connections/>
    </ui>

    @

    The generated ui_mainwindow.h :
    @
    /********************************************************************************
    ** Form generated from reading UI file 'mainwindow.ui'
    **
    ** Created: Fri Oct 19 14:27:11 2012
    ** by: Qt User Interface Compiler version 4.8.1
    **
    ** WARNING! All changes made in this file will be lost when recompiling UI file!
    ********************************************************************************/

    #ifndef UI_MAINWINDOW_H
    #define UI_MAINWINDOW_H

    #include <QtCore/QVariant>
    #include <QtGui/QAction>
    #include <QtGui/QApplication>
    #include <QtGui/QButtonGroup>
    #include <QtGui/QHeaderView>
    #include <QtGui/QPushButton>
    #include <QtGui/QWidget>

    QT_BEGIN_NAMESPACE

    class Ui_Widget
    {
    public:
    QPushButton *pushButton;

    void setupUi(QWidget *Widget)
    {
        if (Widget->objectName().isEmpty())
            Widget->setObjectName(QString::fromUtf8("Widget"));
        Widget->resize(400, 300);
        pushButton = new QPushButton(Widget);
        pushButton->setObjectName(QString::fromUtf8("pushButton"));
        pushButton->setGeometry(QRect(160, 150, 75, 23));
    
        retranslateUi(Widget);
    
        QMetaObject::connectSlotsByName(Widget);
    } // setupUi
    
    void retranslateUi(QWidget *Widget)
    {
        Widget->setWindowTitle(QApplication::translate("Widget", "Widget", 0, QApplication::UnicodeUTF8));
        pushButton->setText(QApplication::translate("Widget", "PushButton", 0, QApplication::UnicodeUTF8));
    } // retranslateUi
    

    };

    namespace Ui {
    class Widget: public Ui_Widget {};
    } // namespace Ui

    QT_END_NAMESPACE

    #endif // UI_MAINWINDOW_H
    @

    compilation errors :
    @
    14:30:26: Running build steps for project bid3...
    14:30:26: Configuration unchanged, skipping qmake step.
    14:30:26: Starting: "C:\dev\Qt\mingw\bin\mingw32-make.exe"
    C:/dev/Qt/mingw/bin/mingw32-make.exe -f Makefile.Debug
    mingw32-make.exe[1]: Entering directory D:/Source/Cpp/qt5/bid3-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Debug' g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"c:\dev\Qt\Desktop\Qt\4.8.1\mingw\include\QtCore" -I"c:\dev\Qt\Desktop\Qt\4.8.1\mingw\include\QtGui" -I"c:\dev\Qt\Desktop\Qt\4.8.1\mingw\include" -I"c:\dev\Qt\Desktop\Qt\4.8.1\mingw\include\ActiveQt" -I"debug" -I"." -I"..\bid3" -I"." -I"c:\dev\Qt\Desktop\Qt\4.8.1\mingw\mkspecs\win32-g++" -o debug\mainwindow.o ..\bid3\mainwindow.cpp ..\bid3\mainwindow.cpp: In constructor 'MainWindow::MainWindow(QMainWindow*)': ..\bid3\mainwindow.cpp:6: error: invalid use of incomplete type 'struct Ui::MainWindow' ..\bid3\/mainwindow.h:7: error: forward declaration of 'struct Ui::MainWindow' ..\bid3\mainwindow.cpp:8: error: invalid use of incomplete type 'struct Ui::MainWindow' ..\bid3\/mainwindow.h:7: error: forward declaration of 'struct Ui::MainWindow' ..\bid3\mainwindow.cpp: In destructor 'virtual MainWindow::~MainWindow()': ..\bid3\mainwindow.cpp:13: warning: possible problem detected in invocation of delete operator: ..\bid3\mainwindow.cpp:13: warning: invalid use of incomplete type 'struct Ui::MainWindow' ..\bid3\/mainwindow.h:7: warning: forward declaration of 'struct Ui::MainWindow' ..\bid3\mainwindow.cpp:13: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined. mingw32-make.exe[1]: Leaving directoryD:/Source/Cpp/qt5/bid3-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Debug'
    mingw32-make.exe[1]: *** [debug/mainwindow.o] Error 1
    mingw32-make.exe: *** [debug] Error 2
    14:30:28: The process "C:\dev\Qt\mingw\bin\mingw32-make.exe" exited with code 2.
    Error while building project bid3 (target: Desktop)
    When executing build step 'Make'
    @


  • Moderators

    Something is amiss, but sadly my Friday-afternoon brain is not helping :) I will have to investigate myself when I'm more fresh.



  • Sure. If you want to reproduce it on your computer just :

    • Create a new Qt Gui Application with base class QWidget
    • add a push button with Qt Designer
    • try to switch from QWidget to QMainWindow without deleting the push button.
      Have a nice week-end and let me know if you see a solution .
      Thanks again,
      Gilles


  • Easiest seems to be a copy-paste operation between two Creator forms. Just create a new form with the base class you want, switch to the class you want to change, select and copy everything, and past into the empty form.

    Yes, it would be nice to have the option to change the base class for a .ui form, but I never found one.


  • Moderators

    OK, my brain power seems to be restored. I have tried doing this myself as you suggested. I have managed to successfully run the default app after changing it from QWidget to QMainWindow. It works well after steps outlined above (change class inheritance to QMainWindow, change QWidget into QMainWindow in the .ui file), after a full rebuild (and restart of the file in the Designer so that it can pick up those changes). But this results in a bare QMW, different from default you get when creating a new QMW-based project in Qt Creator (status bar and tool bar are missing).

    In general, I think Andre's suggestion is better here. I have tried this in some of my projects before and it is a pretty good solution. Sometimes it fails, as .ui file parser is quite sensitive, but it produces better results than simple renaming.



  • Ok, Thanks guys. Andre's method worked (with some more work to copy past the code from my QWidget to the new QMainWindow)


Log in to reply
 

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