How to propagate keyPressEvent on different qt QMainWindow - events

I have 2 different QMainWindow, the first is the parent of the second. I want press some keys in the children windows and propagate the event in the parent. I create for everyone the function void keyPressEvent(QKeyEvent* event); but when i press key on the children the event is not propagate to the parent. Why?
This is the code...
//Parent class.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QKeyEvent>
#include "test.h"
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void keyPressEvent(QKeyEvent* event);
private:
Ui::MainWindow *ui;
test *form;
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
//Parent class.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
form = new test(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::keyPressEvent(QKeyEvent* event)
{
qDebug() << event->text();
}
void MainWindow::on_pushButton_clicked()
{
form->show();
}
//Children class.h
#ifndef TEST_H
#define TEST_H
#include <QMainWindow>
#include <QKeyEvent>
namespace Ui {
class test;
}
class test : public QMainWindow
{
Q_OBJECT
public:
explicit test(QWidget *parent = 0);
~test();
protected:
void keyPressEvent(QKeyEvent* event);
private:
Ui::test *ui;
};
#endif // TEST_H
//Children class.cpp
#include "test.h"
#include "ui_test.h"
test::test(QWidget *parent) : QMainWindow(parent), ui(new Ui::test)
{
ui->setupUi(this);
}
test::~test()
{
delete ui;
}
void test::keyPressEvent(QKeyEvent* event)
{
qDebug() << event->text();
event->ignore();
}

A QMainWindow is a top-level window and that is usually where event propagation ends. I'm not entirely clear what may be the rule though when a top-level window is parented. By your results, I'll have to assume that it stands.
In any case, you should be able to get the event by defining a filter method in your MainWindow class and installing it on test class. Refer to this documentation.
You also have the option of overriding the event() method of QApplication.

Related

How does Qt control the camera on the mac?

As on Windows it is useless to write, you can't get the camera screen at all.
What should I do?
Do I need to apply for permission?
Where should I put the file Info.plist?
In your Info.plist you should include:
<key>NSCameraUsageDescription</key>
<string>${PRODUCT_NAME} ...a description of why the camera is used by your app...</string>
Here is an example of displaying the camera input.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QCamera>
#include <QCameraInfo>
#include <QCameraViewfinder>
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QCamera *m_camera;
QList<QCameraInfo> m_cameras;
QCameraViewfinder *m_cameraViewFinder;
private:
bool checkCameraAvailability();
private slots:
void setCamera(const QCameraInfo &cameraInfo);
void on_camerSelectBox_currentTextChanged(const QString &arg1);
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow),
m_cameraViewFinder(new QCameraViewfinder)
{
ui->setupUi(this);
// Detect Cameras
m_cameras = QCameraInfo::availableCameras();
for (const QCameraInfo &cameraInfo : m_cameras) {
ui->camerSelectBox->addItem(cameraInfo.description());
}
// Make sure there is at least one camera available, and start with the default camera as preview.
if(checkCameraAvailability()) {
setCamera(QCameraInfo::defaultCamera());
}
}
MainWindow::~MainWindow()
{
delete m_cameraViewFinder;
delete m_camera;
delete ui;
}
void MainWindow::setCamera(const QCameraInfo &cameraInfo)
{
m_camera = new QCamera(cameraInfo);
m_camera->setViewfinder(m_cameraViewFinder);
ui->previewLayout->addWidget(m_cameraViewFinder);
m_camera->start();
}
bool MainWindow::checkCameraAvailability()
{
if (QCameraInfo::availableCameras().count() > 0)
return true;
else
return false;
}
void MainWindow::on_camerSelectBox_currentTextChanged(const QString &arg1)
{
if(checkCameraAvailability()) {
for (const QCameraInfo &cameraInfo : m_cameras) {
if( cameraInfo.description() == arg1 ) {
setCamera(cameraInfo);
}
}
}
}
In you mainwindow.ui you should include:
A layout named previewLayout
A QComboBox named camerSelectBox

Trying to implement Observer Patterns and got Segmentation Fault (pls help) c++

