Accessing a class object from outside - c++

I created a basic project on the TouchGFX Designer and wrote a function in my own cpp file using touchgfx library. I want that when the button is clicked ,the function is called to ScreenView.cpp or ScreenViewBase.cpp from my own cpp file and change the color of the box.
This is my cpp file.
#include <touchgfx/Color.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <gui/screen1_screen/Screen1View.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
#include <touchgfx/widgets/Box.hpp>
ChangeColor::ChangeColor()
{
Screen1View::box1;
box1.setColor(touchgfx::Color::getColorFrom24BitRGB(51, 168, 35));
box1.invalidate();
}
This is the Screen1View.cpp where I want to call my function.
#include<gui/ChangeColor.hpp>
#include <touchgfx/Color.hpp>
Screen1View::Screen1View():
buttonCallback(this, &Screen1View::buttonCallbackHandler)
{
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
button1.setAction(buttonCallback);
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
void Screen1View::buttonCallbackHandler(const touchgfx::AbstractButton& src)
{
if (&src == &button1)
{
//Interaction1
//When button1 clicked execute C++ code
//Execute C++ code
//ChangeColor();
ChangeColor();
}
}
and this is the Screen1BaseView.hpp where the box is declared
#define SCREEN1VIEWBASE_HPP
#include <gui/common/FrontendApplication.hpp>
#include <mvp/View.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Button.hpp>
class Screen1ViewBase : public touchgfx::View<Screen1Presenter>
{
public:
Screen1ViewBase();
virtual ~Screen1ViewBase() {}
virtual void setupScreen();
protected:
FrontendApplication& application() {
return *static_cast<FrontendApplication*>(touchgfx::Application::getInstance());
}
/*
* Member Declarations
*/
touchgfx::Box __background;
touchgfx::Box box1;
touchgfx::Button button1;
private:
};
I can't access the box. Is there way to do it?

TouchGFX uses MPV architecture, i.e. Model-Presenter-View. The point is Model and View can not access each other.
In your case, your cpp file play role as a model, so it's not allowed to access element in View. That's the reason why you can't access. You need a Presenter to handle the connection.

Related

Getting an error "allocating an object of abstract class type in Juce Framework?

i am new in juce and getting an error like "allocating an object of abstract class type 'CreateAccount'" i am beginner in c++. i am try to call the class from the main window of juce and getting error like this.Below is my code
Main.cpp file
#include <JuceHeader.h>
#include "CreateAccount.h"
//==============================================================================
class TestApplication : public JUCEApplication
{
public:
//==============================================================================
TestApplication() {
}
const String getApplicationName() override {
return "Test";
}
const String getApplicationVersion() override { return "1.0.0"; }
void initialise (const String&) override {
mainWindow.reset (new MainWindow ("Test", new CreateAccount(), *this));
// splash = new SplashScreen("Welcome to Screen!",ImageFileFormat::loadFrom(File("/Resources/bell.png")),
// true);
// splash->deleteAfterDelay(RelativeTime::seconds(5), false);
}
void shutdown() override {
mainWindow = nullptr;
}
private:
class MainWindow : public DocumentWindow
{
public:
MainWindow (const String& name, Component* c, JUCEApplication& a)
: DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel()
.findColour (ResizableWindow::backgroundColourId),
DocumentWindow::allButtons),
app (a)
{
setUsingNativeTitleBar (true);
setContentOwned (c, true);
#if JUCE_ANDROID || JUCE_IOS
setFullScreen (true);
#else
setResizable (true, false);
setResizeLimits (300, 250, 10000, 10000);
centreWithSize (getWidth(), getHeight());
#endif
setVisible (true);
}
void closeButtonPressed() override
{
app.systemRequestedQuit();
}
private:
JUCEApplication& app;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE (MainWindow)
};
std::unique_ptr<MainWindow> mainWindow;
};
//==============================================================================
START_JUCE_APPLICATION (TestApplication)
CreateAccount.h file
#include <JuceHeader.h>
//new page for create profile
class CreateAccount : public Component,
public Button::Listener
{
public:
CreateAccount() {
addAndMakeVisible(lblloginwithfb);
lblloginwithfb.setFont(Font(18.0f));
lblloginwithfb.setText("Login with Facebook", dontSendNotification);
lblloginwithfb.setColour(Label::textColourId, Colours::white);
//ready to play button
btncreteprofile.setButtonText("Create your profile");
btncreteprofile.setColour(TextButton::textColourOffId, Colours::white);
btncreteprofile.setColour(TextButton::textColourOnId, Colours::white);
btncreteprofile.setColour(TextButton::buttonColourId, Colour::fromRGB(235,135,15));
btncreteprofile.setColour(TextButton::buttonOnColourId, Colour::fromRGB(235,135,15));
addAndMakeVisible(btncreteprofile);
}
//==============================================================================
void paint(Graphics &g) override {
g.fillAll(Colours::black);
}
void resized() override {
/*Rectangle<int> bounds = getLocalBounds();
FlexBox flexBox;
flexBox.flexDirection = FlexBox::Direction::column;
flexBox.flexWrap = FlexBox::Wrap ::noWrap;
flexBox.alignContent = FlexBox::AlignContent::center;
Array<FlexItem> itemarray;
itemarray.add(FlexItem(80,50,btncreteprofile));
itemarray.add(FlexItem(getWidth(),50,lblloginwithfb));
flexBox.items = itemarray;
flexBox.performLayout(bounds.removeFromBottom(200));*/
Rectangle<int> bounds = getLocalBounds();
const int insetX = getWidth() / 4;
const int insetY = getHeight() / 4;
btncreteprofile.setBounds(insetX,bounds.getCentre().y+80,getWidth() - insetX * 2, 50);
lblloginwithfb.setBounds(insetX,insetY,getWidth() - insetX * 2,getHeight());
}
private:
//==============================================================================
// Your private member variables go here...
Label lblloginwithfb;
TextButton btncreteprofile;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CreateAccount)
};
Please help me when i try to add the listner in createaccount file then will get an error.
You need to implement all pure virtual methods in Button::Listener to make your class not abstract. Button::Listener contains these two methods
virtual void buttonClicked (Button *)=0
virtual void buttonStateChanged (Button *)
The second method is not pure virtual, so you don't have to implement it.
So add a method to your class
virtual void buttonClicked (Button *) override {}
and add the code needed when the button is clicked.
Depending on the C++ version you're using, the override might not get accepted by the compiler. In that case, just omit it. It is used to allow
the compiler to emit warnings/errors with respect to overridden methods.
In JUCE, most UI related things are implemented as a subclass of Component.
Some of the subclasses have the concept of a content component: all subclasses
of ResizableWindow, which adds the setContentOwned() and setContentNonOwned()
methods, inherited by all subclasses of ResizableWindow (especially
DocumentWindow).
To define the content of the DocumentWindow, the example code in your question
uses setContentOwned() in the MainWindow constructor which it gets from the
initialise() in TestApplication.
To implement the navigation you could do the following (there are other ways to do it):
1. Implement the navigation in the MainWindow, so you have the navigation logic in one central place
2. Give each of your "Pages" (let's call one step a Page.) a pointer to the MainWindow. For CreateAccount that would be
CreateAccount.h file:
void setMainWindow(MainWindow * _mainWindow)
{
mainWindow = _mainWindow;
}
3. Add an instance variable, too, somewhere in the CreateAccount class:
MainWindow * mainWindow;
and update the constructor:
CreateAccount()
: mainWindow(nullptr)
{
// ...
}
4. Change the creation code
replace
mainWindow.reset (new MainWindow ("Test", new CreateAccount(), *this));
by:
CreateAccount * ca = new CreateAccount();
MainWindow * mw = new MainWindow ("Test", ca, *this)
ca->setMainWindow(mw);
mainWindow.reset(mw);
5. Implement your navigation in a set of custom methods (need to be public) in MainWindow, e.g.
public:
void createProfileClicked()
{
// ...get entered data...
// ...process entered data...
// ...implement next navigation step...
// (you would create or recycle the "Page" for the next step here)
setContentOwned(
// ...
);
}
6. Call that method from the buttonClicked() event handler in CreateAccount:
mainWindow->createProfileClicked();
This is just one way to implement what you want. It all depends on the complexity of your project.
Edit:
My suggestion given in this answer introduces cyclic dependencies of classes.
Let me first restate what I think you currently have, deduced from your comments:
mainwindow.h
#include "splashpage.h"
class MainWindow : public DocumentWindow
{
public:
// ...
void alaramReadyBtnClicked()
{
setContentOwned(new SplashPage(), false);
}
// ...
};
splashpage.h:
#include "mainwindow.h"
class SplashPage : public Component, public Button::Listener
{
public:
SplashPage()
: mainWindow(nullptr)
{}
void setMainWindow(MainWindow * _mainWindow)
{ mainWindow = _mainWindow; }
void buttonClicked (Button *) override
{
if (button == &tvbtnSomething) {
mainWindow->splashSomethingClicked();
}
}
private:
MainWindow * mainWindow;
};
There's a cyclic dependency of declarations in there between MainWindow and the Page classes. When the compiler sees
mainWindow->splashSomethingClicked();
it needs to have seen the declaration of MainWindow but in mainwindow.h
it needs the declaration of SplashPage for this:
void alaramReadyBtnClicked()
{
setContentOwned(new SplashPage(), false);
}
First, it is good practice to use include guards in your header files
e.g. mainwindow.h
// you need these include guards to prevent that the compiler
// sees this file a second time; it's a very good rule of thumb to always do this
// in you header files
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "splashpage.h"
class MainWindow : public DocumentWindow
{
// ...
};
#endif // !defined(MAINWINDOW_H)
There are specific situations in C++ for which the compiler doesn't need to know the complete declaration: if you only use pointers or references and don't reference them. You can then use a forward declaration of class names.
But you can't do this with everything in header files only. Because there's a concept of a "compilation unit".
To break the cyclic dependency, change your ...Page.h:
#ifndef SPLASHPAGE_H
#define SPLASHPAGE_H
// don't include mainwindow.h here
class MainWindow; // forward declaration
class SplashPage : public Component, public Button::Listener
{
public:
SplashPage()
: mainWindow(nullptr)
{}
void setMainWindow(MainWindow * _mainWindow)
{
mainWindow = _mainWindow; // pointer copy does not need full declaration
}
// note: implementation not in this header file anymore
void buttonClicked (Button *) override;
private:
// ...
MainWindow * mainWindow; // does not need full declaration
};
#endif // !defined(SPLASHPAGE_H)
splashpage.cpp:
#include "mainwindow.h"
#include "splashpage.h"
void SplashPage::buttonClicked (Button *) override
{
if (button == &tvbtnSomething) {
mainWindow->splashSomethingClicked();
}
}
If you use the JUCE Projucer tool, you can add pairs of these files easily which should already contain the include guards stuff.

Make an object know what is happening inside a show function it's created

It's my first time using Qt IDE and I got stuck on a problem.
I have two classes that are connected through an interface. One is the ContrGeral and the other is the IAAutenticacao. The ContrGeral opens the main window. How can the class ContrGeral knows what's happening inside the show function that it has executed in order to make the class IAAutenticacao runs another window (or update it)?
I'm following the concept of interface, so I can't just put a sequential of actions inside the MainWindow class (created by ContrGeral). I need it to inform the ContrGeral somehow about the situation.
As the show function that opens the window don't return anything nor receive anything, I don't know what to do.
main.cpp
#include "windows.h"
#include "controladoras.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CntrGeral tela_inicial;
tela_inicial.mostra();
return a.exec();
}
controladores.h
#ifndef CONTROLADORAS_H
#define CONTROLADORAS_H
#include "interfaces.h"
#include "dominios.h"
#include "windows.h"
#include <QApplication>
#include <stdexcept>
using namespace std;
class CntrGeral {
private:
IAAutenticacao *cntrIAAutenticacao;
IAUsuario *cntrIAUsuario;
IAEventos *cntrIAEventos;
MainWindow inicial;
public:
void setIAAutenticacao(IAAutenticacao *);
void setIAUsuario(IAUsuario *);
void setIAEventos(IAEventos *);
void mostra();
};
void inline CntrGeral::setIAAutenticacao(IAAutenticacao *cntrIAAutenticacao) {
this->cntrIAAutenticacao = cntrIAAutenticacao;
}
void inline CntrGeral::setIAEventos(IAEventos *cntrIAEventos) {
this->cntrIAEventos = cntrIAEventos;
}
void inline CntrGeral::setIAUsuario(IAUsuario *cntrIAUsuario) {
this->cntrIAUsuario = cntrIAUsuario;
}
void inline CntrGeral::mostra() {
inicial.show();
}
#endif // CONTROLADORAS_H
The problem is at inicial.show(), once it is executed it does not return anything.
thanks in advance.
You need more knowledge about Qt signals and slots. read this before.
Then you can do the connections as follows:
First add slots in your class CntrGeral:
controladores.h
class CntrGeral {
...
public slots:
void onMainWindowPressButton();
...
}
Then connect and add the implementation of the slot:
controladores.cpp
CntrGeral::CntrGeral()
{
...
// connect for example "pushButton" (a QPushButton's object)
// Which is a member of your MainWindow's object "inicial"
connect(inicial.pushbutton, SIGNAL(release()),
this, onMainWindowPressButton());
...
}
CntrGeral::onMainWindowPressButton()
{
/** TODO after push button pressed **/
}
Hope it helps you.

