I've got a PCD point cloud and I want it to show progressively in a window inside a MFC application. In my dialog I have some code that opens this viewer, but for some reason, it seems that it isn't working. I am working with the PCL library.
Here's the code of the dialog
// ClavegueresDlg.cpp: archivo de implementación
//
#include "stdafx.h"
#include "Clavegueres.h"
#include "ClavegueresDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
//#define new DEBUG_NEW
#endif
// Cuadro de diálogo CAboutDlg utilizado para el comando Acerca de
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Datos del cuadro de diálogo
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // Compatibilidad con DDX/DDV
// Implementación
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// Cuadro de diálogo de CClavegueresDlg
CClavegueresDlg::CClavegueresDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CClavegueresDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CClavegueresDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CClavegueresDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON2, &CClavegueresDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON1, &CClavegueresDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
// Controladores de mensaje de CClavegueresDlg
BOOL CClavegueresDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Agregar el elemento de menú "Acerca de..." al menú del sistema.
// IDM_ABOUTBOX debe estar en el intervalo de comandos del sistema.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Establecer el icono para este cuadro de diálogo. El marco de trabajo realiza esta operación
// automáticamente cuando la ventana principal de la aplicación no es un cuadro de diálogo
SetIcon(m_hIcon, TRUE); // Establecer icono grande
SetIcon(m_hIcon, FALSE); // Establecer icono pequeño
// TODO: agregar aquí inicialización adicional
return TRUE; // Devuelve TRUE a menos que establezca el foco en un control
}
void CClavegueresDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// Si agrega un botón Minimizar al cuadro de diálogo, necesitará el siguiente código
// para dibujar el icono. Para aplicaciones MFC que utilicen el modelo de documentos y vistas,
// esta operación la realiza automáticamente el marco de trabajo.
void CClavegueresDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // Contexto de dispositivo para dibujo
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Centrar icono en el rectángulo de cliente
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Dibujar el icono
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// El sistema llama a esta función para obtener el cursor que se muestra mientras el usuario arrastra
// la ventana minimizada.
HCURSOR CClavegueresDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CClavegueresDlg::InitPCL()
{
if (io::loadPCDFile<PointXYZ>("C:\\Users\\avilarrubla\\Desktop\\Clavegueres\\configuracio\\InfSup.pcd", original_point_cloud) == -1) //* load the file
{
//error
}
else
{
Eigen::Matrix4f scale_trf = Eigen::Matrix4f::Identity();
float fl_scale = 3;
scale_trf(0, 0) = fl_scale; scale_trf(1, 1) = fl_scale; scale_trf(2, 2) = fl_scale;
transformPointCloud(original_point_cloud, point_cloud, scale_trf);
//color = PointCloud<PointXYZRGB>();
//copyPointCloud(point_cloud, color);
vamos_borrar = point_cloud.begin();
point_cloud_anadir = PointCloud<PointXYZ>::Ptr();
cuantos = point_cloud.points.size();
tenemos = 0;
viewer = visualization::PCLVisualizer("", false);
viewer.setBackgroundColor(0.94, 0.1, 0.1);
VisualiserRenderer = vtkRenderer::New();
InteractionVisualiserWindow = vtkRenderWindowInteractor::New();
VisualiserWindow = viewer.getRenderWindow();
/*
InteractionVisualiserWindow->RemoveObservers(vtkCommand::LeftButtonPressEvent);
InteractionVisualiserWindow->RemoveObservers(vtkCommand::RightButtonPressEvent);
InteractionVisualiserWindow->RemoveObservers(vtkCommand::MiddleButtonPressEvent);
InteractionVisualiserWindow->RemoveObservers(vtkCommand::MouseWheelBackwardEvent);
InteractionVisualiserWindow->RemoveObservers(vtkCommand::MouseWheelForwardEvent);
*/
LPRECT rect = new CRect;
CStatic *pclStatic = new CStatic();
pclStatic = (CStatic*)GetDlgItem(IDC_VISTA3D);
VisualiserWindow->SetParentId(pclStatic->m_hWnd);
//VisualiserWindow->SetSize(rect->right - rect->left, rect->bottom - rect->top);
VisualiserWindow->SetSize(0, 0);
//VisualiserWindow->SetPosition(10, 10);
InteractionVisualiserWindow->SetRenderWindow(VisualiserWindow);
VisualiserWindow->Render();
InteractionVisualiserWindow->Render();
//single_color = visualization::PointCloudColorHandlerCustom<PointXYZ>(point_cloud_anadir, 10, 255, 10);
SetTimer(1, 10, NULL);
}
}
void CClavegueresDlg::OnTimer(UINT_PTR nIDEvent)
{
viewer.removePointCloud("point_cloud_anadir");
viewer.removeAllShapes();
if (point_cloud_anadir->points.size() < cuantos){
point_cloud_anadir->points.resize(point_cloud_anadir->points.size() + 1);
point_cloud_anadir->points[tenemos].x = (*vamos_borrar).x;
point_cloud_anadir->points[tenemos].y = (*vamos_borrar).y;
point_cloud_anadir->points[tenemos].z = (*vamos_borrar).z;
++vamos_borrar;
++tenemos;
}
viewer.addPointCloud<PointXYZ>(point_cloud_anadir, "sample cloud");
viewer.setPointCloudRenderingProperties(visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");
CDialogEx::OnTimer(nIDEvent);
}
void CClavegueresDlg::OnBnClickedButton2()
{
// TODO: Agregue aquí su código de controlador de notificación de control
//visualization::PCLVisualizer viewer("", false);
KillTimer(1);
if (!viewer.wasStopped()){
viewer.~PCLVisualizer();
viewer.close();
}
}
void CClavegueresDlg::OnBnClickedButton1()
{
// TODO: Agregue aquí su código de controlador de notificación de control
InitPCL();
}
Button1 is a button that when clicked should begin to show the point cloud and Button2 should stop it. The important code is the InitPCL() and the timer code. The first one initializes the viewer and the Timer inserts into the viewer a point every 10ms. Is there something wrong? How should I change this in order to work?
You should have written what exactly does not work, but I guess you simply forgot ON_WM_TIMER() in the message map and therefore OnTimer is never called.
BEGIN_MESSAGE_MAP(CClavegueresDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_TIMER() // <<<<<<<<<<<<<<< add this line
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON2, &CClavegueresDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON1, &CClavegueresDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
In the declaration of CClavegueresDlg add this:
void OnTimer(UINT_PTR nIDEvent);
You could have found out this yourself by using the debugger.
There may be other issues related to the PCL.
Related
I am trying to make a telemetry software for a college project. I am new to C++ as I am more used to Python. I followed a few tutorials and asked help from GPT3 to make it.
// Importation des librairies
#include "telemetry.h"
#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QStandardItemModel>
#include <QTableView>
// Structure pour stocker les données de télémétrie
struct TelemetryData {
double time;
double distance;
double speed;
double acceleration;
double acceleratorPressure;
double brakePressure;
double gpsPositionX;
double gpsPositionY;
};
//----------------------------------------------------------------------------- Main ------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// ---------- Création des différents affichages, boutons et onglets --------
QApplication app(argc, argv);
// Créer la fenêtre principale de l'application
QMainWindow window;
window.setWindowTitle("Télémétrie");
// Créer le layout principal de la fenêtre
QWidget* centralWidget = new QWidget(&window);
QVBoxLayout* mainLayout = new QVBoxLayout(centralWidget);
window.setCentralWidget(centralWidget);
// Créer le widget QTabWidget et l'ajouter à l'interface utilisateur
QTabWidget* tabWidget = new QTabWidget(centralWidget);
mainLayout->addWidget(tabWidget);
// Créer le premier onglet affichant le graphique de pression d'accélérateur et de frein
QWidget* firstTab = new QWidget();
QVBoxLayout* firstTabLayout = new QVBoxLayout(firstTab);
// Créer le graphe de pression d'accélérateur et de frein
QCustomPlot* pressureGraph = new QCustomPlot(firstTab);
pressureGraph->addGraph();
pressureGraph->addGraph();
pressureGraph->graph(0)->setPen(QPen(Qt::green));
pressureGraph->graph(1)->setPen(QPen(Qt::red));
pressureGraph->xAxis->setLabel("Temps (ms)");
pressureGraph->yAxis->setLabel("Pression (bars)");
pressureGraph->yAxis->setRange(0, 1);
firstTabLayout->addWidget(pressureGraph);
// Créer les boutons de contrôle du graphe de pression d'accélérateur et de frein
QPushButton* pauseButton = new QPushButton("Mettre en pause", firstTab);
QPushButton* nextButton = new QPushButton("Milliseconde suivante", firstTab);
QPushButton* previousButton = new QPushButton("Milliseconde précédente", firstTab);
QPushButton* forwardButton = new QPushButton("Avancer x3", firstTab);
QPushButton* backwardButton = new QPushButton("Reculer x3", firstTab);
firstTabLayout->addWidget(pauseButton);
firstTabLayout->addWidget(nextButton);
firstTabLayout->addWidget(previousButton);
firstTabLayout->addWidget(forwardButton);
firstTabLayout->addWidget(backwardButton);
// Ajouter l'onglet au widget QTabWidget
tabWidget->addTab(firstTab, "Graphique de pression d'accélérateur et de frein");
// Créer le deuxième onglet affichant un tableau de données de télémétrie
QWidget* secondTab = new QWidget();
QVBoxLayout* secondTabLayout = new QVBoxLayout(secondTab);
// Créer le modèle de données et le tableau
QStandardItemModel* model = new QStandardItemModel(0, 9, secondTab);
model->setHeaderData(0, Qt::Horizontal, "Temps (ms)");
model->setHeaderData(1, Qt::Horizontal, "Distance (m)");
model->setHeaderData(2, Qt::Horizontal, "Vitesse (m/s)");
model->setHeaderData(3, Qt::Horizontal, "Accélération (m/s^2)");
model->setHeaderData(4, Qt::Horizontal, "Pression d'accélérateur (bars)");
model->setHeaderData(5, Qt::Horizontal, "Pression de frein (bars)");
model->setHeaderData(6, Qt::Horizontal, "Position GPS X (m)");
model->setHeaderData(7, Qt::Horizontal, "Position GPS Y (m)");
//Créer l'onglet secondaire
QTableView* tableView = new QTableView(secondTab);
tableView->setModel(model);
secondTabLayout->addWidget(tableView);
// Ajouter l'onglet au widget QTabWidget
tabWidget->addTab(secondTab, "Données de télémétrie");
// Créer le bouton permettant de changer d'onglet
QPushButton* switchTabButton = new QPushButton("Changer d'onglet", centralWidget);
mainLayout->addWidget(switchTabButton);
// Connecter le signal clicked() du bouton à un slot qui changera l'onglet sélectionné dans le widget QTabWidget
QObject::connect(switchTabButton, &QPushButton::clicked, [&tabWidget]() {
int currentIndex = tabWidget->currentIndex();
int newIndex = (currentIndex + 1) % tabWidget->count();
tabWidget->setCurrentIndex(newIndex);
});
// --------------------- Ouverture du Fichier -------------------
// Ouvrir le fichier de données de télémétrie en lecture
QFile file("telemetry.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
// Afficher une erreur si le fichier ne peut pas être ouvert
QMessageBox::critical(nullptr, "Erreur", "Impossible d'ouvrir le fichier de données de télémétrie");
return -1;
}
// Collecter les données de télémétrie depuis le fichier
QTextStream in(&file);
QVector<TelemetryData> data;
while (!in.atEnd()) {
QString line = in.readLine();
QStringList fields = line.split("\t");
if (fields.size() != 8) {
// Afficher une erreur si le nombre de champs est incorrect
QMessageBox::critical(nullptr, "Erreur", "Format de données de télémétrie incorrect");
return -1;
}
TelemetryData datum;
datum.time = fields[0].toDouble();
datum.distance = fields[1].toDouble();
datum.speed = fields[2].toDouble();
datum.acceleration = fields[3].toDouble();
datum.acceleratorPressure = fields[4].toDouble();
datum.brakePressure = fields[5].toDouble();
datum.gpsPositionX = fields[6].toDouble();
datum.gpsPositionY = fields[7].toDouble();
data.append(datum);
}
file.close();
// -------------- Affinage des affichages --------------
// Créer un objet gnuplot pour dessiner la gauge de vitesse
Gnuplot gp;
gp << "set terminal qt size 350,200 font ',14'\n";
gp << "set style data line\n";
gp << "set xrange [-1:1]\n";
gp << "set yrange [-1:1]\n";
gp << "set border 0\n";
gp << "set tics out\n";
gp << "set nokey\n";
gp << "unset colorbox\n";
gp << "set object 1 circle at 0,0 size 1.1 fc rgb 'white'\n";
gp << "set object 2 circle at 0,0 size 1 fc rgb 'black'\n";
gp << "set object 3 circle at 0,0 size 0.9 fc rgb 'red'\n";
gp << "set object 4 circle at 0,0 size 0.1 fc rgb 'black'\n";
gp << "set object 5 circle at 0,0 size 0.07 fc rgb 'white'\n";
// Créer une image du circuit vu d'en haut
QImage circuitImage("circuit.png");
QLabel* circuitLabel = new QLabel(centralWidget);
circuitLabel->setPixmap(QPixmap::fromImage(circuitImage));
circuitLabel->setScaledContents(true);
circuitLabel->setFixedSize(500, 500);
mainLayout->addWidget(circuitLabel);
// Dessiner un cercle rouge à la position de la voiture sur l'image du circuit
QGraphicsScene* circuitScene = new QGraphicsScene(circuitLabel);
QGraphicsEllipseItem* car = new QGraphicsEllipseItem(0, 0, 10, 10);
car->setBrush(QBrush(Qt::red));
circuitScene->addItem(car);
QGraphicsView* circuitView = new QGraphicsView(circuitScene, circuitLabel);
circuitView->setRenderHint(QPainter::Antialiasing);
circuitView->setRenderHint(QPainter::SmoothPixmapTransform);
circuitView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
circuitView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
circuitView->setFixedSize(500, 500);
// Créer une jauge de vitesse
QLabel* speedGauge = new QLabel(centralWidget);
speedGauge->setFixedSize(350, 200);
speedGauge->setPixmap(QPixmap::fromImage(gp.plot(QString(""), "", "", "", false).scaled(350, 200)));
mainLayout->addWidget(speedGauge);
// Afficher la fenêtre principale
mainWindow.show();
// ---------------- Fonction Temps réel ---------------
// Initialiser l'index de la donnée de télémétrie actuellement affichée
int dataIndex = 0;
// Initialiser un booléen indiquant si la lecture en temps réel est en pause
bool paused = false;
// Boucle principale de mise à jour de l'affichage en temps réel
while (true) {
// Mettre à jour le graphique de pression d'accélérateur et de frein
pressureGraph->graph(0)->addData(data[dataIndex].time, data[dataIndex].acceleratorPressure);
pressureGraph->graph(1)->addData(data[dataIndex].time, data[dataIndex].brakePressure);
pressureGraph->xAxis->setRange(data[dataIndex].time, 8, Qt::AlignRight);
pressureGraph->replot();
// Mettre à jour la jauge de vitesse
double speedRatio = data[dataIndex].speed / 140.0; // 140 km/h est la vitesse maximale
gp << "set object 4 circle at " << QString::number(speedRatio * std::sin(M_PI / 4)).toStdString()
<< "," << QString::number(-speedRatio * std::cos(M_PI / 4)).toStdString()
<< " size 0.1 fc rgb 'black'\n";
speedGauge->setPixmap(QPixmap::fromImage(gp.plot(QString(""), "", "", "", false).scaled(350, 200)));
// Mettre à jour la position de la voiture sur l'image du circuit
car->setPos(250 + data[dataIndex].gpsPositionX * 3, 250 - data[dataIndex].gpsPositionY * 3); // 250, 250 est le centre de l'image
// Mettre à jour l'affichage du tableau de données de télémétrie
for (int i = 0; i < model->rowCount(); ++i) {
model->setData(model->index(i, 0), data[i].time);
model->setData(model->index(i, 1), data[i].distance);
model->setData(model->index(i, 2), data[i].speed);
model->setData(model->index(i, 3), data[i].acceleration);
model->setData(model->index(i, 4), data[i].acceleratorPressure);
model->setData(model->index(i, 5), data[i].brakePressure);
model->setData(model->index(i, 6), data[i].gpsPositionX);
model->setData(model->index(i, 7), data[i].gpsPositionY);
}
tableView->scrollTo(model->index(dataIndex, 0));
// Attendre 1 milliseconde avant de mettre à jour à nouveau l'affichage
QThread::msleep(1);
// Si la lecture en temps réel n'est pas en pause, passer à la donnée de télémétrie suivante
if (!paused) {
++dataIndex;
}
if (dataIndex >= data.size()) {
dataIndex = 0;
}
}
There is no error and when I build the solution, it works fine, saying the operation was succesful, however when I try to debug it, no .exe is found.
Here is what I get when I build the solution :
Build started...
1>------ Build started: Project: Telemetrie_PITA, Configuration: Debug x64 ------
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
I checked the project files and it is true, there is no .exe in sight.
To verify whether the error would come from my project or my installation, I ran a simple HelloWorld project which worked perfectly fine.
Menu -> Build -> Build Solution perform.
.exe file is default located in C:\Users\DESKTOP NAME\source\repos\PROJECT NANE\PROJECT NAME\bin\Debug path.
.exe can also be forcibly deleted Anti-Virus Program.
I'm not familiar with the SFML environment yet, we started learning it this year at school
I'm struggling to draw a sprite on another sprite using this method
I guess this s.~Drawable(); is used to draw on another windows but i couldn't find any example to implement it anyone could redirect me to a good documentation that is easy to understands for begginers.
Thanks.
PS: I found other methods but I need to load image everytimes to change the player's sprite image and I guess this would slow down the game fps depending on the user drive
int sizeX = 1920, sizeY = 1080;
sf::RenderWindow window(sf::VideoMode(sizeX, sizeY), "Test");
window.setFramerateLimit(60); // max FPS a 60
sf::Vector2f player1(10, 10);
sf::Vector2f player2(590, 10);
sf::Sprite paddle1;
sf::Sprite paddle2;
sf::Texture t;
t.loadFromFile("Background.png");
sf::Sprite s(t);
//s.~Drawable();
// chargement du fichier .jpg dans un objet image de type Texture
sf::Texture imageBack1;
sf::Texture imageBack2;
sf::Texture imageForward1;
sf::Texture imageForward2;
sf::Texture imageLeft;
sf::Texture imageRight;
// PLayer2
sf::Texture imageBack1b;
sf::Texture imageBack2b;
sf::Texture imageForward1b;
sf::Texture imageForward2b;
sf::Texture imageLeftb;
sf::Texture imageRightb;
if (!imageBack1.loadFromFile("Back1.png"))
printf("PB de chargement de l'image !\n");
if (!imageBack2.loadFromFile("Back2.png"))
printf("PB de chargement de l'image !\n");
if (!imageForward1.loadFromFile("Forward1.png"))
printf("PB de chargement de l'image !\n");
if (!imageForward2.loadFromFile("Forward2.png"))
printf("PB de chargement de l'image !\n");
if (!imageLeft.loadFromFile("Left.png"))
printf("PB de chargement de l'image !\n");
if (!imageRight.loadFromFile("Right.png"))
printf("PB de chargement de l'image !\n");
//Player2 I guess this can be removed
if (!imageBack1b.loadFromFile("Back1b.png"))
printf("PB de chargement de l'image !\n");
if (!imageBack2b.loadFromFile("Back2b.png"))
printf("PB de chargement de l'image !\n");
if (!imageForward1b.loadFromFile("Forward1b.png"))
printf("PB de chargement de l'image !\n");
if (!imageForward2b.loadFromFile("Forward2b.png"))
printf("PB de chargement de l'image !\n");
if (!imageLeftb.loadFromFile("Leftb.png"))
printf("PB de chargement de l'image !\n");
if (!imageRightb.loadFromFile("Rightb.png"))
printf("PB de chargement de l'image !\n");
/* L’image doit être associée à un objet de type Sprite (équivalent à un rectangle) pour être dessinée. Ici , le sprite s’appelle bonhomme. Après, on ne travaille plus que sur le sprite… image ne sert plus à rien*/
paddle1.setTexture(imageBack1);
paddle2.setTexture(imageBack1);
// Start the game loop
while (window.isOpen())
{
// Poll for events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window.close();
// Escape pressed : exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
window.close();
}
window.clear();
// Draw the sprites
window.draw(paddle1);
window.draw(paddle2);
window.draw(s);
window.display();
}
You could draw to a sf::RenderTexture: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1RenderTexture.php
And have this render texture be the texture of the Sprite.
I was writing a chat program with Qt 5.9. I finished the client-side program and started improving it. The first thing I did was making a new Qwidget (a secondary window) that would appear when pressing the connect button on my main window. Everything went fine, but when I tested and pressed the connect button on my main window, my secondary window appeared and disappeared instantly. How can I make my secondary window stay (not disappear) for the time the user presses the button (which is on the secondary window)? Here is the code of both my windows : main window.h (fenClient.h):
#ifndef FENCLIENT_H
#define FENCLIENT_H
#include <QtWidgets>
#include <QtNetwork>
#include <ui_fenclient.h>
#include <fenconnexion.h>
class FenClient : public QWidget, private Ui::FenClient
{
Q_OBJECT
public:
FenClient();
~FenClient();
private slots:
void on_boutonConnexion_clicked();
void on_boutonEnvoyer_clicked();
void on_message_returnPressed();
void donneesRecues();
void connecte();
void deconnecte();
void erreurSocket(QAbstractSocket::SocketError erreur);
private:
QTcpSocket *socket;
quint16 tailleMessage;
};
#endif // FENCLIENT_H
#include <fenclient.h>
main window.cpp (fenClient.cpp) This is where the secondary window is created.
FenClient::FenClient()
{
setupUi(this);
socket = new QTcpSocket;
connect(socket,SIGNAL(readyRead()),this,SLOT(donneesRecues()));
connect(socket,SIGNAL(connected()),this,SLOT(connecte()));
connect(socket,SIGNAL(disconnected()),this,SLOT(deconnecte()));
connect(socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(erreurSocket(QAbstractSocket::SocketError)));
tailleMessage = 0;
}
void FenClient::on_boutonConnexion_clicked()
{
listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
boutonConnexion->setEnabled(false);
fenConnexion *fenetreCo = new fenConnexion; //this is where my secondary window is created
fenetreCo->show();
fenetreCo->activateWindow();
fenetreCo->setParent(this);
fenetreCo->echangerPseudo(pseudo->text());
socket->abort();
socket->connectToHost(serveurIP->text(),serveurPort->value());
}
void FenClient::on_boutonEnvoyer_clicked()
{
if (message->text().isEmpty())
{
QMessageBox::information(this,"Veuillez écrire quelque chose","Pour éviter le spam, j'ai decidé d'empecher l'envoi de message vide. Veuillez écrire quelque chose...");
}
else if(pseudo->text() == "")
{
QMessageBox::information(this,"Veuillez spécifier votre nom","Pour éviter l'anonimité, j'ai décidé d'obligé l'usage d'un pseudo.");
}
else
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
QString messageAEnvoyer = tr("<strong>") + pseudo->text() + tr("</strong> : ") + message->text();
out<<(quint16) 0;
out<< messageAEnvoyer ;
out.device()->seek(0);
out << (quint16) (paquet.size() - sizeof(quint16));
socket->write(paquet);
message->clear();
message->setFocus();
}
}
void FenClient::on_message_returnPressed()
{
on_boutonEnvoyer_clicked();
}
void FenClient::donneesRecues()
{
QDataStream in(socket);
if (tailleMessage==0)
{
if(socket->bytesAvailable() < (int)sizeof(quint16))
{return;}
in >> tailleMessage;
}
if (socket->bytesAvailable() < tailleMessage)
{return;}
QString messageRecu;
in >> messageRecu;
listeMessages->append(messageRecu);
tailleMessage = 0;
}
void FenClient::connecte()
{
listeMessages->append(tr("<em>Connexion réussie</em>"));
boutonConnexion->setEnabled(true);
message->setEnabled(true);
}
void FenClient::deconnecte()
{
listeMessages->append(tr("<em>Déconnecté!</em>"));
message->setEnabled(false);
}
void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
{
switch(erreur)
{
case QAbstractSocket::HostNotFoundError:
listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
break;
case QAbstractSocket::ConnectionRefusedError:
listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
break;
case QAbstractSocket::RemoteHostClosedError:
listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
break;
default:
listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
}
boutonConnexion->setEnabled(true);
}
FenClient::~FenClient()
{}
secondary window.h (fenconnexion.h)
#ifndef FENCONNEXION_H
#define FENCONNEXION_H
#include <ui_fenconnexion.h>
#include <QtWidgets>
class fenConnexion : public QWidget, private Ui::Form
{
Q_OBJECT
public:
fenConnexion();
QString pseudoUtilisateur;
void echangerPseudo(QString pseudoAEchanger);
private slots :
void checkPseudo();
private:
QString pseudo;
};
#endif // FENCONNEXION_H
secondary window.cpp (fenconnexion.cpp)
#include <fenconnexion.h>
fenConnexion::fenConnexion()
{ setupUi(this);
connect(boutonInserer,SIGNAL(clicked(bool)),this,SLOT(checkPseudo()));
}
void fenConnexion::checkPseudo()
{
pseudo=pseudoInsere->text();
if (pseudo.isEmpty())
{
QMessageBox::information(this,"Probleme","Veuillez entre un pseudo conetenant au moins un caractere.");
}
else
{
pseudoUtilisateur=pseudo;
pseudoInsere->clear();
pseudo.clear();
this->close();
}
}
void fenConnexion::echangerPseudo(QString pseudoAEchanger)
{
pseudoAEchanger.clear();
pseudoAEchanger = pseudoUtilisateur;
}
I feel like I've made a very simple error, but as I haven't used Qt in over 6 months, I don't seem to find it.
You need to make sure you've set up the window properly before trying to show it.
fenConnexion *fenetreCo = new fenConnexion;
fenetreCo->show();
fenetreCo->activateWindow();
fenetreCo->setParent(this);
Set the parent of the window before invoking show on it. That makes the window this' child, which means that it's this' responsibility to manage its life-cycle.
Hello I have this Microsoft Foundation Classes that will run mostly and check USB Device and other stuff. The problem is, certain IntelliSense is undefined that's why most errors will display when running the program.
Here's the error list:
The Entire Code:
// MFCApplication2Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "MFCApplication2.h"
#include "MFCApplication2Dlg.h"
#include "afxdialogex.h"
#include "afxwin.h"
#include "CyAPI.h"
#define UART_H
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
bool IsConnect = false;
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CMFCApplication2Dlg dialog
CMFCApplication2Dlg::CMFCApplication2Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMFCApplication2Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCApplication2Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMFCApplication2Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication2Dlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON3, &CMFCApplication2Dlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON2, &CMFCApplication2Dlg::OnBnClickedButton2)
END_MESSAGE_MAP()
// CMFCApplication2Dlg message handlers
BOOL CMFCApplication2Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CMFCApplication2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMFCApplication2Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMFCApplication2Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
bool CMFCApplication2Dlg::OnBnClickedButton1()
{
USBDevice->Open(0);
if (USBDevice->IsOpen() != TRUE)
{
AfxMessageBox(_T("Failed to Open Device"));
return false;
}
else
{
IsConnect = true;
return true;
}
}
void CMFCApplication2Dlg::OnBnClickedButton3()
{
USBDevice->Close();
IsConnect = false;
}
void CMFCApplication2Dlg::OnBnClickedButton2()
{
char tmpUart[60];
long OutPacketSize;
OutPacketSize = sizeof(sUart);
LPTSTR pBuffer;
CString sBuffer;
int i;
if (IsConnect == false)
{
AfxMessageBox(_T("USB Connect Fail"));
return;
}
CEdit*OutValue = (CEdit*)GetDlgItem(IDC_OUT_VALUE);
pBuffer = sBuffer.GetBuffer(60);
OutValue->GetWindowText(pBuffer, 60);
strcpy(tmpUart, pBuffer);
OutPacketSize = strlen(tmpUart);
for (i = 0; i<OutPacketSize; i++) sUart[i] = tmpUart[i];
sUart[OutPacketSize + 1] = 0;
OutPacketSize = OutPacketSize + 1;
//Perform the BULK OUT
if (USBDevice->BulkOutEndPt)
{
USBDevice->BulkOutEndPt->XferData(sUart, OutPacketSize);
}
}
HELP:
What certain libraries do I have to import or include to fix these kind of errors? I'm new to MFC's and I don't quite yet understand the structures and ways to program this. Please help.
The ON_BN_CLICKED message map macro expects a member function pointer with the signature
afx_msg void memberFxn()
However, your OnBnClickedButton1 returns a bool. That member function must not have a return value (void) to use it with ON_BN_CLICKED.
I would like to display text in my Windows thanks to sfml. But I don't arrived to do it, the texte just don't appear in the windows, that's really strange because I can display lines without difficulties !
Can you check my code and tell me what I need to change please ? :)
My main.cpp
int main()
{
bool sortir = false;
// Création de la pile de double
Pile<double> pile_double;
// Création de la pile de string
Pile<string> pile_string;
// Création du map
map<string, function<void()>> _map;
int largeur_fenetre = 300;
int hauteur_fenetre = 400;
// Création de la fenetre
sf::RenderWindow window(sf::VideoMode(largeur_fenetre, hauteur_fenetre), "Interpreteur NPI");
//copie largeur / longueur
push(pile_double, (double) largeur_fenetre);
push(pile_double, (double) hauteur_fenetre);
// on fait tourner le programme tant que la fenêtre n'a pas été fermée
while (window.isOpen())
{
// on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
sf::Event event;
while (window.pollEvent(event))
{
cout << "passage 1er while" << endl;
// fermeture de la fenêtre lorsque l'utilisateur le souhaite
if (event.type == sf::Event::Closed)
window.close();
}
// effacement de la fenêtre en noir
window.clear(sf::Color::Black);
window.display();
cout << "coucou" << endl;
while (sortir == false)
{
cout << "Entrez la commande souhaité >";
string carac;
cin >> carac;
// Recherche du string dans le map
for (map<string, function<void()>>::iterator it = _map.begin(); it != _map.end(); ++it) // Debut recherche de la relation
{
// S'il est trouvé on demarre sa fonction associé
if (carac == it->first)
{
(it->second)();
pile_double.display();
pile_string.display();
window.display();
}
} // Fin de la recherche de la relation string -> fonction | Fin du For
if (carac == "exit")
{
sortir = true;
}
}
}
return 0;
}
fonction.cpp
void drawstr(Pile<double>& nomDeLaPile, sf::RenderWindow& window, Pile<string>& nomDeLaPile2)
{
sf::Text text;
sf::Font font;
text.setFont(font);
text.setString("Hello world");
text.setCharacterSize(24);
text.setColor(sf::Color::Red);
text.setStyle(sf::Text::Bold | sf::Text::Underlined);
window.draw(text);
}
My apologies for very bad English, I hope you understand anyways!
You do:
sf::Font font;
text.setFont(font);
But you don't load any font, you "set" an empty font...
Try something like that before:
if (!font.loadFromFile("arial.ttf"))
{
// error
}
But you shouldn't do that in the drawing function.
Font has to be loaded once when starting the application.
From the SFML tutorial:
Note that SFML won't load your system fonts automatically, i.e.
font.loadFromFile("Courier New") won't work. First because SFML
requires file names, not font names, and secondly because SFML doesn't
have a magic access to your system's font folder. So, if you want to
load a font, you need to have the font file with your application,
like other resources (images, sounds, ...).
SFML does not provide a default font, or an font for that matter.
When you created a Font object using:
sf::Font font;
it is an empty font. What you need to do is download a font from a website, such as http://www.dafont.com/ or find where the font files are on your computer.
Then you should load the font (from the same SFML tutorial):
sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
// error...
}