I'm trying to learn c++ so, I try to implement the observer patterns from the book Game Progamming Patterns but I'm always getting Segmentation Fault.
Searching arround I saw that Segmentation fault happens when a program try to access a non allocated memory. So I tried hard to fix it, but I can't. Someone can help me?
Here is my code:
Observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include "EntityAndEvent.h"
#include "Subjects.h"
class Observer
{
private:
Observer* next_;
public:
Observer()
: next_(nullptr)
{}
virtual void onNotify(const Entity& entity, Event::Type event) = 0;
// Other stuff...
friend class Subjects;
};
#endif
Achievements.cpp
#ifndef ACHIEVEMENTS_CPP
#define ACHIEVEMENTS_CPP
#include "Observer.h"
#include <vector>
class Achievements : public Observer
{
public:
enum Type{
FELL_OFF,
AWAKE_ON
};
private:
std::vector<Type> done{};
public:
virtual void onNotify(const Entity&, Event::Type);
void unlock(Achievements::Type);
void printDone();
};
void Achievements::onNotify(const Entity& entity, const Event::Type event)
{
switch (event)
{
case Event::Type::ENTITY_FELL:
if(entity.isHero())
unlock(Achievements::Type::FELL_OFF);
break;
case Event::Type::ENTITY_AWAKE:
if(entity.isHero())
unlock(Achievements::Type::AWAKE_ON);
break;
default:
break;
}
};
void Achievements::unlock(Achievements::Type achiev)
{
done.push_back(achiev);
}
void Achievements::printDone()
{
// assert(done.size());
for(size_t i{0}; i < done.size(); i++)
{
std::cout << done[i] << "\n";
}
};
EntityAndEvent.cpp (i create this just to work with observer and subjects)
#ifndef ENTITY_AND_EVENT_H
#define ENTITY_AND_EVENT_H
class Entity
{
public:
inline const bool isHero() const {return true;}
};
class Event
{
public:
enum Type{
ENTITY_FELL,
ENTITY_AWAKE
};
};
#endif
Subjects.h
#ifndef SUBJECT_H
#define SUBJECT_H
#include "Observer.h"
#include <vector>
class Observer;
class Subjects
{
private:
// when implements this, prefer to use linked list or another optimized algorithms
Observer* head_{};
protected:
void notify(const Entity& Entity, Event::Type event);
public:
Subjects() : head_(NULL)
{};
~Subjects() {}
void addObserver(Observer* observer);
// const int getNumObs() const {return num_obs_;}
};
#endif
Subjects.cpp
#include "Subjects.h"
#include <cassert>
void Subjects::notify(const Entity& entity, Event::Type event)
{
Observer* observer = head_;
while (observer != NULL)
{
observer->onNotify(entity, event);
observer = observer->next_;
};
};
void Subjects::addObserver(Observer* observer)
{
if (head_ != nullptr)
observer->next_ = head_;
head_ = observer;
};
Physics.cpp (i create this just to populates the subject)
#ifndef PHYSICS_H
#define PHYSICS_H
#include "Subjects.h"
#include "EntityAndEvent.h"
class Physics: public Subjects
{
private:
public:
void update(const Entity& entity)
{
if (entity.isHero())
{
notify(entity, Event::Type::ENTITY_AWAKE);
};
};
};
#endif
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "Achievements.cpp"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
#include "Subjects.cpp"
int main()
{
Physics *p{};
Entity e{};
Achievements *achiev{};
p->addObserver(achiev);
p->update(e);
return 0;
}
With Physics *p{}; you are declaring a pointer, but it currently does not point to a valid object (it is being initialized as nullptr here). Therefore, calling p->addObserver results in a segmentation fault. You should be able to confirm this by running the program in a debugger.
Why are you using a pointer here? Change Physics *p{}; to Physics p{};.
Disclaimer: Since your code is definitely not a minimum example I didn't look into the whole code or even tried to compile it. I'm only posting an answer because there is a clear error in the main function (use of an invalid pointer) that results in a segmentation fault.
first, tks for the reply. #darcamo that works. I dont know why it was declared as pointer.
I fixed that, so if anyone else have the same doubt check below:
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
int main()
{
Physics p{};
Entity e{};
Achievements achiev{};
Observer* ptr_achiev{&achiev};
p.addObserver(ptr_achiev);
p.update(e);
return 0;
}

having difficulties to make a vector of polymorphic objects using shared_ptr and unique_ptr in C++ Visual studio 2019 Cmake project