Qt5.11 app plugins build error occurs: Signal and slot arguments are not compatible

I want to develop an plugin-based Qt application.
As one part of the app, plugins should be able to add toolbars or widgets to app's MainWindow.
I think the toolbar of plugins should be created within plugin's implementation and passed to MainWindow.
Refer this link:Qt object management with Qt Plugins I write my code.
I use an on_Action_triggered()(function no param) as slot to receive the signal of toolbar action triggered(), then connect the actionaddShapeAction toon_Action_triggered() ,using:
connect(addShapeAction,SIGNAL(triggered(bool)),this,SLOT(on_Action_triggered()))
But I got some errors when building the code.
enter image description here
such as:
C:\Qt\Qt5.10.1\5.10.1\msvc2015\include\QtCore\qobject.h:320: error: C2338: Signal and slot arguments are not compatible.
How to solve this problem?
Is there any better way to build a toolbar of plugins?
Here is the code of shapeplugininterface.h
#ifndef SHAPEPLUGININTERFACE_H
#define SHAPEPLUGININTERFACE_H
#include <QObject>
#include <QString>
#include <QtWidgets/QMainWindow>
class ShapePluginInterface{
public:
virtual ~ShapePluginInterface(){}
virtual QString description() = 0;
virtual void generateShape(QString shapeType) = 0;
virtual void Initialize(QMainWindow* window);
};
#define SHAPEPLUGININTERFACE_IID "com.geolike.shapeplugininterface"
Q_DECLARE_INTERFACE(ShapePluginInterface, SHAPEPLUGININTERFACE_IID)
#endif // SHAPEPLUGININTERFACE_H
And here is the code of basic_shape_plugin.h:
#ifndef BASIC_SHAPE_PLUGIN_H
#define BASIC_SHAPE_PLUGIN_H
#include "basic_shape_plugin_global.h"
#include "shapeplugininterface.h"
#include <QtPlugin>
#include <QDebug>
#include <QtWidgets/QAction>
#include <QtWidgets/QToolBar>
class BASIC_SHAPE_PLUGINSHARED_EXPORT Basic_Shape_Plugin:
public QObject,
public ShapePluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "com.geolike.shapeplugininterface")
Q_INTERFACES(ShapePluginInterface)
public:
Basic_Shape_Plugin();
~Basic_Shape_Plugin();
QString description();
void generateShape(QString shapeType);
void Initialize(QMainWindow* window);
public slots:
void on_Action_triggered();
};
#endif // BASIC_SHAPE_PLUGIN_H
basic_shape_plugin.cpp files:
#include "basic_shape_plugin.h"
Basic_Shape_Plugin::Basic_Shape_Plugin(){}
Basic_Shape_Plugin::~Basic_Shape_Plugin(){}
QString Basic_Shape_Plugin::description()
{
return "This is a plugin to generate shapes.";
}
void Basic_Shape_Plugin::generateShape(QString shapeType)
{
qDebug() << shapeType;
}
void Basic_Shape_Plugin::on_Action_triggered(){
this->generateShape("Action Triggered!");
}
void Basic_Shape_Plugin::Initialize(QMainWindow *window)
{
QAction* addShapeAction = new QAction(window);
connect(addShapeAction,SIGNAL(triggered(bool)),this,SLOT(on_Action_triggered()));
QToolBar* toolBar = new QToolBar;
toolBar->addAction("Shapes",addShapeAction);
window->addToolBar(toolBar);
}
The addAction method signature that you're attempting to use doesn't do what you think it does.
There are two ways to fix the code. Ideally, you should let addAction provide you with an action - that's what that whole convenience API was designed to do:
void Basic_Shape_Plugin::Initialize(QMainWindow *window)
{
auto *toolBar = new QToolBar;
auto *addShapeAction = toolBar->addAction("Shapes");
connect(addShapeAction, &QAction::triggered, this, &Basic_Shape_Plugin::on_Action_triggered);
window->addToolBar(toolBar);
}
Alternatively, you can create the action with the desired text yourself:
void Basic_Shape_Plugin::Initialize(QMainWindow *window)
{
auto *addShapeAction = new QAction("Shapes", window);
connect(addShapeAction, &QAction::triggered, this, &Basic_Shape_Plugin::on_Action_triggered);
auto *toolBar = new QToolBar;
toolBar->addAction(addShapeAction);
window->addToolBar(toolBar);
}
The parentage of the action doesn't matter much - whether you create it as a child of window, or the QToolBar::addAction creates it as the parent of toolBar.

