How can I make signal and slot of lineEdit which is declare in another class ?
LineEdit is declared in Peakdetechtion class and i want to make signal and slot in peaksettingform so how can I do this?
the QLineEdit either has to be accessible from the outside (public or get) or you have to forward the signal you are interested in.
accessible version (incomplete and very dirty)
class Peakdetechtion { // horrible name
public:
QLineEdit* getLineEdit() { return m_lineEdit; } // don't do it
private:
QLineEdit* m_lineEdit;
};
class Peaksettingform : public QObject { //horrible name
Q_OBJECT
public:
Peaksettingform(Peakdetechtion *p, QObject *parent = 0)
: QObject(parent) {
// you can do this from outside and replace 'this' with a pointer to a Peaksettingform object
connect(p->getLineEdit(), SIGNAL(textChanged(const QString &)), this, SLOT(handleText(const QString &)));
}
public slots:
void handleText(const QString &);
};
signal forwarding
class Peakdetechtion : public QObject { // horrible name
Q_OBJECT
public:
Peakdetechtion() {
m_lineEdit = new QLineEdit(); // should have a parent but i am lazy
connect(m_lineEdit, SIGNAL(textChanged(const QString&)), this, SIGNAL(leTextChanged(const QString&)));
}
signals:
void leTextChanged(const QString &);
private:
QLineEdit* m_lineEdit;
};
class Peaksettingform : public QObject { //horrible name
Q_OBJECT
public:
Peaksettingform(Peakdetechtion *p, QObject *parent = 0)
: QObject(parent) {
// you can do this from outside and replace 'this' with a pointer to a Peaksettingform object
connect(p, SIGNAL(leTextChanged(const QString &)), this, SLOT(handleText(const QString &)));
}
public slots:
void handleText(const QString &);
};
Related
I'm working in visual studio and I keep getting these error.
E0322 object of abstract class type "GameState" is not allowed
Error C2259 'GameState': cannot instantiate abstract class
Error C2665 'GameState::GameState': no overloaded function could convert all the argument types
I understand that I need to override the functions from the state class in the gamestate class and I thought that I did that but apparently not. Can anyone see where I am going wrong?
code:
state.h:
class State {
private:
sf::RenderWindow* window;
std::vector<sf::Texture> textures;
public:
State(sf::RenderWindow* window);
virtual ~State(); //this means that all child classes must define these
virtual void endState() = 0;
virtual void update(const float& dt) = 0;
virtual void render(sf::RenderTarget* target = nullptr) = 0; };
state.cpp
#include "State.h"
State::State(sf::RenderWindow* window)
{
this->State::~State(){}
gamestate.h
#include "State.h"
class GameState :
public State
{
private:
public:
GameState(sf::RenderWindow\* window);
virtual \~GameState();
void endState();
void update(const float& dt);
void render(sf::RenderTarget\* target);
};
Gamestate.cpp
#include "GameState.h"
GameState::GameState(sf::RenderWindow\* window)
: State(window){}
GameState::\~GameState(){}
void GameState::endState(){}
void GameState::update(const float& dt){}
void GameState::render(sf::RenderTarget* target = nullptr){}
game.h
#include "GameState.h"
class Game
{
//variables
sf::RenderWindow* window;
sf::Event sfEvent;
sf::Clock dtClock; //frame tracker
float dt; //deltatime
std::stack<State*> states;
//initialization
void initWindow();
void initStates();
public:
Game();
virtual \~Game();
void updateDeltaTime();
void updateSFMLEvents();
void update();
void render();
void run();
};
game.cpp
//I will be leaving out all the unnecessary code to save space
#include "Game.h"
void Game::initStates() {
this->states.push(new GameState(this->window)); //this is where the problem is
}
hovering over GameState says that State::endState()/render()/update() has no override
please help!!!
I'm trying to update gui label with an other thread information (QString).
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public Q_SLOTS:
void sl_appendInfo(QString p_text);
private:
Ui::MainWindow *ui;
QFuture<void> m_thread;
QFuture<void> m_engine;
engine* m_object;
};
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
m_object = new engine();
qRegisterMetaType<QString>();
bool success = connect(this->m_object, SIGNAL(engine::sig_appendInfo(QString)), this, SLOT(sl_appendInfo(QString)), Qt::QueuedConnection);
if(!success)
{
qDebug("success failed");
}
m_engine = QtConcurrent::run(this->m_object, &engine::eventLoop);
}
//slot declaration in mainwindow.cpp
void MainWindow::sl_appendInfo(QString p_text)
{
ui->label->setText(p_text.toLocal8Bit().constData());
}
class engine : public QObject
{
Q_OBJECT
public:
engine();
~engine();
void eventLoop();
Q_SIGNALS:
void sig_exitengine(void);
void sig_appendInfo(QString p_text);
};
void engine::eventLoop()
{
int state = false;
while(true)
{
state = getNextEvent(m_event);
if (state == true)
{
sig_appendInfo("information for gui: we handled a new event !");
state=false;
}
QThread::msleep(1000);
}
}
Now I use this link : My signal / slot connection does not work to build my own code but it didn't work, the connection failed... Can I have some help please?
Thank you
Your connect syntax is wrong. You shouldn't include the class name in the SIGNAL macro. If you use the old syntax, it should be:
bool success = connect(m_object, SIGNAL(sig_appendInfo(QString)), this, SLOT(sl_appendInfo(QString)), Qt::QueuedConnection);
Or if you want to use the new syntax:
bool success = connect(m_object, &engine::sig_appendInfo, this, &MainWindow::sl_appendInfo, Qt::QueuedConnection);
The mainwindow.cpp:
#include "ui_mainwindow.h"
#include <QtCore>
/* ****** Thread part ****** */
myThread::myThread(QObject *parent)
: QThread(parent)
{
}
void myThread::run()
{
while(1){
qDebug("thread one----------");
emit threadSignal1();
usleep(100000);
}
exec();
}
myThread2::myThread2(QObject *parent)
: QThread(parent)
{
}
void myThread2::run()
{
while(1){
qDebug("thread two");
emit threadSignal2();
usleep(100000);
}
exec();
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
onethread = new myThread(this);
onethread->start(QThread::NormalPriority);
twothread = new myThread2(this);
twothread->start(QThread::NormalPriority);
connect(onethread, SIGNAL(onethread->threadSignal1()),
this, SLOT(mySlot1()));
connect(twothread, SIGNAL(threadSignal2()),
this, SLOT(mySlot2()),Qt::QueuedConnection);
}
void MainWindow::mySlot1()
{
ui->textEdit1->append("This is thread1");
}
void MainWindow::mySlot2()
{
ui->textEdit1->append("This is thread2");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->textEdit1->append("textEdit1");
ui->textEdit2->append("textEdit2");
}
The mainwindow.h:
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
namespace Ui {
class MainWindow;
}
class myThread : public QThread
{
Q_OBJECT
public:
myThread(QObject *parent = 0);
void run();
signals:
void threadSignal1();
};
class myThread2 : public QThread
{
Q_OBJECT
public:
myThread2(QObject *parent = 0);
void run();
signals:
void threadSignal2();
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void mySlot1();
void mySlot2();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
myThread *onethread;
myThread2 *twothread;
};
#endif // MAINWINDOW_H
Please check the above code. It can give the qDebug output normally while the textEdit1/2 have no any output. And it seems to be a multi-thread signal/slot connect issue. Who can help? Thanks!
You need to define the slots as slots:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void mySlot1();
void mySlot2();
...
Also a few other things. You don't need the exec() call in each of the threads. They are going into an endless loop anyways and would never reach that statement. And, the purpose of exec() is to start an event loop in the thread so that it can receive and process events, like having its own slots. You are just emitting.
Are you sure this connection works?
connect(onethread, SIGNAL(onethread->threadSignal1()),
this, SLOT(mySlot1()));
It should probably be:
connect(onethread, SIGNAL(threadSignal1()),
this, SLOT(mySlot1()));
I believe QueuedConnection will be implied for the connections because they are targeting a slot on an owner in a different thread than the emitter.
I need to start and stop a thread very frequently using push button..I am using Qt. Recently I learned to create a QObject of the worker and move it to the object of the QThread as the correct way of implementing threads in Qt. Following is my implementation...
Worker.h
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
void StopWork();
void StartWork();
bool IsWorkRunning();
signal:
void SignalToObj_mainThreadGUI();
public slots:
void do_Work();
private:
void Sleep();
volatile bool running,stopped;
QMutex mutex;
QWaitCondition waitcondition;
};
Worker.cpp
worker::worker(QObject *parent) :
QObject(parent),stopped(false),running(false)
{
}
void worker::do_Work()
{
running = true;
while(!stopped)
{
emit SignalToObj_mainThreadGUI();
Sleep();
}
}
void worker::Sleep()
{
mutex.lock();
waitcondition.wait(&mutex,10);
mutex.unlock();
}
void worker::StopWork()
{
mutex.lock();
stopped = true;
running = false;
mutex.unlock();
}
void worker::StartWork()
{
mutex.lock();
stopped = false;
running = true;
mutex.unlock();
}
bool worker::IsWorkRunning()
{
return running;
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
private slots:
void on_pushButton_push_to_start_clicked();
void on_pushButton_push_to_stop_clicked();
private:
Ui::MainWindow *ui;
worker *myWorker;
QThread *WorkerThread;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker.moveToThread(WorkerThread);
QObject::connect(WorkerThread,SIGNAL(started()),myWorker,SLOT(do_Work()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_push_to_start_clicked()
{
if(!myWorker.IsWorkRunning())
{
myWorker->StartWork();
WorkerThread->start();
}
}
void MainWindow::on_pushButton_push_to_stop_clicked()
{
if(myWorker.IsWorkRunning())
{
myWorker->StopWork();
WorkerThread->quit();
}
}
Initially the application works fine but after some operations of the push button to turn the working of the thread on and off the following error comes up...
QObject::killTimers(): timers cannot be stopped from another thread
I am quite puzzled at this error...do I need to implement the start/stop functions as signals and slots rather than member functions of the class?
Don't start and stop WorkerThread. Just leave it running. Also, move your StartWork() and StopWork() methods to the public slots section. You really don't need the mutex at all.
Worker.h
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
signal:
void SignalToObj_mainThreadGUI();
void running();
void stopped();
public slots:
void StopWork();
void StartWork();
private slots:
void do_Work();
private:
volatile bool running,stopped;
};
Worker.cpp
worker::worker(QObject *parent) :
QObject(parent), stopped(false), running(false)
{}
void worker::do_Work()
{
emit SignalToObj_mainThreadGUI();
if ( !running || stopped ) return;
// do important work here
// allow the thread's event loop to process other events before doing more "work"
// for instance, your start/stop signals from the MainWindow
QMetaObject::invokeMethod( this, "do_Work", Qt::QueuedConnection );
}
void worker::StopWork()
{
stopped = true;
running = false;
emit stopped();
}
void worker::StartWork()
{
stopped = false;
running = true;
emit running();
do_Work();
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void startWork();
void stopWork();
private slots:
void on_pushButton_push_to_start_clicked();
void on_pushButton_push_to_stop_clicked();
private:
Ui::MainWindow *ui;
worker *myWorker;
QThread *WorkerThread;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker.moveToThread(WorkerThread);
connect( this, SIGNAL(startWork()), myWorker, SLOT(StartWork()) );
connect( this, SIGNAL(stopWork()), myWorker, SLOT(StopWork()) );
}
void MainWindow::on_pushButton_push_to_start_clicked()
{
emit startWork();
}
void MainWindow::on_pushButton_push_to_stop_clicked()
{
emit stopWork();
}
class A : public QObject{
Q_OBJECT
signals:
void a_sig();
public:
A(){ }
public slots:
void begin(){
QObject::connect(&_timer, SIGNAL(timeout()), this, SIGNAL(a_sig()));
_timer.start(1000);
}
private:
QTimer _timer;
};
class B : public QObject{
Q_OBJECT
public:
B(){ value = 0; }
public slots:
void b_slot(){
++value;
QFile file("out.txt");
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
out << value << "\n";
file.close();
}
private:
int value;
};
int main(int argc, char **argv){
QCoreApplication app(argc, argv);
A a;
B b;
QThread aThread;
QThread bThread;
QObject::connect(&aThread, SIGNAL(started()), &a, SLOT(begin()));
QObject::connect(&a, SIGNAL(a_sig()), &b, SLOT(b_slot()));
a.moveToThread(&aThread);
b.moveToThread(&bThread);
aThread.start();
bThread.start();
return app.exec();
}
I'm trying to understand why b_slot() isn't getting called. Can anyone explain what's happening, and why b_slot() isn't getting called?
The problem is the ownership of the _timer member of the A class.
Since you're not explicitly initializing it, it is initialized without a parent object. So the a.moveToThread(&aThread) isn't moving the timer to aThread, and things get confused after that.
Change A's constructor to:
A() : _timer(this) {}
and your b_slot() will get called.
The problem is that while object a is moved to aThread, _timer object still belongs to the original main thread. Try initializing _timer inside begin method like that:
void begin() {
_timer = new QTimer;
QObject::connect(_timer, SIGNAL(timeout()), this, SIGNAL(a_sig()));
_timer->start(1000);
}
private:
QTimer *_timer;