inheritance in Qt won't allow me to reference? - c++

So I I have an h file and a cpp file in a Qt project. I have to declare some qstrings inside my header file and I would like to reference them in my cpp file but I don't seem to be able to access it, can someone explain why or the correct way to do it?
#ifndef PROFILE_H
#define PROFILE_H
#include <QMainWindow>
#include "login.h"
#include "searchnote.h"
#include "note.h"
#include <QDebug>
namespace Ui {
class Profile;
}
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
private slots:
void on_actionAdd_Note_triggered();
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
Note myNoteList;
};
#endif // PROFILE_H
#include "profile.h"
#include "ui_profile.h"
Profile::Profile(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Profile)
{
ui->setupUi(this);
}
Profile::~Profile()
{
delete ui;
}
void Profile::on_actionAdd_Note_triggered()
{
SearchNote openSearch; //will send us the searchNote gui
openSearch.setModal(true);
openSearch.exec();
}
void myNoteListAdd(QString newName){
myNoteList.add(); //the cpp file doesnt recognize this object
}

myNoteListAdd is a stand-alone function, myNoteList is a private data member of Profile class.
Only member functions (often also called methods) of the same class can access these private data members

It may be the case that you intend myNoteListAdd to be a member function of Profile, i.e.
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
private slots:
void on_actionAdd_Note_triggered();
**void myNoteListAdd(QString newName);**
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
Note myNoteList;
};
And implement as:
void Profile::myNoteListAdd(QString newName){
myNoteList.add(newName); // assuming you want to add newName to myNoteList
}
Otherwise, you need some form of accessing the member myNoteList, either by making it public or having a getter member. In either case you need an instance of a Profile to work with, i.e.:
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
//either this:
Note myPublicNoteList;
// or this
Note getNoteList() { return myNoteList; }
private slots:
void on_actionAdd_Note_triggered();
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
};
then in your .cpp
void myNoteListAdd(QString newName)
{
Profile p = new Profile(); // or some other mechanism to get a Profile
//then either
p.myPublicNoteList.add(newName);
// or
p->getNoteList().add(newName);
}

Related

recover a slot parameter