Cannot Access the Qt UI from an external cpp file

Im trying to make a program an in that program I want to press a button that processes some text in another cpp file and appends my QTextEdit. I basically as a test just setup my button to run a function in the other file and also in when the program starts. When it starts it properly prints to the Text Edit as well as my console but when I press my button it only prints to the console and not to my TextEdit. For the function that appends the text in my TextEdit and prints to the console, I made it a public slot so I could access it from my other file.
This is my quiz.cpp
#include <iostream>
#include "quiz.h"
#include "ui_quiz.h"
#include "test.h"
Quiz::Quiz(QWidget *parent) : QMainWindow(parent), ui(new Ui::Quiz) {
ui->setupUi(this);
setText();
}
Quiz::~Quiz() {
delete ui;
}
void Quiz::on_actionQuit_triggered() {
QCoreApplication::quit();
}
void Quiz::on_pushButton_clicked() {
run();
}
void Quiz::setText() {
ui->console->append("Hello");
std::cout << "Hello world!" << std::endl;
}
This is its header:
#ifndef QUIZ_H
#define QUIZ_H
#include <QMainWindow>
namespace Ui {
class Quiz;
}
class Quiz : public QMainWindow
{
Q_OBJECT
public:
explicit Quiz(QWidget *parent = 0);
~Quiz();
public slots:
void setText();
private slots:
void on_actionQuit_triggered();
void on_pushButton_clicked();
private:
Ui::Quiz *ui;
};
#endif // QUIZ_H
This is my test.cpp:
#include "quiz.h"
#include "test.h"
#include "ui_quiz.h"
void run() {
Quiz* quiz = new Quiz();
quiz->setText();
}
and its header:
#ifndef TEST_H
#define TEST_H
#endif // TEST_H
void run();
What am I doing wrong? Why can I not access the ui but the rest of the function runs?
you can access UI only from Main thread.
you can use signal-slot to do that.
write your slot in main. and emit your signal from second class.
connect signal-slot in constructor main.
second class .h file:
void updateUI(QString str);
second class .cpp file:
emit updateUI("some text");
main class .h file:
void updateUI(QString str);
main class .cpp file(implementation):
void Main::updateUI(QString str)
{
// change ui here
}
main class .cpp file (in constructor):
connect(secondobj, &secondclass::updateUI, this, &mainclass::updateUI);
In header file of your cpp where you want to use the UI, add the following lines of ui.
##.h file:
class A
{
Public:
Ui::MainWindow *ui;
}
##.cpp file:
ui->label->setText(ui->button->text());

