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 class printrectangle
class PrintRectangle : public QWidget
{
Q_OBJECT
public:
explicit PrintRectangle(QWidget *parent = 0);
private:
void resetClickedIndex();
void updateIndexFromPoint( const QPoint& point);
public:
int mXIndex;
int mYIndex;
QVector<QPoint> points;
bool clicked[5][5] = {};
teacher tech;
perceptron p[5][5];
double techconst = 0.1;
signals:
public slots:
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *eventPress);
};
and MainWindow
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_learn_clicked();
void on_classify_clicked();
private:
Ui::MainWindow *ui;
};
When I click button I call to on_learn_clicked() function. I would like to transfer clicked[5][5] array into on_learn_clicked becasue I send this array to other object when user click button. How to do this?
It is not clear what is exactly the relation between MainWindow and the PrintRectangle widget. I suppose the button signal and PrintRectangle slot are connected somewhere in the MainWindow implementation.
One way to solve the problem would be to use to use the QSignalMapper as #Noidea stated.
Another way would be to use a lambda as a slot when connecting. This way you could capture the sender/receiver or other objects in scope and use their members.
You can find some information about the connect syntax in New Signal Slot Syntax
But basically you could write something like:
connect(button, &QPushButton::clicked, this, [this, printRectangle]()
{
// do smth with clicked[5][5] from printRectangle or just
// retrieve it and call another method like:
// this->processClicked(printRectangle->clicked);
// or pass it to another object
}
This way you could modify your on_classify_clicked slot to a regular method with bool[5][5] argument to do the processing.
I am using Qt and C++, after click on menu item second window appears, and after click on a button in second menu (slot saveData()), I want to change object (obj_map) of class MainMenu. Is it possible, and how to do it the best way? Because I now cannot modify obj_map, because it is in different class. I tried to do something with pointers, but the result was a segmentation fault.
Main Window:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
map obj_map;
public Q_SLOTS:
void saveMap();
private:
Ui::MainWindow *ui;
};
Other window which appears after click in on menu item in main window.
namespace Ui
{
class PreferencesWindow;
}
class PreferencesWindow : public QWidget
{
Q_OBJECT
public:
explicit PreferencesWindow(QWidget *parent = 0);
public Q_SLOTS:
void saveData();
private:
Ui::PreferencesWindow *uip;
};
From here I need to change obj_map
void PreferencesWindow::saveData()
{
// FROM HERE I NEED TO CHANGE obj_map
}
Preferences object is created in a slot:
void MainWindow::saveMap()
{
PreferencesWindow *p = new PreferencesWindow();
p->show();
}
You could use signals and slots: when saveData() is called, emit a signal, like emit saveDataClicked() and catch that signal in the MainWindow with a slot called change_obj_map. There, you can do your changes.
So, in MainWindow you can write:
connect (PreferencesWindow, SIGNAL(saveDataClicked()), this, SLOT(change_obj_map());
and then in the slot:
void change_obj_map()
{
// Do your changes here
}
Another way is having a local obj_map in PreferencesWindow that is a pointer to the address of obj_map in MainWindow. So, when you create PreferencesWindow, you can just pass the address of MainWindow's obj_map to the constructor and assign that address to the local variable obj_map.
As PreferencesWindow objects are created by MainWindow, the easiest is to have PreferencesWindow objects store a pointer to MainWindow:
class MainWindow;
class PreferencesWindow : public QWidget
{
Q_OBJECT
public:
explicit PreferencesWindow(MainWindow *parent = 0);
public Q_SLOTS:
void saveData();
private:
Ui::PreferencesWindow *uip;
MainWindow* m_mainwindow;
};
Pass the pointer upon construction:
void MainWindow::saveMap()
{
PreferencesWindow *p = new PreferencesWindow( this );
p->show();
}
Then use it:
PreferencesWindow::PreferencesWindow(MainWindow *parent) :
QWidget( parent ),
m_mainwindow( parent )
{
}
void PreferencesWindow::saveData()
{
// FROM HERE I NEED TO CHANGE obj_map
m_mainwindow->obj_map.....it's accessible!
}
I'm trying to write my new app, but it crashes every time I press a button on QDialog.
Here's my code :
mainwindow.h
#include <QMainWindow>
#include "creatlist.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QDialog* creatList;
public slots:
void tableFull(){
...some code here...
}
private:
Ui::MainWindow *ui;
};
creatlist.h :
#include <QDialog>
#include "mainwindow.h"
namespace Ui {
class creatlist;
}
class MainWindow;
class creatlist : public QDialog
{
Q_OBJECT
public:
explicit creatlist(QWidget *parent = 0);
~creatlist();
MainWindow* mainwindow;
signals:
void updateList();
public slots:
void ready(){
///////////////////////////////////////////////////////////crash
connect(this,SIGNAL(updateList()),mainwindow,SLOT(tableFull()));
emit updateList();
}
private:
Ui::creatlist *ui;
};
If i try to send some signals my app crashes with a Segmentation Fault.
I did:
void creatlist::ready()
{
mainwindow = new MainWindow(this);
emit mainwindow->linktableFull();
}
but if I try to do QTextBroser.append("hue hue"); in linktableFull(), QTextBrowser is always empty.
Your QTextBrowser always empty because you create new mainwindow object in every ready() function. You should create mainwindow object once and use same mainwindow object throughout code. You can create new mainwindow object in creatlist constructor.
I am a newbie in Qt and C++ programming. I have some problem in my program that i need a solution for.
I have two files MainWindow.h and ChatWindow.h, which contains two classes of MainWindow and ChatWindow.
This is chatwindow.h
namespace Ui {
class ChatWindow;
}
class ChatWindow : public QMainWindow
{
Q_OBJECT
public:
explicit ChatWindow(QWidget *parent=0);
~ChatWindow();
private slots:
void send_chat_fn(pjsua_call_id call_id);
void rcv_chat_fn(pjsua_call_id call_id);
void rcv_msg_fn(QString msg);
void on_pushButton_clicked();
void on_actionQuit_triggered();
private:
Ui::ChatWindow *ui;
};
And this is mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void add_item(QString buddy_uri);
signals:
void send_chat(pjsua_call_id call_id);
void rcv_chat(pjsua_call_id call_id);
void rcv_msg(QString msg);
private slots:
void on_actionAdd_Buddy_triggered();
void on_actionQuit_triggered();
void on_actionStatus_triggered();
void on_actionNew_Chat_triggered();
void on_action_Configuration_triggered();
void on_listWidget_doubleClicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
};
Now i want to connect signals from mainwindow.h to slots in chatwindow.h.
I have tried connection in the constructor of class ChatWindow, but it does not work (i think that is because connections work on instances not on classes). Instance of MainWindow class which i want to connect is in mainwindow.cpp. Defining instances of class ChatWindow in MainWindow gives error:
Cannot set parent, parent is in different thread
And if i create a new instance in Constructor of ChatWindow, then it doesnt connect to the desired instance.
Its a complete mess. Please help me through this.