I have a slot that receives a QString, and I want to assign the value for this parameter in another variable, or use it directly in another method of the same class.
The signal is emitted from some other class.
MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include"myclass.h"
#include <QWidget>
#include <QtWidgets>
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
private:
Ui::MyWidget *ui;
signals:
void redirectData(QString data);
public slots:
void sendData();
private:
MyClass *myClass; // the object to receive and output the data
};
#endif // MYWIDGET_H
MyWidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
myClass = new MyClass();
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(sendData()));
connect(this, SIGNAL(redirectData(QString)), myClass, SLOT(outputData(QString)));
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::sendData()
{
emit redirectData(ui->lineEdit->text());
myClass->show();
}
MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QWidget>
namespace Ui {
class MyClass;
}
class MyClass : public QWidget
{
Q_OBJECT
public:
explicit MyClass(QWidget *parent = 0);
~MyClass();
QString x;
private:
Ui::MyClass *ui;
signals:
void send2(QString);
public slots:
void outputData(QString data);
};
#endif // MYCLASS_H
MyClass.cpp
#include "myclass.h"
#include "ui_myclass.h"
MyClass::MyClass(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyClass)
{
ui->setupUi(this);
ui->plainTextEdit->insertPlainText(x); // show x in plainTextEdit
}
MyClass::~MyClass()
{
delete ui;
}
void MyClass::outputData(QString data){
x=data; // affect data a x
}
I want to display the value of x in the QPlainTextEdit.
This method is correct but does not fit with the rest of my code. I would like to preserve the value in x.
MyClass.cpp
#include "myclass.h"
#include "ui_myclass.h"
MyClass::MyClass(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyClass)
{
ui->setupUi(this);
}
MyClass::~MyClass()
{
delete ui;
}
void MyClass::outputData(QString data){
ui->plainTextEdit->insertPlainText(data);
}
This now an OK question, if a tad wordy and basic. It is clearly mostly complete (the .ui files are missing - but don't include them!) and reproducible.
Thus, there are two things that you can do:
Simply set the value of the plain text edit in the slot:
void MyClass::outputData(QString data){
x = data;
ui->plainTextEdit->insertPlainText(x);
}
You don't need to store the value in x at all, if you don't need it anywhere else in MyClass.
If MyClass should expose the x property to interact with other classes, you should make it so - and then use the notification signal to modify the widget:
class MyClass : public QWidget {
Q_OBJECT
Q_PROPERTY(QString x READ x WRITE setX NOTIFY xChanged)
QString m_x;
Ui::MyClass *ui;
public:
explicit MyClass(QWidget *parent = {}) {
ui->setupUi(this);
connect(this, &MyClass::xChanged, ui->plainTextEdit, &QPlainTextEdit::insertPlainText);
~MyClass {}
Q_SIGNAL void xChanged(const QString &);
Q_SLOT void setX(const QString &x) {
if (m_x != x) {
m_x = x;
emit xChanged(m_x);
}
}
QString x() const { return m_x; }
};
Other notes
The MyClass::x member should not be public.
The containers passed as method arguments should be almost always of a const reference type - to avoid the premature pessimization of making copies of objects passed. Thus you should modify the signatures as follows - in both declarations (header files) and definitions (implementation - .cpp files):
void MyClass::send2(const QString&);
void MyClass::outputData(const QString &data)
void MyWidget::redirectData(const QString &data)
The old-style connect syntax you use demands normalized signatures and doesn't change - the const and reference must be dropped.
There's no need to store the ui by pointer - simply store it by value. The C++ language then automatically takes care of memory management for you, and the default compiler-generated destructor does the job.
In self-contained examples, there's no need to use the .ui files. Creating the widgets manually and laying them out is quite trivial, as you can see below.
A reworked example
Taking all this into account, this would be a self-contained demo - with no Ui files needed. Your question should have had something like this included - it's self contained, single file. The use of the properties is not undesirable to indicate intent: those are the changeable properties of the classes.
#include <QtWidgets>
class Source : public QWidget {
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
QHBoxLayout m_layout{this};
QLineEdit m_edit;
QPushButton m_send{tr("Send")};
QString m_text;
public:
Source(QWidget *parent = {}) : QWidget(parent) {
m_layout.addWidget(&m_edit);
m_layout.addWidget(&m_send);
connect(&m_send, &QPushButton::clicked, [this]{
setText(m_edit.text());
});
}
Q_SLOT void setText(const QString &text) {
if (text == m_text) return;
m_text = text;
emit textChanged(m_text);
}
QString text() const { return m_text; }
Q_SIGNAL void textChanged(const QString &);
};
class Destination : public QWidget {
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
QHBoxLayout m_layout{this};
QPlainTextEdit m_edit;
QString m_text;
public:
Destination(QWidget *parent = {}) : QWidget(parent) {
m_layout.addWidget(&m_edit);
connect(this, &Destination::textChanged, &m_edit, &QPlainTextEdit::setPlainText);
}
Q_SLOT void setText(const QString &text) {
if (text == m_text) return;
m_text = text;
emit textChanged(m_text);
}
QString text() const { return m_text; }
Q_SIGNAL void textChanged(const QString &);
};
int main(int argc, char **argv) {
QApplication app{argc, argv};
Source src;
Destination dst;
QObject::connect(&src, &Source::textChanged, &dst, [&](const QString &text){
if (!dst.isVisible()) {
dst.move(src.frameGeometry().topRight()); // align the windows
dst.show();
}
dst.setText(text);
});
src.show();
return app.exec();
}
#include "main.moc"

Reference in C++ classes

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);

Subclassing QLabel and use it in QWidget class

When i try to put QLabel in QWidget class its not work properly (no hover event or click event only the label pixmap is show) only the last instance work properly, when not use set parent, it create in new window for each label but its work correctly
this gif show the problem:
https://media.giphy.com/media/3o7TKKmZSISGXN4Opq/giphy.gif
this is QLabel subclass header:
#include <QObject>
#include <QLabel>
class myLabel : public QLabel
{
Q_OBJECT
public:
myLabel();
protected:
void mousePressEvent(QMouseEvent *);
void enterEvent(QEvent *);
void leaveEvent(QEvent *);
signals :
void labelClicked();
void enterSignal();
void leaveEventSignal();
private:
};
this class to make a labelButton:
#include <QObject>
#include <QWidget>
#include "mylabel.h"
class labelButton : public QWidget
{
Q_OBJECT
public:
labelButton();
//some functions
private slots:
//slots
private:
//private member
};
and this the class that i want to use the labelButtons in:
#include <QWidget>
#include "labelbutton.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
labelButton *b_1, *b_2, *b_3;
};
here is widget.cpp:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
b_1 = new labelButton;
b_1->setParent(this);
b_1->moveButton(70, 100);
//some functions to initialize the labelButton
b_1->show();
//-----------------------
b_2 = new labelButton;
b_2->setParent(this);
b_2->moveButton(70, 200);
//some functions to initialize the labelButton
b_2->show();
//-----------------------
b_3 = new labelButton;
b_3->setParent(this);
b_3->moveButton(70, 300);
//some functions to initialize the labelButton
b_3->show();
}
here its work, the problem was in passing the parent
i made a function that take a widget and set buttons parent from the function value
b_1 = new labelButton;
//b_1->setParent(this);
b_1->setParentFunc(this);
b_1->moveButton(70, 100);
//some functions to initialize the labelButton
// b_1->show();
in labelButton:
void labelButton::setParentFunc(QWidget *p)
{
myParent = p;
}
mLabel_1->setParent(myParent); // myParent instead of this

