I use a RaspberryPi and Qt for my Qt for my embedded Project
I have read about QThread. I tested QThread and it is working very fine.
I want to control some GPIO pins in my Thread, but this doesn't work
My GPIO pins are working, I have tested it.
Here my Code:
class referenz_thread:public QThread
{
Q_OBJECT
public:
bool x_isRef;
bool y_isRef;
void run()
{
x_isRef = false;
y_isRef = false;
digitalWrite(x_treiber,1);
digitalWrite(y_treiber,1);
digitalWrite(x_richtung,0);
digitalWrite(y_richtung,1);
while(1)
{
if(digitalRead(x_end) == 0)
{
digitalWrite(x_treiber,0);
x_isRef = true;
}
if(digitalRead(y_end) == 0)
{
digitalWrite(y_treiber,0);
y_isRef = true;
}
if((x_isRef == true) && (y_isRef == true))
{
break;
}
digitalWrite(x_v,1);
digitalWrite(y_v,1);
delay(1);
digitalWrite(x_v,0);
delay(1);
digitalWrite(x_v,1);
delay(1);
digitalWrite(x_v,0);
digitalWrite(y_v,0);
delay(1);
}
}
public slots:
};
This is in MainWindow.cpp
referenz_thread *ref_thread = new referenz_thread();
connect(ui->btn_ref,SIGNAL(clicked()),ref_thread,SLOT(start()));
I have wiringPiSetup already executed in my MainThread.
Related
So been trying my exit and play button work but they do not react the way I want them too for some strange reason. When I change one to else if and if only statement they either both exit or change them again and both start the game. They act like they are the same button and not individuals despite how they are selected and pressed.
Here is my header file:
#pragma once
#include <memory>
#include "State.h"
#include "Game.h"
#include <SFML/Graphics.hpp>
class MainMenu : public Engine::State
{
public:
enum behavior
{
HOVERED, NORMAL
};
private:
std::shared_ptr<Context> context;
sf::Text gameTitle;
sf::Text playButton;
sf::Text exitButton;
void hover(sf::RenderWindow& window, sf::Event event);
//checking certain conditions if it is true or false
bool isPlayButtonSelected;
bool isPlayButtonPressed;
bool isExitButtonSelected;
bool isExitButtonPressed;
public:
MainMenu(std::shared_ptr<Context>& context);
~MainMenu();
void Init() override;
void ProcessInput() override;
void Update(sf::Time deltaTime) override;
void Draw() override;
};
Here is the cpp file:
#include "MainMenu.h"
#include "GamePlay.h"
MainMenu::MainMenu(std::shared_ptr<Context> &context) : context(context),
isPlayButtonSelected(true), isPlayButtonPressed(false), isExitButtonPressed(false),
isExitButtonSelected(false)
{
}
MainMenu::~MainMenu()
{
}
void MainMenu::Init()
{
//our assets being put here that we stored and implement it
context -> assets ->AddFont(MainFont, "Assets/Asdonuts.ttf");
//Titlle screen name of the game code
gameTitle.setFont(context->assets->GetFont(MainFont));
gameTitle.setString("Final Game Project");
gameTitle.setOrigin(gameTitle.getGlobalBounds().width/2,
gameTitle.getGlobalBounds().height/2);
gameTitle.setPosition(context->window->getSize().x/3.5,
context->window->getSize().y/2 - 450.f);
gameTitle.setCharacterSize(150);
//This is the code for the play button
playButton.setFont(context->assets->GetFont(MainFont));
playButton.setString("Start");
playButton.setOrigin(playButton.getGlobalBounds().width/2,
playButton.getGlobalBounds().height/2);
playButton.setPosition(context->window->getSize().x/2,
context->window->getSize().y/2 - 50.f);
playButton.setCharacterSize(70);
//This is the code for the exit button
exitButton.setFont(context->assets->GetFont(MainFont));
exitButton.setString("Exit");
exitButton.setOrigin(exitButton.getGlobalBounds().width/2,
exitButton.getGlobalBounds().height/2);
exitButton.setPosition(context->window->getSize().x/2,
context->window->getSize().y/2 + 50.f);
exitButton.setCharacterSize(70);
}
//this function is when the screen is running and reads user input when pressing
//the buttons and things that happend when they press certain buttons
//while also keeping the window open till they choose to close it on the x button
//on the top right corner
void MainMenu::ProcessInput()
{
sf::Event event;
while(context->window->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
context->window->close();
}
else if(event.type == sf::Event::KeyPressed)
{
switch(event.key.code)
{
case sf::Keyboard::Up:
{
if(!isPlayButtonSelected)
{
isPlayButtonSelected = true;
isExitButtonSelected = false;
}
break;
}
case sf::Keyboard::W:
{
if(!isPlayButtonSelected)
{
isPlayButtonSelected = true;
isExitButtonSelected = false;
}
break;
}
case sf::Keyboard::Down:
{
if(!isExitButtonSelected)
{
isPlayButtonSelected = false;
isExitButtonSelected = true;
}
break;
}
case sf::Keyboard::S:
{
if(!isExitButtonSelected)
{
isPlayButtonSelected = false;
isExitButtonSelected = true;
}
break;
}
case sf::Keyboard::Enter:
{
isPlayButtonPressed = false;
isExitButtonPressed = false;
if(!isPlayButtonPressed)
{
isPlayButtonPressed = true;
}
else if(!isExitButtonPressed)
{
isExitButtonPressed = true;
}
break;
}
default:
{
break;
}
}
}
}
}
void MainMenu::Update(sf::Time deltaTime)
{
//conditions for the menu fonts and all
//so like we know who is highlighted and not highlighted for the user to understand
//what is going on and what selection they are hovering on
if(isPlayButtonSelected)
{
playButton.setFillColor(sf::Color::Blue);
exitButton.setFillColor(sf::Color::White);
}
else
{
exitButton.setFillColor(sf::Color::Blue);
playButton.setFillColor(sf::Color::White);
}
//important thing for our main menu
//if Play button is pressed the game starts
if(isPlayButtonPressed)
{
context->states->Add(std::make_unique<GamePlay>(context), true);
}
//if the exit button is pressed, the game SHOULD exit
else if(isExitButtonPressed)
{
context->window->close();
}
}
void MainMenu::Draw()
{
//draw everything that needs to be display in the main menu
context->window->clear(sf::Color(53, 189, 164));
context->window->draw(gameTitle);
context->window->draw(playButton);
context->window->draw(exitButton);
context->window->display();
}
So an example what I mean is this one both buttons start the game but if I change it to this:
case sf::Keyboard::Enter:
{
isPlayButtonPressed = false;
isExitButtonPressed = false;
if(!isPlayButtonPressed)
{
isPlayButtonPressed = true;
}
if(!isExitButtonPressed)
{
isExitButtonPressed = true;
}
break;
}
if(isPlayButtonPressed)
{
context->states->Add(std::make_unique<GamePlay>(context), true);
}
//if the exit button is pressed, the game SHOULD exit
if(isExitButtonPressed)
{
context->window->close();
}
They will both exit and not start the game. I have been messing around one if and the other else or both as if statements. Despite the changes and testing none of the buttons act individually and act how they are supposed to act. So curious how to fix this issue?
Unsure if I should provide all my headers and cpp files for more context.
I am not really sure if I understand well your problem, but in your example it seems like isExitButtonPressed is always true at the end.
You're setting it to false at the begining and then setting it to true in the if statement which has always a fulfilled condition giving the fact that you set isExitButtonPressed to false beforehand !
I'm junior programmer
recently, I have implemented grabbing of Image using Halcon library.
when I press live button, Timer start to grab image. it works but main screen freezes to the timer cycle.
so, I am improving performance grabbing of Image using Thread
first I implemented thread like this
[ImageUpdateWorker.h]
class ImageUpdateWorker : public QObject
{
Q_OBJECT
public:
explicit ImageUpdateWorker(QObject* parent = 0, QString strThreadName = "ImageUpdateWorker");
~ImageUpdateWorker();
signals:
void finished();
void grab();
public slots:
void run();
private:
bool m_bStop{ false };
};
[ImageUpdateWorker.cpp]
ImageUpdateWorker::ImageUpdateWorker(QObject* parent, QString strThreadName)
: QObject(parent)
{
setObjectName(strThreadName);
}
ImageUpdateWorker::~ImageUpdateWorker()
{
}
void ImageUpdateWorker::run()
{
while (m_bStop == false)
{
emit grab();
}
emit finished();
}
second I implemented inherited QWidget UI Widget with output Screen like this
m_pThread = new QThread();
m_pUpdateWorker = new ImageUpdateWorker(nullptr, strName);
m_pUpdateWorker->moveToThread(m_pThread); // UpdateWorker move to Thread
connect(m_pThread, SIGNAL(started()), m_pUpdateWorker, SLOT(run()));
connect(m_pThread, SIGNAL(finished()), m_pThread, SLOT(deleteLater()));
connect(m_pUpdateWorker, SIGNAL(finished()), m_pThread, SLOT(quit()));
connect(m_pUpdateWorker, SIGNAL(finished()), m_pUpdateWorker, SLOT(deleteLater()));
connect(m_pUpdateWorker, SIGNAL(grab()), this, SLOT(onGrab()));
when I call "m_pThread->start();" screen starts to blokcing :(
If you have any advice or information, I would appreciate it. thank you for reading.
Use m_pImageUpdateThread->moveToThread(m_pThread);
I don't know in QT.
I sent you the code I used in C#.
Mainly you must use the delegates if you don't want to freeze the GUI.
hdisplay is the object HalconDotNet:HWindowControlWPF.
camera is a class where I define the camera parameters.
inside camera.Grab there is the code:
HOperatorSet.GrabImage(out ho_Image, _AcqHandle);
h_Image = new HImage(ho_Image);
At the initialization there is the code:
// Initialise the delegate
updateLiveDelegate = new UpdateLiveDelegate(this.UpdateLive);
HImage ho_Image = new HImage();
Here the code I use:
// ==================
// LIVE
// ==================
bool stopLive = true;
// Declare the thread
private Thread liveThread = null;
// Declare a delegate used to communicate with the UI thread
private delegate void UpdateLiveDelegate();
private UpdateLiveDelegate updateLiveDelegate = null;
private void btnLive_Click(object sender, RoutedEventArgs e)
{
try
{
stopLive = !stopLive;
// if stopLive = false, live camera is activated
if (!stopLive)
{
// Launch the thread
liveThread = new Thread(new ThreadStart(Live));
liveThread.Start();
}
}
catch (Exception ex)
{
// Error
}
}
private void Live()
{
try
{
while (stopLive == false)
{
if (camera.Grab(out ho_Image))
{
// Show progress
Dispatcher.Invoke(this.updateLiveDelegate);
}
else
{
// No grab
stopLive = true;
}
}
// here stopLive is true
}
catch (Exception ex)
{
// Error
}
}
private void UpdateLive()
{
try
{
int imageHeight;
int imageWidth;
string imageType;
ho_Image.GetImagePointer1(out imageType, out imageWidth, out imageHeight);
hDisplay.HalconWindow.SetPart(0, 0, imageHeight - 1, imageWidth - 1);
// display
hDisplay.HalconWindow.DispImage(ho_Image);
}
catch (Exception ex)
{
// Error
}
}
How do I send data over sockets in C++ in QT ?
Here's my attempt, it does not work, regards
the server side that sends a file
void MainWindow::on_pushButton_clicked()
{
QString url("127.0.0.1");
sock.bind(QHostAddress(url), 1440);
sock.connectToHost("127.0.0.1", 1440);
sock.write("Coucou");
sock.close();
}
and the client that receives the file
void MainWindowClient::checker() {
csock.connectToHost("127.0.0.1", 1440);
char *datas;
sock.read(datas, 10000000);
ui->label->setText(datas);
csock.close();
}
When i run the program, it does not display "Coucou" as the label set on the client, why ?
Are you forced to use Sockets or can you use Websockets too? If so, Qt has a wonderful way to deal with Websockets and Signals / Slots.
For example, here's what I use for my Remote Control App on my smartphone to control my Music Player (the code has been truncated). But the server can also send commands to synchronize the UI on the smartphone.
The client:
RemoteClient::RemoteClient(CoverProvider *coverProvider, QObject *parent)
: QObject(parent)
, _socket(new QWebSocket("remote", QWebSocketProtocol::VersionLatest, this))
{
connect(_socket, &QWebSocket::textMessageReceived, this, &RemoteClient::processTextMessage);
}
/// Direction: Remote App is receiving orders from Server
void RemoteClient::processTextMessage(const QString &message)
{
if (message.isEmpty()) {
return;
}
QStringList list = message.split(QChar::Null);
if (list.size() <= 1) {
return;
}
int command = list.first().toInt();
switch (command) {
case CMD_Playback:
// Nothing
break;
case CMD_State: {
QMediaPlayer::State state = (QMediaPlayer::State) list.at(1).toInt();
if (state == QMediaPlayer::PlayingState) {
emit playing();
} else if (state == QMediaPlayer::PausedState) {
emit paused();
} else {
emit stopped();
}
break;
}
case CMD_Track:
/// etc.
break;
}
/// etc.
default:
break;
}
}
/// Direction: Remote App is sending orders to Server
void RemoteClient::setVolume(qreal v)
{
QStringList args = { QString::number(CMD_Volume), QString::number(v) };
_socket->sendTextMessage(args.join(QChar::Null));
}
The server:
void RemoteControl::startServer()
{
auto b = _webSocketServer->listen(QHostAddress::Any, _port);
qDebug() << Q_FUNC_INFO << b;
}
void RemoteControl::initializeConnection()
{
/// ...
connect(mediaPlayer(), &MediaPlayer::volumeChanged, this, &RemoteControl::sendVolume);
}
/// Direction: Server to updating Remote App
void RemoteControl::sendVolume(qreal volume)
{
QStringList args = { QString::number(CMD_Volume), QString::number(volume) };
_webSocket->sendTextMessage(args.join(QChar::Null));
}
/// Direction: Remote App is sending command to Server
void RemoteControl::decodeResponseFromClient(const QString &message)
{
if (message.isEmpty()) {
return;
}
QStringList args = message.split(QChar::Null);
if (args.count() < 2) {
return;
}
int command = args.first().toInt();
switch (command) {
case CMD_Volume: {
qreal volume = args.at(1).toFloat();
_currentView->mediaPlayerControl()->mediaPlayer()->setVolume(volume);
break;
}
/// etc.
}
}
I'm writing a simple server that pass some data to javascript by QWebSocketServer (basicly the same as qt doc...).
And, please take a look at here:
void DebuggerServer::onNewConnection() {
puts("C");
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &DebuggerServer::processMessage);
connect(pSocket, &QWebSocket::disconnected, this, &DebuggerServer::socketDisconnected);
printf("onNewConnection");
m_clients << pSocket;
}
I try to puts("C"); here, but I get nothing.
In my browser (latest version of chrome), If I send a request to the server, i will get some information like socket is connecting.
I've tried these things: closing firewall, changing port, changing browser, changing compile mode.
I'm not sure if this involve this issue, I'm compiling these code by msvc15 and manully moc headers.
This code is inject into other application by loadlibrary.
Full source code for the server is followed...
Server.cpp
#include "Server.h"
#include "Inspector.h"
#include "Server.moc"
#include <QtCore/QCoreApplication>
const int port = 5642;
DebuggerServer *server;
void StartServer() {
server = new DebuggerServer(port);
}
QT_USE_NAMESPACE
DebuggerServer::DebuggerServer(quint16 port, QObject *parent) :
QObject(parent),
m_pWebSocketServer(Q_NULLPTR),
m_clients()
{
m_pWebSocketServer = new QWebSocketServer(QStringLiteral("mvInspector"),
QWebSocketServer::NonSecureMode,
this);
puts("A");
if (m_pWebSocketServer->listen(QHostAddress::Any, port))
{
puts("B");
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &DebuggerServer::onNewConnection);
}
}
DebuggerServer::~DebuggerServer() {
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
template<class T>
QString toStr(QList<T> y) {
QString rst;
for (T x : y)
rst += "\n" + QString(x);
return rst;
}
#define ASSERT_N(x) if (frame.length() != x) rst = "ERRON, wrong number of arguments."; else
void DebuggerServer::processMessage(QString message) {
QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
QStringList frame = message.split("\n");
QString rst;
rst += frame[0];
if (frame[0] == "getRootWindows") {
ASSERT_N(1)
rst += toStr(getRootWindows());
}
if (frame[0] == "getChildren") {
ASSERT_N(2)
rst += toStr(getChildren(frame[1].toInt()));
}
if (frame[0] == "getPropertyName") {
ASSERT_N(2)
rst += toStr(getPropertyName(frame[1].toInt()));
}
if (frame[0] == "getProperty") {
ASSERT_N(3)
rst += getProperty(frame[1].toInt(), frame[2].toStdString().c_str()).toBase64();
}
if (frame[0] == "getClassname") {
ASSERT_N(2)
rst += getClassname(frame[1].toInt());
}
if (frame[0] == "getClassname") {
ASSERT_N(2)
rst += getObjectname(frame[1].toInt());
}
printf(rst.toStdString().c_str());
pSender->sendTextMessage(rst);
}
void DebuggerServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient) {
m_clients.removeAll(pClient);
pClient->deleteLater();
}
printf("socketDisconnected");
}
void DebuggerServer::onNewConnection() {
puts("C");
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &DebuggerServer::processMessage);
connect(pSocket, &QWebSocket::disconnected, this, &DebuggerServer::socketDisconnected);
printf("onNewConnection");
m_clients << pSocket;
}
Server.h
#pragma once
#include <QtCore/qobject.h>
#include <QtWebSockets/qwebsocketserver>
#include <QtWebSockets/QWebSocket>
void StartServer();
class DebuggerServer : public QObject {
Q_OBJECT
public:
explicit DebuggerServer(quint16 port, QObject *parent = Q_NULLPTR);
virtual ~DebuggerServer();
private Q_SLOTS:
void onNewConnection();
void processMessage(QString message);
void socketDisconnected();
private:
QWebSocketServer *m_pWebSocketServer;
QList<QWebSocket *> m_clients;
};
DLLMain
#include <Windows.h>
#include "../Server.h"
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
StartServer();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
Finally, it seems to be a bug of Qt 5.4.1 at least on windows 10 (msvc) .
I can make two Qt application connecting by the websocket, but cannot let At application connecting with a normal browser.
So, I use another websocket library and repect the original Qt websocket.
I have a simple application with just one QPlainTextEdit, basically the same as Qt's example here:
http://qt-project.org/doc/qt-5.1/qtwidgets/mainwindows-application.html
When I press Ctrl+Z, it calls undo. When I press Ctrl+A, it selects all text. This is ok.
But when I press Ctrl+E or Ctrl+R, which are not defined in the menu, the characters "e" and "r" will appear in the QSimpleTextEdit.
How do I prevent this? How to "filter" keypresses which have been defined as menu shortcuts and keep them working, and "prevent" those keypresses not defined as menu shortcuts from appearing in the edit?
There are 2 options:
1) Create a subclass and reimplement keyPressEvent()
2) Create an eventFilter and use installEventFilter() (see http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#installEventFilter)
You can use the following code:
CSimpleEdit.h
#include <QPlainTextEdit>
class CSimpleEdit: public QPlainTextEdit
{ Q_OBJECT
public:
explicit CSimpleEdit(QWidget* parent = 0);
~ CSimpleEdit();
protected:
bool eventFilter(QObject* obj, QEvent* event);
};
CSimpleEdit.cpp
CSimpleEdit::CSimpleEdit(QWidget* parent)
: QPlainTextEdit(parent)
{ installEventFilter(this); }
CSimpleEdit::~CSimpleEdit()
{ removeEventFilter(this); }
bool CSimpleEdit::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->modifiers() != Qt::NoModifier &&
!keyEvent->modifiers().testFlag(Qt::ShiftModifier))
{ bool bMatch = false;
for (int i = QKeySequence::HelpContents; i < QKeySequence::Deselect; i++)
{ bMatch = keyEvent->matches((QKeySequence::StandardKey) i);
if (bMatch) break;
}
/*You can also set bMatch to true by checking you application
*actions list -> QWidget::actions(). */
if (!bMatch) return true;
}
}
else if (event->type() == QEvent::KeyRelease)
{ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->modifiers() != Qt::NoModifier &&
!keyEvent->modifiers().testFlag(Qt::ShiftModifier))
{ bool bMatch = false;
for (int i = QKeySequence::HelpContents; i < QKeySequence::Deselect; i++)
{ bMatch = keyEvent->matches((QKeySequence::StandardKey) i);
if (bMatch) break;
}
if (!bMatch) return true;
}
}
return QObject::eventFilter(obj, event);
}