"undefined class" Qt/C++

I recently started programming in C ++ and am having some difficulties in relation to the exchange of data between classes.
I searched many tutorials and examples, but none worked. I finally decided to ask for help because I do not know what do ...
PS: I want to call keyPressEvent function from my B (solEditor) class
thanks.
addons/soleditor.h (class)
#include <Qsci/qsciscintilla.h>
#include <QWidget>
#include <QKeyEvent>
class Editor; // main class
class solEditor : public QsciScintilla
{
public:
explicit solEditor(QWidget *parent = 0);
Editor editor; // error <<
protected:
void keyPressEvent(QKeyEvent *e);
};
editor.h (main window)
#include <QMainWindow>
#include "about.h"
#include "data.h"
#include "addons/codeeditor.h"
#include "addons/highlighter.h"
#include "addons/soleditor.h"
#include "plugins/headergenerator.h"
#include "plugins/updatescreen.h"
namespace Ui {
class Editor;
}
class solEditor;
class Editor : public QMainWindow
{
Q_OBJECT
solEditor *sE;
public:
QsciScintilla* ce;
Highlighter *Hl;
solEditor *e;
Ui::Editor *ui;
explicit Editor(QWidget *parent = 0);
~Editor();
public slots:
void on_KeyPress(QKeyEvent *e);
};
Error:
SOLEditor\addons\soleditor.h:14: error: C2079: 'solEditor::editor' uses undefined class 'Editor'
You are using a forward declaration
class Editor; // main class
with a local instance of that class
Editor editor; // error <<
Unfortunately, that is not possible, as in this case the compiler needs to know the full details of the Editor class.
There are two possible solutions:
Make the member a pointer: Editor* editor
Use an #include instead of a forward declaration.
If you want to make your code flexible, you could do it like this:
class solEditor : public QsciScintilla
{
public:
explicit solEditor(Editor* editor, QWidget* parent = 0);
inline Editor* editor() const { return _editor; }
private:
Editor* _editor;
}
and in the cpp file:
solEditor::solEditor(Editor* editor, QWidget* parent)
// TODO: call parent constructor
{
_editor = editor;
}
solEditor::~solEditor()
{
_editor = NULL;
}
You can then create a solEditor instance like this:
QWidget* optionalParentWidget = GetParentWidgetFromSomewhere();
Editor* editor = GetEditorInstanceFromSomewhere(); // or create it yourself
solEditor* myEditor = new solEditor(editor, optionalParentWidget);
(As a side node, classes in C++ usually start with a capital letter: QWidget, Editor, SolEditor. That makes it easier to spot if something is a class, a function or a variable).
About the key press event: If you want one class to handle certain events of another class, it's best to use the eventFilter mechanism:
http://qt-project.org/doc/qt-5/qobject.html#installEventFilter