How can i change QMainWindow to QDialog - qt

I am new in Qt. I have made a project in Qt.
Now I need to change the QMainWindow into QDialog.
How can I do this without deleting all my project?
If a change the base mainwindow into QDialog, it is necessary to make a new window for being main?

Depending on if you have a .ui file or not.
If so, you could edit the .ui and change the line
<widget class="QMainWindow" name="MainWindow">
To
<widget class="QDialog" name="MainWindow">
Also, think about if classes like QMenuBar, QToolBar and QStatusBar are necessary in your project. Qt Designer puts them in the .ui file by default and because they are used by QMainWindow.
After that, you should change the base class for your MainWindow. You should have something like this:
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
So you need change QMainWindow by QDialog.
#include <QDialog>
namespace Ui {
class MainWindow;
}
class MainWindow : public QDialog
{
If you don't have a .ui file, the first step is no necessary (obviously :))
Of course, you will need to check if you are using any QMainWindow method which is not implemented by QDialog in order to avoid compilation error and lack of functionality.

You can freely use any type of QWidget as main. The main window is whatever you decide it to be, typically the one you create and show in your main() function. So you can freely change your base class to QDialog and it will probably just work.
However, if you used Qt Designer (either directly or through Qt Creator) to create the .ui file containing all the widgets rather than coding the interface by hand, and you don't want to go through that hassle again, it can be a bit tricky.
One way is to create a new QDialog and then simply copy-paste the designed window contents to the new window. This is the easiest approach, but you may lose some properties that you set in the designer because not everything is copied.
A more tricky, but also more powerful way is to edit the created .ui file by hand. It's just a simple XML file, after all. Look for the class attribute and change class="QMainWindow" to class="QDialog". You should also look for properties and check whether these properties are defined in QDialog by looking at the docs. If they are QMainWindow-specific, then just delete them carefully.
Of course, you should back up your project (or commit it to the source control system) prior to playing around with XML because you may screw up something so that the designed will simply obliterate parts of your files it can't parse.

Related

Passing variable to promoted QWidget

I have two classes:
-MainWindow
-MyWidget which is promoted in MainWindow.ui using QT Creator's design tab.
Both of the class .ui's are designed in design tab.
I try to pass variables to MyWidget from MainWindow without any success. Compiler doesn't give any errors, but variables are not passing. Is there any way to do this? MyWidget works well as long as I don't import MainWindow to it or import MyWidget to MainWindow. After import I can't control MyWidget's content by code. Any suggestions?
EDIT: Made a small example and added code to pastebin, so this post won't get bloated.
MainWindow.h
MainWindow.cpp
another links are in comments
Your class MainWindow does not need to a MyWidget attribute. MyWidget object is actually created by Ui::MainWindow object.
So, to access your MyWidget object (the one displayed on screen as part of MainWindow widget), use ui->widget (as widget is the name you gave the object in Qt Designer <widget class="MyWidget" name="widget" native="true"/>), instead of mw.
Modifying mw makes no sense because this instance of MyWidget is not used for GUI display.
You then have to change:
connect(this, SIGNAL(text(QString, QString)),&mw, SLOT(addText(QString,QString)));
into:
connect(this, SIGNAL(text(QString, QString)),ui->widget, SLOT(addText(QString,QString)));
Note: If MyWidget class needs parameters to be passed upon construction, you can remove the widgetinstanciation from your .ui file and create it locally using mw attribute of the MainWindow class as you did. But, then, to have this instance be shown on screen, you must add it to the layout of your MainWindow, like this (for example): ui->horizontalLayout->addWidget( &mw );

Is is possible to edit an individual Widget in the QtDesginer?

I got a external library, which includes a derived class from QGLWidget, very similar to that one here. In that library I have a class:
class PictureGLWidget : public QGLWidget { //.. }
This extends Qt's native QGLWidget and personalizes it. But it was not written by me, I just got it, via a *.dll. So then, I bind that Widget manually in my code to a layout like:
QGridLayout* layout = new QGridLayout;
layout->addWidget(myPictureGLWidget, 0, 1);
ui->verticalLayout_5->addLayout(layout);
since I designed my MainWindowWidget with the integrated QtDesigner, which is by the way very comfortable, I would like to handle my myPictureGLWidget also in the QtDesigner, since I am currently redesigning the MainWindow.
Is there a way doing that? Thnx in advance!
Qt Designer supports any foreign widget class without needing to provide plugins for that. You only have to accept that the widget's properties and appearance won't be available within Designer.
Insert a dummy QWidget into the layout.
Right click on the widget, select "Promote to...".
Add PictureGLWidget as a new class promoted from QWidget. Specify appropriate header files etc.
Promote your widget to PictureGLWidget.
When this is done, the code generated by uic will instantiate a PictureGLWidget where you need it, instead of a dummy QWidget.
If you want to use the PictureGLWidget in the designer instead of a dummy widget, you can write a designer plugin that wraps the widget and exposes it in the widget pallette, provides property support, etc.
I might have misunderstood your question but don't you just add a QGLWidget to your design in Designer. Right click the widget and select Promote to... ?

Opening a Widget created in Designer, from a Main Window

I’ve created 2 .ui files, one is a main window, the other a widget. Designer generates the 2 .header files each with QT_BEGIN_NAMESPACE around the class declaration.
The problem is, what works in opening my main window, does not work in opening the second widget window.
To display my main window, I created a class that inherits from my .ui file:
class myWindow: public QMainWindow, private Ui::uiClassWindow
setupUi(this);
That opens fine, so then to open the second widget window, I declare a generic widget object and then save it with a pointer to my Widget Ui header file:
QWidget newWidget;
setupUi(newWidget)
But setupUi resolves to my Main Window header file… How do I tell it to use the Widget’s setupUi?
Is there a better way to go about this?
Up to my knowledge, for setupUi function is defined in Ui namespace. You need to give scope (Ui) for other widget too.
The setupUi() method is created by uic from your UI file, and it's different for each compiled UI.
In your myWindow, you inherit from Ui::uiClassWindow and can use its setupUi() method without qualification. You'll need an instance of a different UI class for your newWidget:
auto widget_ui = new Ui::myWidget;
QWidget newWidget;
widget_ui->setupUi(newWidget)
You could delete the widget_ui immediately if you wanted - but usually, you'll need to keep it in order to access the children it has now created in newWidget.

How to use subclassed class in qt

I've subclassed qt's pushbutton and now I would like to use it in my project (instead of qpushbutton) - the problem I have is that even if I add #include "mybutton.h" in ui_class it gets overwritten and I don't know what else can I do it.
Is there a way to have this button within designer on a panel just like the ordinary qpushbutton is?
Never modify the ui_Class file yourself. Any change you make there will be overwritten when the .ui gets compiled. Instead use the promote to functionality within QtDesigner.
If some forms must be designed, but certain custom widgets are
unavailble to the designer, we can substitute similar widgets to
represent the missing widgets. For example, we might represent
instances of a custom push button class, MyPushButton, with instances
of QPushButton and promote these to MyPushButton so that uic generates
suitable code for this missing class.

how can I have more than a UI for a QMainWindow?

I would like to have a QMainWindow that can change it's look at runtime, i.e when a user clicks a button. Besides keeping references to different UI classes generated by the QtDesigner, is there another way of doing that? Maybe by storing each UI in a layout ? What do you think ?
How much of the main window do you want to change? You could use a QStackWidget any place you want to change things, and change the shown page of the widget when the button is pressed. This will be quick to change, but for large or complicated UIs it may be slightly slower at startup, since it will be creating the widgets for both UIs at the same time. (There are fairly easy ways to change this, also, but they do add complications to something that could be straightforward for most people.) Also, if both layouts should have the same data, just in different places, you have the additional overhead of keeping both sets of UIs up to date while the program is running.
I think I got it now.
You have a QMainWindow and when a certain event is triggered you want to change the appearance of that particular window, like remove some buttons, add a treeview widget or what not.
Well the straight forward approach would be to do it manually, remove some widgets and add new ones using regular C++ code. This can be abit hard if you're used to Qt Designer.
The other way I can think of is using Qt Designer to generate the code for the other appearances and copy it to a special function. The code generated by Qt Designer is usually in a header file called "ui_classname.h" and isn't hard to understand. You will however need to remove some of it as not all would be necessary.
Also, instead of copying the generated code from Qt Designer you could just call it. Usually your widget has a pointer to the generated class and in your widget's constructor you see something like this:
MyWindow::MyWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::MyWindow)
{
m_ui->setupUi(this);
}
and in the corresponding header file:
class MyWindow : public QMainWindow {
...
private:
Ui::MyWindow *m_ui;
};
You could add the additional generated classes for the other appearances and use them when your event triggers.
It might look like this:
class MyWindow : public QMainWindow {
...
private:
void changeAppearance(int id);
Ui::MyWindow *m_ui;
Ui::MyWindowFirstAppearance *m_uiFirst;
Ui::MyWindowSecondAppearance *m_uiSecond;
...
};
void MyWindow::changeAppearance(int id)
{
// some code to remove the current appearance, basically the opposite of what setupUi is doing
if (id == 0)
m_ui->setupUi(this);
else...
m_uiFirst->setupUi(this);
...
}
This has the benefit of using the generated classes directly, so every change you do in Qt Designer doesn't require a change to your main window. The problem is I'm not sure if it's legal to call setupUi more than once and in a place other than your widget's constructor, so you'll have to check that (by looking at what's happening in the setupUi function).
You can dynamically load UI layouts at runtime. Check Qt documentation for QUiLoader class.
This also enables you to upgrade UI layouts without modifying a single line of code.
What I do is to design two UIs under two different QFrames, put the two QFrames in a layout together in the QMainWindow, and then hide() and show() the correct QFrame that you want...
You can use a QTabWidget and hide its buttons. You can then design each GUI in a separate window of the tabWidget. It has the advantage over hiding frames that you won't clutter up your Qt Creator window.
If I'm getting this right, I think you might want to take a loot at style sheets. It allows you to have "skins" for your widgets, much like CSS.
If I didn't get this right, and what you're trying to do is generate .ui files on the fly and create widgets with those using QUiLoader, then you're probably going at this the wrong way since I can't think of a good reason a regular application would need that.

Resources