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.
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!!!
Following along Threaded Fortune Server Example I've created a similar server that receives json object from clients and it can handle around 3330 clients simultaneously without any issue.
If I increase the number of clients to 3400, I get:
CreateWindow() for QEventDispatcherWin32 internal window failed (The current process has used all of its system allowance of handles for Window Manager objects.)
Qt: INTERNAL ERROR: failed to install GetMessage hook: 1158, The current process has used all of its system allowance of handles for Window Manager objects.
How can I increase number of threads?
EDIT
Instead of FortuneThread I have ClientThread like this:
class ClientThread : public QThread
{
Q_OBJECT
public:
explicit ClientThread(qintptr socketDescriptor);
void run() override;
signals:
void readyRemove();
private:
qintptr socketDescriptor;
};
and in run() I am creating client:
void ClientThread::run()
{
Client c(socketDescriptor);
emit readyRemove();
}
and the Client is as usual:
class Client : public QTcpSocket
{
Q_OBJECT
public:
explicit Client(qintptr descriptor);
public slots:
void onReadyRead();
void onError(QTcpSocket::SocketError error);
};
and implemented as:
Client::Client(qintptr descriptor)
{
connect(this, &Client::readyRead, this, &Client::onReadyRead);
connect(this, static_cast<void (Client::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), this, &Client::onError);
setSocketDescriptor(descriptor);
waitForDisconnected();
}
void Client::onReadyRead()
{
QVariantMap map = QJsonDocument::fromJson(readAll()).object().toVariantMap();
qDebug() << map["Name"].toString() << map["Age"].toInt();
}
void Client::onError(SocketError error)
{
if(state() == ConnectedState && error == SocketTimeoutError)
waitForDisconnected();
}
Ofcourse, onReadyRead() can be problematic in this way. Server class takes care of ClientThread. It stores each client thread in a QVector and removes it when disconnected from host and here is its header:
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(qint16 port, QObject *parent = 0);
~Server();
protected:
void incomingConnection(qintptr descriptor) override;
public slots:
void removeClient();
private:
QVector<ClientThread*> clients;
};
and incomingConnection and removeClient do these:
void Server::incomingConnection(qintptr descriptor)
{
ClientThread *thread = new ClientThread(descriptor);
connect(thread, &ClientThread::readyRemove, this, &Server::removeClient);
thread->start();
clients.push_back(thread);
}
void Server::removeClient()
{
ClientThread *thread = (ClientThread*)sender();
thread->quit();
thread->deleteLater();
clients.removeOne(thread);
}
To test the Server application I've used the following Console application:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVector<QTcpSocket*> clients;
for(int i = 0; i < 3300; i++){
QTcpSocket *sock = new QTcpSocket();
sock->connectToHost("127.0.0.1", 2000);
sock->waitForConnected();
clients.push_back(sock);
}
QJsonObject obj;
obj["Name"] = QString("TestName");
obj["Age"] = 1;
QJsonDocument doc(obj);
foreach (QTcpSocket *s, clients) {
s->write(doc.toJson());
s->flush();
}
foreach (QTcpSocket *s, clients) {
s->close();
s->deleteLater();
}
}
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);
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 &);
};
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();
}