I have a project which provides the user with a GUI via Qt. I designed it with the Qt Designer (integrated in the Qt Creator) and now I would like to add another window in order to let the user change settings.
Afaik I have to use a QWidget to create another window and now I'm wondering how I may edit this QWidget in Qt Designer because I am only able to design mainwindow.
My code looks like this:
mainwindow.hpp
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
// various slot calls
// action triggered when clicking an entry in the QMenu of mainwindow
void on_action_dummy();
private:
Ui::MainWindow *ui;
QWidget dummy;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
// various implementations of the slot calls in mainwindow.hpp
void MainWindow::on_action_dummy()
{
dummy.show();
}
Maybe I need a own class for my new window? Is QWindow even the right class for this task?
You need to add a new UI file as well as header/class. There's an option for this in the "New File" dialog in Qt Creator (Qt Designer Form Class under the "Qt" sub-category on the sidebar). Then you open that up and instantiate the class like MainWindow in your program's entry point (int main()). Something like:
MySettingsDialog *dialog = new MySettingsDialog(this);
dialog->show();
You need to be careful how you instantiate it--mainly making sure the object will survive when it leaves the current scope (e.g. using a pointer if you are calling this in a method inside your class). Also, how you show/exec your dialog can vary. This is usually the case when you want a blocking (modal) dialog instead of a new "window".
Edit: To handle the memory management, you can set the WA_DeleteOnClose attribute:
dialog->setAttribute(Qt::WA_DeleteOnClose);
Related
I need to create a new window over top of my current program (I'm attempting a dialog in this case) when a button is clicked. I have this working, but I am having trouble editing the content of the Dialog. As far as I'm aware, no .ui file is created for this and it is only being created when I connect the button to the function.
I have tried using a QMessageBox but was unable to resize the window how I needed. And still ran into the issue of adding the other elements.
void MyNameSpace::openInfoDialog()
{
QDialog* Dialog = new QDialog(this);
Dialog->setWindowTitle("View Stuff");
Dialog->setMinimumSize(500,250);
Dialog->adjustSize();
DialogRunner* msgRunner = new DialogRunner(Dialog, this);
msgRunner->safeExec();
}
This is my connect
connect(_Widget.InfoBtn, SIGNAL(clicked(bool)), this, SLOT(openInfoDialog()));
This code does produce a dialog on click, but I need to be able to add things like labels etc to it. I also use QT Designer as my WYSIWYG.
What can I do to create the new window from a button click and have it filled with other text etc ?
I have this working, but I am having trouble editing the content of
the Dialog
You can add ui files in your project:
Using that option Qt Creator will make a class with cpp and h files and a ui file in which you can add other widgets as you're used to.
use the import directives to use your class where you need it like you did in the code above and you will have your ui file available.
Then connect the clicked signal of your button with the slot of your dialog class. You can do that in the constructor of the class that holds the button.
You can read this approach more in detail in the book C++ GUI Programming
with Qt 4
on chapter 2 : Creating Dialogs.
It is available for free on the web. It uses Qt4, but in Qt5 it works the same way around.
EDIT: Here is a minimal example that shows you where you can use the needed parts: a mainwindow with a button on it (in the ui file). a Dialog class which also has a ui file (with several widgets on it). When clicking the button on the mainwindow, the dialog form is shown. Thjs is what I asked you for before. It makes it easier to communicate / test.
pro file
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test
TEMPLATE = app
SOURCES += \
dialog1.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
dialog1.h \
mainwindow.h
FORMS += \
dialog1.ui \
mainwindow.ui
**main.cpp**
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
**mainwindow.cpp**
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog1.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
Dialog1* dialog = new Dialog1(this);
connect( ui->pushButton_1, SIGNAL(clicked()), dialog, SLOT(show()));
}
MainWindow::~MainWindow()
{
delete ui;
}
dialog1.h
namespace Ui {
class Dialog1;
}
class Dialog1 : public QDialog
{
Q_OBJECT
public:
explicit Dialog1(QWidget *parent = nullptr);
~Dialog1();
private:
Ui::Dialog1 *ui;
};
#endif // DIALOG1_H
dialog1.cpp
#include "dialog1.h"
#include "ui_dialog1.h"
Dialog1::Dialog1(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog1)
{
ui->setupUi(this);
}
Dialog1::~Dialog1()
{
delete ui;
}
I'm really stuck on one problem that I want to solve. the problem is that I have a Class for QMainWindow which holds the Ui variable for that form. Now I want to be able to edit that Form using the Ui variable in that class on a QDialog cpp file. I probably sound really stupid and I really have no idea how I should explain this, but I have code which maybe can help.
MainWindow.h:
#include "ui_mainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
Ui::MainWindow *ui;
}
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"
Dialog *dialog;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
dialog->show();
}
QDialog.cpp:
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
Ui::MainWindow *mainui;
void Dialog::on_pushbutton_clicked(){
mainui->label->setText("test");
}
So as you can see from the above code, it shows that I have a pointer to the Ui variable however its uninitialised, therefore it would lead to a SIGSEGV error, so how to do Initialize this pointer? any help here is highly appreciated, and even though this is probably really simple I just don't know what to do. (I have looked at other questions but I couldn't quite grasp what to do, so please explain what I am to do before linking me to a similar question. Also, I have left out the Dialog.h file as I didn't think it was needed, please tell me if I need to show it, thanks!).
Generally in C++ you should practice what is called encapsulation - keep data inside a class hidden from others that don't need to know about it. It's not good to have multiple pointers to the UI object as now all those other objects have to know how the main window UI is implemented.
In this case, what I would recommend is to use Qt's signals and slots mechanism to allow the dialog to tell the main window what you need it to do. That has the advantage that if you add more dialogs, or change how things are implemented in the main window, you don't need to alter the signal slot mechanism, and the details are hidden cleanly.
So - for your dialog, add a signal like this in the header file
class Dialog : QDialog
{
Q_OBJECT
signals:
void setTextSignal(QString text);
}
and in your main window header, add a slot.
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void setTextSlot(const QString &text);
}
now in your method where the button is pressed,
void Dialog::on_pushbutton_clicked()
{
emit setTextSignal("test");
}
and in your main window
void MainWindow::setTextSlot(const QString &text)
{
mainUi->label->setText(text);
}
The final part is to connect the signal and slot together, which you would do in your main window function where you create the dialog:
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
connect(dialog, SIGNAL(setTextSignal(QString)), this, SLOT(setTextSlot(QString)));
dialog->show();
}
You can see there are many advantages to this; the Dialog no longer needs a pointer to the main window UI, and it makes your code much more flexible (you can have other objects connected to the signals and slots as well).
Short answere - your can't! If you want to create a new instance of the ui, you would have to do:
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(this);
However, the this-pointer for a UI created for a QMainWindow based class must inherit QMainWindow - thus, you can't.
In general, it is possible if you create your Ui based on a QWidget instead of a QMainWindow, since both inherit QWidget.
Alternativly, you could try the following:
QMainWindow *subWindow = new QMainWindow(this);
subWindow->setWindowFlags(Qt::Widget);
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(subWindow );
//... add the mainwindow as a widget to some layout
But I would guess the result will look weird and may not even work in the first place.
I am new to Qt. I took an example from here http://doc.qt.io/qt-5/qtmultimediawidgets-player-example.html.
Now I want to integrate the player in the main window. I created a Qt Widgets application project, I thought, that I would just have to edit the main window code:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Player* player;
MainWindow::setCentralWidget(player);
}
But it doesn't work and I get the following error:
Starting /home/***/Documents/build-player-Desktop-Debug/player...
The program has unexpectedly finished.
/home/***/Documents/build-player-Desktop-Debug/player crashed
How can I integrate a custom widget which is written in code, without ui in a main window? Thank you in advance.
In your own MainWindow class you can add a widget to the layout of that MainWindow:
MyMainWindow::MyMainWindow(QWidget *parent) :
...
{
this->ui->setupUi(this);
QLabel *myLabel = new QLabel();
this->layout()->addWidget(myLabel);
}
Well, player can't be placed on the window if it is not initialized.
Write something like that :
Player *player = new Player();
I usually add a QWidget (or whatever widget type I'm extending) to my .ui-file in the designer and then promote it to the actual derived type. See the Qt docs for more info on promoting widgets. This means that I can set the base widget's properties and design the window as usual but still get an instance of my special class when the UI is instantiated.
MainWindow:MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
SomeStupidWidget *ssw = new SomeStupidWidget(this); /* important! don't forget about passing "this" as argument, otherwise this could cause a memory leak(Qt handles object's lifetime by means of it's "owner" mechanism)*/
layout()->addWidget(ssw);
}
I'm working on an app in C++/Qt I have used the design tool to design a Qdialog box.
The Dialog box is defined as below.
c++ file
#include "dialogwarning.h"
#include "ui_dialogwarning.h"
DialogWarning::DialogWarning(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogWarning)
{
ui->setupUi(this);
}
DialogWarning::~DialogWarning()
{
delete ui;
}
header file
#include <QDialog>
namespace Ui {
class DialogWarning;
}
class DialogWarning : public QDialog
{
Q_OBJECT
public:
explicit DialogWarning(QWidget *parent = 0);
~DialogWarning();
private:
Ui::DialogWarning *ui;
};
The source use it as below:
WarningDialog = new DialogWarning();
QLabel *label = new QLabel("File/Folder name already exist", WarningDialog);
label->setGeometry(WarningDialog->rect().center().x() - label->rect().width()/2,
WarningDialog->rect().center().y() - label->rect().height()*2,
WarningDialog->rect().width(),
WarningDialog->rect().height());
WarningDialog->exec();
I'm using exec instead of show because the exec primitive allow me to be stucked inside the dialog until a press on the "Ok" button.
What is strange is that the OK button is not working. I do not need any specific behavior just wait the OK press to continue to run the code.
Thanks
i'm not quite sure assuming u have connected everything. could be that the application is frozen.
why not put the calculation in a different thread and connect the same signal that shows the dialog to thread pause.
the signal of the ok pushbutten should be connected to close the dialog and thread resume...
So I'm making a web browser as my first Qt project (surprise!) and I'm wondering why calling setWindowState(Qt::WindowMaximized) is not changing window geometry. I have this code:
From mainwindow.h:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
};
From mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// this->geometry() is the same here...
setWindowState(Qt::WindowMaximized);
ui->webView->setGeometry(0, 60, geometry().width(), geometry().height()-60);
// ...as it is here.
}
As you may be able to tell, I'm trying to start the application with the window maximized and the QWebView also maximized. Basically, whenever the main window is resized, I also want to call ui->webView->setGeometry with the update height and width. But MainWindow::geometry doesn't seem to be updating. What am I doing wrong?
I would have to double check, but your geometry might not get updated properly until your main window gets a show event.
However, I would suggest you put your QWebView inside of a layout instead of trying to size it manually every time your main window changes size.