How can I overwrite the "next" slot in a QWizard? - c++

I'm using a QWizard class, which contains several QWizardPage. For some pages, I need to do something when the "Next" button is clicked.
I tried to overwrite the next slot in my QWizard class; however, it seems this doesn't work. The program still went into the original next slot in the parent QWizard class instead of the one I implemented.
Is this because this next slot is virtual protected? How can I do some things after the next button is clicked?
The header file of my QWizard class follows. By the way, the accept signal works fine as what I expected.
#ifndef PRIMERWIZARD_H
#define PRIMERWIZARD_H
#include <QWizard>
namespace Ui {
class PrimerWizard;
}
class PrimerWizard : public QWizard {
Q_OBJECT
public:
PrimerWizard(QWidget *parent = 0);
~PrimerWizard();
protected slots:
void next();
void accept();
protected:
void changeEvent(QEvent *e);
private:
Ui::PrimerWizard *ui;
};
#endif // PRIMERWIZARD_H
I create a new wizard instance via QtCreator's wizard (Ha XD)
The code is as follows:
PrimerWizard* pW = new PrimerWizard(this);
pW->exec();
And the signal-slot connection of next is created by QtCreator, I cannot find where it's actually connected. I think the connection is built in ui_PrimerWizard.h by this function:
QMetaObject::connectSlotsByName(PrimerWizard);

The next slot cannot be overwritten. However, the validatePage function for QWizardPage can. This function will be called when the "Next" or "Finish" button is clicked.

Related

How to open a second QMainWindow from my first/original MainWindow?

I am creating a desktop app with Qt6 and C++ and I have my original MainWindow class. Using Qt Creator I generated ui,h,cpp for a new SummaryClass (QMainWindow).
I want to be able to click a button located in MainWindow so that I can open the SummaryWindow.
void MainWindow::openSummary()
{
SummaryWindow window;
window.show();
}
I understand that at the end of the function the window instance falls out of scope and gets destroyed. (the destructor generated by Qt Creator gets automatically called) since the window appears then disappears quickly.
If I were to simply execute
SummaryWindow window = new SummaryWindow();
window.show();
The window would show successfully but then that creates a memory leak.
Are there workarounds/solutions for what I want to achieve?
To be clear, I want to open the window and keep both windows visible.
one alternative is that you define a list of pointers to the summaryClass and you create and show as many instances of the summary as you need in the slot for the button in the mainWindow
your mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QList<SummaryClass*> l;
};
and the slot of the button
void MainWindow::on_pushButton_clicked()
{
SummaryClass* sm = new SummaryClass(this);
l.push_back(sm);
sm->show();
}
as soon as you do this:
new SummaryClass(this);
every summary class will be destroyed when the mainWin is destroyed....
In the constructor of the SummaryWindow write:
SummaryWindow::SummaryWindow() {
this->setAttribute(::Qt::WA_DeleteOnClose);
...
}
That makes the trick. Now
auto window = new SummaryWindow();
window->show();
does not cause a memory leak. (To ensure, you can add some debug printing into ~SummaryWindows()).

No matching signal for QAction, no "go to slot" menu entry

I have problem with actually running QActions created with QtCreator. To run e.g. actionSystemSettings, I've added slot to MainWindows so it looks like this:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_menuWork_actionSystemSettings();
private:
Ui::MainWindow *ui;
};
And this:
void MainWindow::on_menuWork_actionSystemSettings() {
qDebug() << "Yay!";
}
It prompts:
QMetaObject::connectSlotsByName: No matching signal for
on_menuWork_actionSystemSettings()
I guess it's some dumb mistake and I just forgot about something but reading documentation gives me nothing. I have no "go to slot" menu entry which should auto-create some template... at least Visual Studio for C# did that.
When you're defining slots the correct way is:
on_<widget_name>_<signal>
for instance if you have to name your slot
private slots:
on_actionSystemSettings_triggered();
See QtAutoConnect
According to the documentation for QMetaObject::connectSlotsByName():
Searches recursively for all child objects of the given object, and
connects matching signals from them to slots of object that follow the
following form:
void on_object-name_signal-name(signal-parameters);
So, I think your slot should have the following signature:
void MainWindow::on_actionSystemSettings_triggered()
{
//
}

Qt4: connect slot and signal from other forms