Subclassing QString to add more functionality?

Trying to add functionality to QString but get build errors ?? And if I am missing things??
#ifndef CSTRING_H
#define CSTRING_H
#include <QString>
#include <QStringList>
#include <QObject>
class CString : public QString, public QObject
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0);
QStringList Find(QString qstrSearch);//all occurances
signals:
public slots:
};
#endif // CSTRING_H
#include "cstring.h"
CString::CString(QObject *parent) :
QString(parent) //ERROR IS POINTING TO HERE
{
}
QStringList Find(QString qstrSearch)//all occurances
{//indexOf, contains
QStringList qstrList;
return qstrList;
}
Don't derive classes form QString since it wasn't designed with polymorphy in mind (note that it has no virtual methods, in particular no virtual destructors) If you want to provide new utility functions, just use free functions - you may want to put them in a namespace:
namespace CString {
QStringList find(const QString &search);
}
QString(parent) Qstring does not have a constructor taking a QObject-parent as parameter. Therefor the compiler tries to cast your QObject to closest Matching constructor, which probably would be QString ( QChar ch )
You should use composition instead of inheritance here, because QString is not designed for subclassing. You can get a lot of troubles if you will subclass it.
Do something like this:
class CString : public QObject //if you're really need this class to be QObject, that's not always a good idea
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0) :
QObject(parent),
mString() //QString have no constructors with parameter QObject*...
{
}
private:
QString mString;
}
Of course, implementation should be in cpp file, it's just a short example

Access a variable from another class

I have two classes, MyClass and Widget. Below is the MyClass class and from my Widget class i want to get the str variable. How is that done?
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
void fetch();
public slots:
void replyFinished(QNetworkReply*);
private:
QNetworkAccessManager* m_manager;
};
MyClass::MyClass()
{
m_manager = new QNetworkAccessManager(this);
connect( m_manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
void MyClass::fetch()
{
m_manager->get(QNetworkRequest(QUrl("http://stackoverflow.com")));
}
void MyClass::replyFinished(QNetworkReply* pReply)
{
QByteArray data=pReply->readAll();
QString str(data);
//this str should be available in my widget class
}
EDIT: Here is a the important part of the widget
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
};
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//here str should be accessed
}
If you want the str variable from your function available to classes or other functions, here are two choices:
Return it from the function.
Declare a variable in MyClass to hold the string and set the
variable to the value.
Case 1: Returning from a function
QString MyClass::replyFinished(...)
{
QString str(data);
return data;
}
Case 2: Declare a class member variable
class MyClass
{
public:
QString m_replyStr;
};
//...
void MyClass::replyFinished(...)
{
QByteArray data = pReply->readAll();
m_replyStr = data;
}
Modifying your question with an example of what you want to do would be very helpful.
You can emit a signal with str as argument and connect it to a slot in your widget. Then you can do what you want with it.
This way you will preserve the event oriented design and you have not need to control if str exists. Simply when it's ready the slot will handle it.
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
void fetch();
public slots:
void replyFinished(QNetworkReply*);
signals:
void strReplyReady(QString str);
private:
QNetworkAccessManager* m_manager;
};
...
void MyClass::replyFinished(QNetworkReply* pReply)
{
QByteArray data=pReply->readAll();
QString str(data);
emit strReplyRead(str);
}
your Widget
class MyWidget : public QWidget
{
//public members
...
public slots:
void readReply(QString str);
}
void MyWidget::readReply(QString str){
//do what you want with str
}
in the main.cpp you do the connect with the static member of QObject
QObject::connect(myClassPointer,SIGNAL(strReplyReay(QString)) ,
myWidgetPointer,SLOT(readReply(QString)));