How to change my GUI Base Class (QWidget => QMainWindow) ?
-
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 .
-
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();
}
@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
@ -
Just change QWidget from line 4 of the .ui file into a QMainWindow.
-
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 guiTARGET = bid3
TEMPLATE = appSOURCES += main.cpp
mainwindow.cppHEADERS +=
mainwindow.hFORMS +=
mainwindow.ui
@mainwindow.h :
@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
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();
}
@
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 UiQT_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 directoryD:/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 directory
D:/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'
@ -
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.
-
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.