I have a small problem. I want run function in MainWindow from AnotherWindow. I can't set connect() for it.
Main class: MainWindow
Other form: AnotherWindow
Function in main class: setVariable(QString)
Function in other form: btnClicked()
I have now connected button signal clicked():
// In AnotherWindow.cpp
connect(ui->btnOK, SIGNAL(clicked()), this, SLOT(btnOkClicked()));
// Function in same file
void interfaceWindow::btnOkClicked() {
/* Some actions - emit signal? */
this->close();
}
btnOkClicked() are declared as private slot.
// In MainWindow.cpp
void MainWindow::setVariable(QString _var) {
this->var = _var;
}
setVariable(QString) are declared as public slot.
How I can send variable from AnotherForm (from btnOkClicked() function) to MainWindow (setVariable(QString) function) ? How and where I must send signal and make connection?
I readed about signals and slots, but my code don't work - I don't paste it here because it's terrible :)
Any help for Qt newbie?
You need to have an reference of AnotherWindow in MainWindow OR vice versa. Then you need the following things:
// AnotherWindow.h
signals:
void buttonOkClickedSignal(QString var);
// AnotherWindow.cpp
void interfaceWindow::btnOkClicked() {
emit buttonOkClickedSignal("The button got clicked!");
this->close();
}
Next step varies based on whether MainWindow has reference to AnotherWindow or vice versa. You can either:
// AnotherWindow.cpp
connect(this, SIGNAL(buttonOkClickedSignal(QString), &mainWindow, SLOT(setVariable(QString)));
or:
// MainWindow.cpp
connect(&anotherWindow, SIGNAL(buttonOkClickedSignal(QString), this, (SLOT(setVariable(QString)));
If you are invoking the slot through signal it shouldn't matter whether it's private or public (see Qt Documentation).
Hope this helps.
I'm not entirely sure I understand your question, but let me try.
You want to be able to fire a slot in another class. There are a few ways you can do that.
Declare one as a friend class to the other. Then they can see the protected and private variables/memebers
It is possible to make slots static so you can call them without a class object.
For example,
class MainWindow {
private slot:
void setVariable(QString);
}
class AnotherWindow {
friend class MainWindow;
MainWindow *window;
public:
AnotherWindow() {
connect(this, SIGNAL(fire(QString)), window, SLOT(setVariable(QString)));
}
signals:
void fire(QString);
public slots:
void onButtonClicked() {
emit fire(QString);
}
}
The previous is pseudocode so don't expect it to compile. I think this is what you want. Basically since your slot is private on MainWindow you need to make it a friend. To connect, it needs to be a member. Then when the onButtonClicked slot is evoked, then it fire()s the setVarialbe() slot.
Here is a simple code for your another window:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0)
{
okBtn = new QPushButton ("I am Ok!");
MyData = "";
connect(okBtn ,SIGNAL(clicked()),this,SLOT(OnOk()));
}
~MyWidget();
private:
QString MyData;
QPushButton * okBtn;
//something that modify string MyData
signals:
void MyDataSignal(QString);
//Internal slot that emits signal with proper data
private slots:
void OnOk()
{
if(MyData!="")
{
emit MyDataSignal(MyData);
}
}
};
Now in MainWindow create an object of MyWidget (suppose myWid)and connect it to slot
connect(myWid, SIGNAL(MyDataSignal(QString)),this,SLOT(OnMyWidOkClicked(QString)));
the signal will pass string to slot.
While making signals and slots keep in mind following points:
To connect a signal to a slot (or to another signal), they must have the same parameter
Parameters should be in the same order in both signal and slot.
if a signal has more parameters than the slot it is connected to, the additional parameters are simply ignored but opposite is not possible.
If you will connect a signal that have unmatched parameters to slot then no compile time error will occur but at run time command window will show a warning that signal/slot/connection does not exist.

Change label text from another class using Qt signals and slots

I'm trying to change text of a class Label from another class. I have class MainWindow, which contains Label.
I also have a Bot class from which I wanna change the value of label.
I'm trying to create signal and slots but I have no idea where to start.
I created signal and slots like so:
//in mainwindow.h
signals:
void changeTextSignal();
private slots:
void changeText();
//in mainwindow.cpp
void MainWindow::changeText(){
this->label->setText("FooBar");
}
But I have no idea how to connect a signal to be able to change Label's text from another class.
Read up on Qt signal-slot mechanism. If I understand you correctly, you are trying to signal from Bot to MainWindow that the Label text needs to change. Here's how you do it...
//bot.h
class Bot
{
Q_OBJECT;
//other stuff here
signals:
void textChanged(QString);
public:
void someFunctionThatChangesText(const QString& newtext)
{
emit textChanged(newtext);
}
}
//mainwindow.cpp
MainWindow::MainWindow
{
//do other stuff
this->label = new QLabel("Original Text");
mybot = new Bot; //mybot is a Bot* member of MainWindow in this example
connect(mybot, SIGNAL(textChanged(QString)), this->label, SLOT(setText(QString)));
}
void MainWindow::hello()
{
mybot->someFunctionThatChangesText("Hello World!");
}

Why can't I access my other form's widgets in Qt?

So, I have the following code in my main window's Qt C++ form (under a button click slot):
newform *nf = new newform(this);
nf->show();
I want to be able to access a webview control I placed on the new form. After some research, I figured that calling nf->ui would be my best bet in order to gain access to all of newform's controls. So I went into newform.h and changed the *ui variable to public:
#ifndef NEWFORM_H
#define NEWFORM_H
#include <QMainWindow>
namespace Ui {
class newform;
}
class newform : public QMainWindow
{
Q_OBJECT
public:
explicit newform(QWidget *parent = 0);
~newform();
Ui::newform *ui;
};
#endif // NEWFORM_H
Yet, whenever I try calling nf->ui, a dropdown menu doesn't appear and I still can't get access to my webview. When I type my code anyway and try to run, I get:
error: invalid use of incomplete type 'class Ui::newform'
error: forward declaration of 'class Ui::newform'
What's going on? Am I doing something wrong? Any help is appreciated. Thanks in advance.
The errors are because you will need access to the ui class definition to call member functions and access the widgets it contains and that is a bad solution to cause such a dependency on that class internals.
So, don't try to access the ui (or the other members) directly, those are private and it's recommended that they stay that way, instead code the functionality you need into the newform class and make that class do the work that you need to be triggered from mainwindow class, something like:
class newform : public QMainWindow
{
Q_OBJECT
public:
explicit newform(QWidget *parent = 0);
~newform();
//code a member function (or a slot if you need a signal to trigger it)
//example:
void loadUrlInWebView(QUrl url);
private:
Ui::newform *ui; //leave this private - it's not a good solution to make it public
};
//and in the .cpp file
void newform::loadUrlInWebView(Qurl url)
{
//you can access the internal widgets here
ui->WEBVIEWNAME->load(url);
//do whatever you need here and you call this public function from other form
}