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.
Related
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
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.
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
audioRecorder = new QAudioRecorder;
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/amr");
audioSettings.setQuality(QMultimedia::HighQuality);
audioRecorder->setEncodingSettings(audioSettings);
audioRecorder->setOutputLocation(QUrl::fromLocalFile("test.amr"));
audioRecorder->record();
}
void MainWindow::on_pushButton_2_clicked()
{
//How to use audioRecorder variable???
}
I want to use the audioRecorder variable into the last method of my code. because when I declare audioRecorder = new QAudioRecorder;, the variable audio recorder is only accessible into the method on_pushButton_clicked(), so I want to make this variable usable into the method n_pushButton_2_clicked(). How to do it ?
Like some person said in the comments, you need to have your QAudioRecorder object declared as a member of your MainWindow class.
So basically you need something like this :
QAudioRecorder* audioRecorder;//This could also be a shared_ptr
Then, your audioRecorder object is created in your on_pushButton_clicked() function.
You can now use it in on_pushButton_2_clicked() function.
However, this is quite unsafe, for example, if you did not create the audioRecorder before calling on_pushButton_2_clicked(), audioRecorder is not going to point to a valid object and this will most certainly crash your project.
So before using it in on_pushButton_2_clicked(), verify if its valid:
if(audioRecorder)
{
// You can use audioRecorder safely here
}
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);
}
Trying to add text to QGraphicsView:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QGraphicsScene scene;
scene.addText("Hello, world!");
ui->graphicsView->setScene(&scene);
}
But when the project running, there is nothing on the QGraphicsView.
Your QGraphicsScene scene is a local variable and it is deleted immeadiately after the Widget's constructor has been executed.
Change the scene to a private member variable of the Widget class.