For an exercise i need to build a vector of polymorphic objects and for some reason both shared and Unique ptr make linkage errors 2019 and 1120 when i use them. i have no option to use the old way of memory allocation with New and Delete so i have to make it work. i tried various of different syntax options for doing this and still with no luck.
*note:
we use Cmake to bind the project together in visual studio
and also we splitting the objects into header and cpp files.
here are my objects for now:
//This is the abstract base class
#pragma once
#include <string>
class Shape
{
public:
Shape() = default;
virtual ~Shape() = default;
virtual std::string get_name() = 0;
private:
};
These are the derived classes:
#pragma once
#include "Shape.h"
class Circle : public Shape
{
public:
Circle();
~Circle();
virtual std::string get_name() override;
private:
std::string m_name;
};
Cpp file:
#pragma once
#include "Circle.h"
Circle::Circle()
: m_name("Circle")
{
}
Circle::~Circle()
{
}
std::string Circle::get_name() override
{
return m_name;
}
another derived class:
#pragma once
#include "Shape.h"
class Rectangle : public Shape
{
public:
Rectangle();
~Rectangle();
virtual std::string get_name() override;
private:
std::string m_name;
};
Cpp file:
#pragma once
#include "Rectangle.h"
Rectangle::Rectangle()
: m_name ("Rectangle")
{
}
Rectangle::~Rectangle()
{
}
std::string Rectangle::get_name() override
{
return m_name;
}
this is the class that operates the program:
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include "Shape.h"
#include "Circle.h"
#include "Rectangle.h"
class Board
{
public:
Board();
~Board();
void run();
void objects_allocation();
private:
std::string m_string;
std::vector<std::shared_ptr<Shape>> m_gates;
};
Cpp file:
#pragma once
#include "Board.h"
Board::Board()
: m_string(" ")
{
}
Board::~Board()
{
}
void run()
{
while (m_string != "exit")
{
std::cin >> m_string;
}
std::cout << "Goodbye!" << std::endl;
}
void Board::Objects_allocation()
{
m_gates.push_back(std::make_shared <Circle>());
m_gates.push_back(std::make_shared <Rectangle>());
}
and here is my main function:
#pragma once
#include "Board.h"
int main()
{
Board board1;
board1.run();
return 0;
}
sincerely thank you if you could explain to me what went wrong here..
The Problem was in the Cmake file. now everything is working just like i wanted.

Why do sometimes two scripts are being launched at the same time?

Explanations: I'm trying to create a daemon-script that will be watching the Watch folder and if I drop some files there - it should run the script.
Problem: sometimes after I drop the file - nothing happens
Script: the script is working with files in the Watch folder and deletes them after.
Additional question: do I have to delete mc object manually or it will be done automatically?
main.cpp
#include "widget.h"
#include <QFileSystemWatcher>
#include <QApplication>
#include <QDebug>
#include "myclass.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFileSystemWatcher watcher;
watcher.addPath("/home/user/Documents/Watch/");
MyClass* mc = new MyClass;
QObject::connect(&watcher, SIGNAL(directoryChanged(QString)), mc, SLOT(showModified(QString)));
return app.exec();
}
myclass.h
#ifndef MYCLASS
#define MYCLASS
#include <QWidget>
#include <QDir>
#include <QDebug>
#include <QProcess>
class MyClass : public QWidget
{
Q_OBJECT
public:
MyClass(QWidget* parent=0)
:QWidget(parent){}
~MyClass(){}
public slots:
void showModified(const QString& str)
{
if(QDir("/home/user/Documents/Watch/").entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).count() == 0)
{
qDebug()<<"EEEMPTYYYY!!!!!!!!!!!!!!!!!!!\n";
_status = false;
}
Q_UNUSED(str)
if (_status == false)
{
_status = true;
QProcess *proc = new QProcess();
proc->setWorkingDirectory("/home/user/Documents/");
proc->startDetached("/home/user/Documents/script.sh");
proc->waitForFinished();
delete proc;
}
}
private:
bool _status = false;
};
#endif // MYCLASS

undefined reference to 'typeinfo for Thread'

I had write this code but compiler throw me an error and have no idea why :S
So I was wondering that you can help me:
This is an abstract class for an easy thread implementation:
#ifndef THREAD_H
#define THREAD_H
#include <pthread.h>
class Thread {
public:
void start();
inline pthread_t getThread() const{
return _thread;
}
private:
pthread_t _thread;
inline static void* callRun(void* pObject){
((Thread*)pObject)->run();
return (void*)0;
}
protected:
virtual void* run();
};
#endif /* THREAD_H */
The source code is:
#include "Thread.h"
void Thread::start(){
pthread_attr_t attrib;
pthread_attr_init(&attrib);
pthread_attr_setdetachstate(&attrib, PTHREAD_CREATE_JOINABLE);
pthread_create(&_thread, &attrib, callRun, (void*)this);
pthread_attr_destroy(&attrib);
}
And the class PlayersManager inherit from Thread
#ifndef PLAYERMANAGER_H
#define PLAYERMANAGER_H
#include "Thread.h"
class PlayersManager : public Thread {
private:
void movePlayers();
void checkPlayers();
void* run();
};
#endif /* PLAYERMANAGER_H */
but I get the next compile error:
build/Debug/GNU-Linux-x86/PlayersManager.o:(.rodata._ZTI14PlayersManager[_ZTI14PlayersManager]+0x8): undefined reference to `typeinfo for Thread'
Any idea of what is happening? Thanks.

Resources