I have a Qt GUI called MainWindow.
I am rendering some 3D objects in the constructor of the MainWindow.
Moreover I declared a custom class of the vtkInteractorStyleTrackballCamera in MainWindow.cpp like in this example.
Now I would like to call a function from the MainWindow class in the function OnLeftButtonDown() from my custom class of the Interactor.
I tried to inherit the MainWindow class to the custom Interactor class like this:
class customMouseInteractorStyle : public vtkInteractorStyleTrackballCamera, MainWindow
But this doesn't work.
How can I access the functions of the MainWindow there?
The function is automatically called when pressing the left button of the mouse.
// Define interaction style
class customMouseInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static customMouseInteractorStyle* New();
vtkTypeMacro(customMouseInteractorStyle, vtkInteractorStyleTrackballCamera);
virtual void OnRightButtonDown()
{
MainWindowfunction(); // <- I want to call this
vtkInteractorStyleTrackballCamera::OnRightButtonDown();
}
};
vtkStandardNewMacro(customMouseInteractorStyle);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Rendering some things
}
void MainWindow::MainWindowfunction
{
// Do something
}
To answer your specific question, so you say you have this constructor:
customMouseInteractorStyle(MainWindow *ptr) { ptr->MainWindowfunction(); }
To make this work, first add a member variable:
private:
MainWindow *mainWin;
Then change the constructor to initialize it:
customMouseInteractorStyle(MainWindow *ptr) : mainWin(ptr) {}
Then your OnRightButtonDown becomes:
virtual void OnRightButtonDown()
{
mainWin->MainWindowfunction();
vtkInteractorStyleTrackballCamera::OnRightButtonDown();
}
Related
We are developing in C++ (and Qt) using Visual Studio 2015 and the Qt Designer for our UI (via Form / .ui files).
We now need to share some Common Data between our UI elements (e.g. most recently used paths etc.) and I would like to do this via dependency injection (i.e. providing the UI with a Reference to the common object during construction) instead of e.g. (ab)using the singleton pattern.
Has someone faced (and solved) similar problems, and is there a sensible way to do this?
Update (to elaborate):
For example I have a custom FooWidget which I wish to use in my FooDialog.ui form file.
// My custom Widget
class FooWidget : public QWidget {
Q_OBJECT
public:
FooWidget(QWidget* parent);
//...
}
// The FooDialog class (scaffolding created by Qt Designer)
class FooDialog : public QDialog {
Q_OBJECT
public:
FooDialog(QWidget* parent) : QDialog(parent), ui (new Ui::FooDialog()) {
ui->setupUp(this);
//...
}
private:
Ui::FooDialog* ui;
}
// The Ui::FooDialog class autogenerated(!) by Qt Designer
// I cannot (must not) change this code, as it will be regenerated every time
class Ui_FooDialog {
public:
FooWidget* widget;
void setupUi(QWidget *fooDialog) {
//...
widget = new FooWidget(fooDialog);
//...
}
}
namespace Ui { class ScannerStatus: public Ui_ScannerStatus {}; }
I would like to provide the FooWidget with a common data object (e.g. text size and colours shared across all my Ui classes), but I can't do so in the constructor (since the autogenerated Ui_FooDialog treats FooWidget as a generic QWidget, which only needs/takes a QWidget* parent in the constructor - I cannot provide a pointer or reference to my shared TextColourAndSize object.
I am aware I could create a second ui->widget->setupTextColourAndSize(...) step in FooDialog (after the initial ui->setupUi(this)) which provides that common data object, but having two init() type functions seems like a rather bad code smell (one is bad enough).
FooWidget needs two constructors, and a setter for the dependency:
explicit FooWidget(QObject *parent = nullptr) : QWidget(parent), … {
…
}
FooWidget(Dependency *dep, QObject *parent = nullptr) : FooWidget(parent) {
setDependency(dep);
}
void setDependency(Dependency *dep) {
…
}
Then you’d set the dependency after the widget is constructed:
FooDialog(Dependency *dep, …) … {
setupUi(this);
ui->fooWidget->setDependency(dep);
}
This could be automated: the parent widget can have a property that holds the pointer to the dependency, and the child widgets can find it automatically:
FooDialog(Dependency *, …) : … {
setProperty("dependency", dep);
setupUi(this);
}
FooWidget(QWidget *parent) : … {
auto *dep = parent() ? parent()->property("dependency").value<Dependency*>() : nullptr;
if (dep) setDependency(dep);
}
This will work with no extra effort if Dependency derives from QObject. Otherwise, you’ll need to have the following in a suitable header file:
class Dependency { … };
Q_DECLARE_METATYPE(Dependency*)
In all circumstances, you do need to promote the fooWidget object to FooWidget class within Qt Designer.
Ok from what I'm seeing you do not need "dependency injection". Question was incorrectly stated.
You can use this custom widget directly from Qt designer.
When you create your FooDialog place regular widget QWidget in place where you need to have a FooWidget.
Then "promote" regular this widget to FooWidget (possibly you have to add some simple information about that type) - (I did that long time ago and do not remember all details).
For detailed instruction just google: qt promote widget qt designer, you will find lots of examples how to do it.
These were good solutions, but talking about dependency injections, there is also an option to have some fun with C++. It's not a wise solution at all, of course I know it, but nevertheless...
foowidget.h
#ifndef FOOWIDGET_H
#define FOOWIDGET_H
#include <QWidget>
class Something
{
public:
QString getHello() const
{ return "Hello world!"; }
};
/***************************************************/
template<typename T>
class Injector
{
public:
QString getHello() const
{ return m_dataContainer.getHello(); }
private:
T m_dataContainer;
};
/***************************************************/
class FooWidget : public QWidget, public Injector<Something>
{
Q_OBJECT
public:
explicit FooWidget(QWidget* parent = nullptr);
protected:
virtual void mousePressEvent(QMouseEvent*) override;
};
#endif // FOOWIDGET_H
foowidget.cpp
#include "foowidget.h"
#include <QMessageBox>
FooWidget::FooWidget(QWidget *parent)
: QWidget(parent)
{ }
void FooWidget::mousePressEvent(QMouseEvent*)
{
QMessageBox::information(nullptr, "Test", getHello());
}
foodialog.h
#ifndef FOODIALOG_H
#define FOODIALOG_H
#include <QDialog>
class SomethingElse
{
public:
QString getHello() const
{ return "OMG! OMG"; }
};
#include "foowidget.h"
namespace Ui {
class FooDialog;
}
class FooDialog : public QDialog, public Injector<SomethingElse>
{
Q_OBJECT
public:
explicit FooDialog(QWidget *parent = nullptr);
~FooDialog();
protected:
void showEvent(QShowEvent *) override;
private:
QScopedPointer<Ui::FooDialog> ui;
};
#endif // FOODIALOG_H
foodialog.cpp
#include "foodialog.h"
#include "ui_foodialog.h"
#include <QMessageBox>
FooDialog::FooDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::FooDialog)
{
ui->setupUi(this);
}
FooDialog::~FooDialog()
{ }
void FooDialog::showEvent(QShowEvent *)
{
QMessageBox::information(nullptr, "Test", getHello());
}
Multiple inheritance + deriving widgets from some small template proxy class works for both custom widgets and those, having UI forms. I've put a FooWidget on a FooDialog (via propagation mechanizm) in the sketch above and got two message boxes.
The idea itself can be implemented better, with smarter template usage, just tried to reduce sample code, anyway it's an unnessesary complication. But technically it works without any additional initializations =)
I just want to make a custom Dialog, so I want to make a class around the standard QDialog. The goal is to call the constructor which creates the Dialog, and the show() function should be called to make it shown. Next step would be to make a connect between my Widget (which calls the Dialog constructor) Pushbutton and the show() function.
My header looks like this:
#include <QDialog>
class Dialog_Setting : public QDialog
{
Q_OBJECT
public:
Dialog_Setting();
public slots:
void show(void);
private:
QDialog * dialog;
};
my .cpp:
#include "Dialog_Setting.h"
Dialog_Setting::Dialog_Setting()
{
dialog = new QDialog;
}
void Dialog_Setting::show()
{
dialog->show();
}
I have taken out my connect and get a new error.
What is wrong with my class?
undefined reference to `vtable for Dialog_Setting'
thanks for your help, I love StackOverflow
Make sure that show() is implemented as a slot so you can connect() stuff to it:
#include <QDialog>
class Dialog_Setting : public QDialog
{
Q_OBJECT
public:
Dialog_Setting();
public slots:
void show();
};
You also forgot to inherit from QObject or some other QObject-based class like QDialog and to declare the macro Q_OBJECT. All of these things are required to make your custom classes communicate with other classes through connect().
I'm new to programming. I can not understand how to make a reference to the methods of another class.
I have several files and classes:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtCore/QtGlobal>
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class Valve;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void openValve(int id);
void closeValve(int id);
private:
Ui::MainWindow *ui;
Settings *settings;
Valve *valve;
};
class A {
...
private:
void start();
}
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowFlags(Qt::CustomizeWindowHint);
this->setFixedSize(this->geometry().width(),this->geometry().height());
//класс для 7 клапанов
valve = new Valve(7);
}
MainWindow::~MainWindow()
{
delete settings;
delete ui;
}
void MainWindow::valveSwitch(int id)
{
if (valve->getState(id))
closeValve(id);
else
openValve(id);
}
void MainWindow::openValve(int id)
{
QString str = "Valve №" + QString::number(id);
valveButton[id-1]->setEnabled(false);
if (valve->open(id)) {
valveButton[id-1]->setEnabled(true);
//valveButton[id-1]->setPalette(QPalette(Qt::green));
//valveButton[id-1]->setStyleSheet(VALVE_OPEN_COLOR);
QString style = QString(DEFAULT_STYLE_BUTTON) + QString(DEFAULT_BACKGROUND_BUTTON);
valveButton[id-1]->setStyleSheet(style);
ui->mainLabel->setText(str + " open! :)");
}
else {
valveButton[id-1]->setEnabled(true);
ui->mainLabel->setText("Cant open " + str);
remoteDisconnect();
}
}
void MainWindow::closeValve(int id)
{
QString str = "Valve №" + QString::number(id);
valveButton[id-1]->setEnabled(false);
if (valve->close(id)) {
valveButton[id-1]->setEnabled(true);
//valveButton[id-1]->setPalette(style()->standardPalette());
valveButton[id-1]->setStyleSheet("");
ui->mainLabel->setText(str + " close! :)");
}
else {
valveButton[id-1]->setEnabled(true);
ui->mainLabel->setText("Cant close " + str);
remoteDisconnect();
}
}
A::A
{
}
A::~A
{
}
void A::start()
{
//MainWindow::openValve(2);
//valve.open(3);
}
How do I access MainWindow class methods openValve/closeValve from class A?
Or how can I access an instance valve of a class Valve of MainWindow's constructor from class A?
//MainWindow::openValve(2);
//valve.open(3);
At very first:
openValve is not static, so you need an instance of MainWindow to be able to call it:
MainWindow* mw_ex0;
// alternatively, if more appropriate:
MainWindow& mw_ex1;
mw_ex0->openValve(2);
mw_ex1.openValve(2);
The MainWindow instance could be a parameter of your function start or a member variable of class A – depending on your concrete needs.
Same applies if you want to access the valve member (valve is a pointer, so you need operator->): mw_ex0->valve->open(3); or mw_ex1.valve->open(3);).
However, you need to grant class A access to those currently private members; three options:
Make A a friend class of MainWindow - this allows A to access MainWindow's private members (might apply for Valve class, too, if open is not public).
Make the appropriate functions public (MainWindow::openValve and Valve::open); to access the valve member of MainWindow, too, you could make it public, too, but it is in general not recommendable to make the internals of a class publicly available to the outside world - someone might simply change your valve member to something else - and your program is broken... So rather provide a simple getter for.
Make A an inner class of MainWindow. Then it gets access to its outer class members implicitly (depending on the requirements for class A, this might not be suitable – up to you to decide...).
Sidenotes:
In your constructor, you do not initialise the settings member.
You do not clean up the valve member in your destructor (potential memory leak).
To avoid having to clean up, you could to incorporate valve directly in your class - this is not always suitable, but might be a good option here (up to you to decide, just showing the alternative):
class MainWindow
{
Valve valve;
};
MainWindow::MainWindow()
: valve(7) // calls constructor directly
{ }
Be aware that you now do use operator. to access the valve's members (mw_ex0->valve.open(3);). Advantage is that Valve will no be automatically cleaned up together with MainWindow. Alternatively, a std::unique_ptr could be used to hold the pointer to your Valve instance, then you get automatic cleanup, too.
You should pass a MainWindow object into the A::start method:
class A {
...
private:
void start(MainWindow & w);
}
void A::start(MainWindow & w) {
w._MainWindow_method_name_here_();
}
Or you should declare a static method in MainWindow class:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static void aStaticMethod();
};
void MainWindow::aStaticMethod() {
...
}
void A::start() {
MainWindow::aStaticMethod();
}
To access protected/private methods of MainWindow you should declare the A class as a friend of MainWindow:
class MainWindow : public QMainWindow
{
friend class A;
...
};
Update
I create a new class for it to work in a separate thread, and call its methods from the main class (by clicking on the button). Accordingly, I need class A to open / close valves, etc.
The "true Qt way" is to use signals & slots mechanism.
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// Transform open/closeValve methods into slots
// (a method that can be assigned as an event handler)
//
public slots:
void openValve(int id);
void closeValve(int id);
private:
Ui::MainWindow *ui;
Settings *settings;
Valve *valve;
};
// This class should be a descendant of QObject
//
class A : public QObject
{
Q_OBJECT
// Transform this method to a slot, so it can be called
// as regular method, or can be assigned as an event handler,
// for instance, as QPushButton::click handler.
//
public slots:
void start();
// Add signals
//
signals:
void openValveSignal(int id);
void closeValveSignal(int id);
}
void A::start()
{
// do something and then emit the signal to open valve,
// MainWindow::openValve(2) will be called
emit openValveSignal(2);
...
// do something and then emit the signal to close valve,
// MainWindow::closeValve(3) will be called
emit closeValveSignal(3);
}
// connects A signals with MainWindow slots,
// so when you `emit A::***Signal()` then corresponding
// `MainWindow::***` method will be called
//
void initialize(MainWindow * pWnd, A * pA)
{
QObject::connect(pA, &A::openValveSignal, pWnd, &MainWindow::openValve);
QObject::connect(pA, &A::closeValveSignal, pWnd, &MainWindow::closeValve);
}
You can call a->start() method from MainWindow methods as usual. Or you can connect button clicked signal with A::start method, for instance:
void initialize(MainWindow * pWnd, QAbstractButton * pBtn, A * pA)
{
// C++11 lambda function is used here because A::start has no arguments
QObject::connect(pBtn, &QAbstractButton::clicked, [pA](){ pA->start(); });
QObject::connect(pA, &A::openValveSignal, pWnd, &MainWindow::openValve);
QObject::connect(pA, &A::closeValveSignal, pWnd, &MainWindow::closeValve);
}
so when you click a button then A::start method will be called automatically. And then MainWindow::open/closeValve methods will be called from A::start method.
Declare openValve as public method and valve as public object (open must be public too)
Then use as:
MainWindow mainWindow;
mainWindow.openValve(2);
mainWindow.valve.open(3);
I have difficulties in understanding how to pass parent object to child.
In Qt, I have a MainWindow class and a DoSomething() function. Then I created a Job object within MainWindow and tried to call DoSomething within Job's DoItNow() function. But I just don't know how to do it.
MainWindow.h
class Job;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int value;
void DoSomething();
private:
Job *job;
}
MainWindow.cpp
#include "mainwindow.h"
#include "job.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
job = new Job(this); // passing this pointer to child
}
void MainWindow::DoSomething() { // do something }
Job.h
class Job : public QObject
{
Q_OBJECT
private:
void DoItNow();
public:
explicit CDMcommand(QObject *parent = 0);
}
Job.cpp
#include "job.h"
#include "mainwindow.h"
Job::Job(QObject *parent) : QObject(parent)
{
// some setups
parent->value = 0; // this is not working
}
void Job::DoItNow()
{
parent->DoSomething(); // What is the pointer to MainWindow instance?
}
How to access non-static public register in *parent?
How to pass *parent to function in job instance?
Maybe I missunderstand the question, but I think you are a bit confused about inheritance. Your Job is a child class of QObject and MainWindow indirectly inherits also form QObject, but there is no direct relation between MainWindow and Job. I am not too familiar with Qts signal and slot mechanism, which is probably the way to go here, but maybe I can offer you a different solution:
Job::Job(QObject *parent) : QObject(parent)
{
// some setups
parent->value = 0; // this is not working
}
This is not working, because QObject has no member called value. If you can live with Jobs constructor not taking a QObject* as parameter, then just declare a
MainWindow* parentWindow;
as a private member in Job and change the constructor to
Job::Job(MainWindow *parentWindow) : QObject(parentWindow)
{
// some setups
parentWindow->value = 0; // this will work now
}
then also
void Job::DoItNow()
{
parentWindow->DoSomething();
}
will work without problems.
How can I call the Qt 'parent' object method from the 'child'
object method?
The safe and simple way to do it:
void Job::DoItNow()
{
// first evaluate the pointer: is that of type we expect?
MainWindow* pMainWindow = qobject_cast<MainWindow*>(parent());
if (pMainWindow)
pMainWindow->DoSomething(); // MainWindow::DoSomething must be exposed to class Job
}
But of course making two classes dependent on each other too much is a violation of OOP principles: these two objects become tightly coupled now. And there is already a good suggestion in comments: use an explicit signal-slot mechanism for that or providing the interface to interact between decoupled objects.
I'm studying the Qt4 library and I want to add some functionality to all the children of QWidget in my project. I need all widgets to have mousePressEvent overridden. Obviously I do not need to override it in every particular widget I use(I use many of them and I they to follow DRY rule) , instead I create a Foo class:
class Foo : public QWidget
{
Q_OBJECT
protected:
/* implementation is just a test */
virtual void mousePressEvent(QMouseEvent*) { this->move(0,0); }
};
And derive my button from it:
class FooButton : public QPushButton , public Foo
{
public:
FooButton (QWidget* parent) : QPushButton(parent) { };
};
But the event seems to be not overridden... What am I doing wrong?
Thanks in advance.
For the mousePressEvent access, try QObject::installEventFilter().
http://doc.qt.digia.com/stable/qobject.html
You are inheriting twice now from QWidget. This is problematic (see diamond problem).
Instead, drop your Foo class and move your custom mouse press event handler to your FooButton class:
class FooButton : public QPushButton
{
Q_OBJECT
protected:
/* implementation is just a test */
virtual void mousePressEvent(QMouseEvent*) { this->move(0,0); }
public:
FooButton (QWidget* parent) : QPushButton(parent) { };
};
If this doesn't suit the design of your application, then try using virtual inheritance instead. That is, change Foo to:
class Foo : public virtual QWidget
If that doesn't help, you should follow the advice of the other answers and install an event handler.
(You can read about virtual inheritance in its Wikipedia article.)
I suspect that the problem is that you're inheriting from QWidget twice, once through QPushButton and once through Foo.
From the way you phrased the question, I'm assuming that you want to do this for varying kinds of widgets, and thus don't want to have to subclass QPushButton, QLabel, QCheckBox, etc. If this is not the case then you should use Nikos's answer.
If not, your best bet is probably doing to be to use an event filter.
class MousePressFilter : public QObject {
Q_OBJECT
public:
MousePressFilter(QObject *parent) : QObject(parent) { }
protected:
bool eventFilter(QObject *watched, QEvent *event) {
QWidget *widget = dynamic_cast<QWidget*>(watched);
widget->move(0,0);
return false;
}
};
And then in your Foo class constructor:
class Foo {
Foo() {
installEventFilter( new MousePressFilter(this) );
}
};