I'm learning qt framework for c++ and I'm not able to understand what this statement does:
Window::Window (QWidget *parent) : QWidget(parent)
{
....
}
// (QWidget *parent) : QWidget(parent) <---
This statement means calling base class constructor. In your context it is widget class. It is base class for window. Actually parent widget will be passed to this constructor
Related
Hi I am new to the Qt and C++. I have one requirement where I have to access signal of Base class using derived class object. Whether is it possible and if yes then how? I tried to implement it using one simple application, but it is not working.
//Base Class
//Which is emitting signal temp() in it's constructor
class IPCBase : public QWidget
{
Q_OBJECT
public:
explicit IPCBase(QWidget *parent = 0);
~IPCBase();
signals:
void temp();
private:
Ui::IPCBase *ui;
};
//cpp
IPCBase::IPCBase(QWidget *parent) :
QWidget(parent),
ui(new Ui::IPCBase)
{
ui->setupUi(this);
qDebug()<<"coming to base cpp";
emit temp();
}
I have created one derived class named IPCReceiver and using the object of IPCReceiver(derived class) I am trying to use the connect statement in another class(Form) and call the SLOT.It is not giving compilation error but the SLOT is not getting called.
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
IPCReceiver *receiver = new IPCReceiver;
connect(receiver, SIGNAL(temp()), this, SLOT(debug()));
}
Thanks in advance.
Your signal temp() emits in constructor of a class. That's why your connection is unusable. In your logic: at first emits signal in constructor, then you create connection. You must emit signal after creation of the connection.
You generally shouldn't be emitting any signals from constructors of any class deriving from QObject as it makes the class much harder to use. You need to emit the signal from the event loop, after the constructor has finished. There are at least two idioms that express that:
Using a Connection to QObject::destroyed
IPCBase::IPCBase(QWidget *parent) :
QWidget(parent),
ui(new Ui::IPCBase)
{
ui->setupUi(this);
QObject src;
connect(&src, &QObject::destroyed, this, &IPCBase::temp, Qt::QueuedConnection);
}
The src object is used only as a source of a generic signal.
Using QMetaObject::invokeMethod
IPCBase::IPCBase(QWidget *parent) :
QWidget(parent),
ui(new Ui::IPCBase)
{
ui->setupUi(this);
QMetaObject::invokeMethod(this, "temp", Qt::QueuedConnection);
}
As an aside, you don't need to allocate Ui dynamically, you can make it a member variable instead; then the compiler-generated default destructor is sufficient.
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 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);
I have a MainWindow class and Another class. Another class has method createView that create new QGraphicsView. This method I call from MainWindow and I also want to layout this view on my form. It looks like:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)) {
...
AnotherClass object(this);
object.createView();
...
}
...
void AnotherClass::createView() {
QGraphicsView *gv= new QGraphicsView(mainWindow); // mainWindow - pointer to MainWindow object
gv->show();
}
But it doesn't work so good... actually it does't work at all. And yes, I save pointer on MainWindow object in my Another class as mainWindow, that I take from Another class constructor.
If use
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)) {
...
QGraphicsView *gv= new QGraphicsView(this);
gv->show();
...
}
It will work fine, but this solution doesn't satisfied me.
Problem was in creating variable on stack.