Qt qwidget appearing and disappearing instantly - c++

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.

Related

Display images from source directory selected by user

I have a Qt application where user selects source directory which has images (.pgm files) (any number). In the UI,
I have created a display area (QGroupBox) which has 2 QGraphicsview which displays 2 images at a time.
UI image:
Going ahead,
I want to create QGraphicsViews Widget for all the images and display 2 of them at a time. There will be a scroll bar to the right.
When user drags the scroll bar down other QGraphicsView Widgets
should be visible to the user with different images. How can i do this using Qt in C++?
PS: I am able to display two images in the display area using QGraphicsView Widget when the load images button is clicked.
#include "ui_DataViewerPage.h"
#include <iostream>
#include <QGraphicsScene>
#include <QPixmap>
#include <QThread>
#include <QSettings>
#include "DataWorker.h"
namespace Ui
{
class DataViewerPage;
}
// This is the main UI thread header and cpp file
class DataViewerPage : public QWidget
{
Q_OBJECT
public:
DataViewerPage(QWidget* parent = nullptr);
virtual ~DataViewerPage();
public slots:
void on_loadButton_clicked();
void startWorker();
void stopWorker();
void displayImage(QString fileName);
signals:
void startLoadingImages();
private:
Ui::DataViewerPage* ui;
DataWorker* worker;
QSettings settings;
// Worker thread handles data processing away from ui thread
QThread workerThread;
QSharedPointer<QGraphicsScene> ptr_scene;
QSharedPointer<QGraphicsScene> ptr_scene2;
int currentDisplayNum;
};
#include "DataViewerPage.h"
DataViewerPage::DataViewerPage(QWidget* parent)
: QWidget(parent), worker(nullptr), ui(new Ui::DataViewerPage)
{
ui->setupUi(this);
ui->Display->setVisible(true);
ptr_scene = QSharedPointer<QGraphicsScene>(new QGraphicsScene(this));
ptr_scene2 = QSharedPointer<QGraphicsScene>(new QGraphicsScene(this));
}
DataViewerPage::~DataViewerPage()
{
workerThread.quit();
workerThread.wait();
workerThread.terminate();
if (worker)
{
delete worker;
}
delete ui;
}
void DataViewerPage::on_loadButton_clicked()
{
ui->Display->setVisible(true);
ui->loadButton->setDisabled(true);
emit startLoadingImages();
}
void DataViewerPage::stopWorker()
{
workerThread.quit();
workerThread.wait();
workerThread.terminate();
if (worker)
{
delete worker;
worker = nullptr;
}
}
void DataViewerPage::startWorker()
{
stopWorker();
worker = new DataWorker();
worker->moveToThread(&workerThread);
connect(this, &DataViewerPage::startLoadingImages, worker, &DataWorker::startLoadingImages);
connect(worker, &DataWorker::displayImage, this, &DataViewerPage::displayImage);
workerThread.start();
currentDisplayNum = 0;
}
void DataViewerPage::displayImage(QString fileName)
{
QPixmap pixelMap(fileName.toStdString().c_str()); // <- path to image file
switch (currentDisplayNum)
{
case 0:
ptr_scene->addPixmap(pixelMap);
ui->img1->setScene(ptr_scene.get());
break;
case 1:
ptr_scene2->addPixmap(pixelMap);
ui->img2->setScene(ptr_scene2.get());
break;
default:
break;
}
currentDisplayNum++;
}
// This is the worker thread header and cpp file.
#pragma once
#include <QThread>
#include <QSettings>
#include <filesystem>
class DataWorker : public QObject
{
Q_OBJECT
public:
DataWorker();
~DataWorker();
public slots:
void startLoadingImages();
signals:
void displayImage(QString fileName);
private:
QSettings settings;
std::string path;
};
#include "DataWorker.h"
#include <iostream>
#include <QImage>
DataWorker::DataWorker()
{
path = settings.value("dataDir").toString().toStdString();
}
DataWorker::~DataWorker()
{
}
void DataWorker::startLoadingImages()
{
std::cout << "startloadingImages called..." << std::endl;
int iCount = 0;
for (const auto& entry : std::filesystem::directory_iterator(path))
{
QString imgPath = QString::fromStdString(entry.path().string());
emit displayImage(imgPath);
iCount++;
if(iCount > 1)
break; // Right now do it for two only.......
}
}

QStackedWidget how to use it exactly?

I tried to use QStackedWidget before, but I didn't understand exactly how to. The code below makes me understand how to change the current window from the main window to another window, already called in the mainwindow, and this is working good. I changed the current index to all the other windows, and every time the window is not the same, which is good.
My question is:
From another window how can I switch to another window (different than the current)? Do I Have to define this QStackedWidget in all the other windows, so that I can use it the same way as I am using it here?
I would love that after clicking on a button on a window(the other windows) the window switch to another one, How can I do it?
For example, in this code I have the FenetrePrincipale that allow me to change the windows using the setCurrentIndex , setting the setCurrentIndex to 3 for example make the first window that appear is MAFENETRE3.
I would like that from for example, from MAFENTRE3 use a button that allow me to switch to another window .
( actually after having problems with QStackedWidget I just implement my code normally and instead of switching to another window, I just open window on the bottom of the window calling which is not looking good!
PS HERE THE CODE OF TEST :
fenetrprincipale.h
#ifndef FENETRE_PRINCIPALE
#define FENETRE_PRINCIPALE
#include <QApplication>
#include <QtWidgets>
#include "MaFenetre.h"
#include "MaFenetre2.h"
#include "MaFenetre3.h"
#include "MaFenetre4.h"
class FenetrePrincipale : public QMainWindow
{
Q_OBJECT
public:
FenetrePrincipale();
~FenetrePrincipale();
public slots:
void slotDisplayFen(int fenIndex);
private:
QStackedWidget *stack;
MaFenetre *fen1;
MaFenetre2 *fen2;
MaFenetre3 *fen3;
MaFenetre4 *fen4;
};
#endif
fenetreprincipale.cpp
#include "FenetrePrincipale.h"
FenetrePrincipale::FenetrePrincipale() : QMainWindow()
{
stack = new QStackedWidget(this);
fen1 = new MaFenetre();
fen2 = new MaFenetre2 ();
fen3 = new MaFenetre3();
fen4 = new MaFenetre4();
stack->addWidget(fen1);
stack->addWidget(fen2);
stack->addWidget(fen3);
stack->addWidget(fen4);
this->setCentralWidget(stack);
stack->setCurrentIndex(0); // on affiche la première fenêtre à l'ouverture du programme
setWindowTitle("Test STACKEDLAYOUT");
resize(500,600);
connect(fen1, SIGNAL(askDisplayFen(int)), this, SLOT(slotDisplayFen(int)));
connect(fen2, SIGNAL(askDisplayFen(int)), this, SLOT(slotDisplayFen(int)));
connect(fen3, SIGNAL(askDisplayFen(int)), this, SLOT(slotDisplayFen(int)));
connect(fen4, SIGNAL(askDisplayFen(int)), this, SLOT(slotDisplayFen(int)));
}
FenetrePrincipale::~FenetrePrincipale()
{
}
void FenetrePrincipale::slotDisplayFen(int fenIndex)
{
if ((fenIndex < 0) || (fenIndex > 3)) {return;}
stack->setCurrentIndex(fenIndex);
}
Here is the code of Mafenetre
MaFenetre.h
#ifndef DEF_MAFENETRE
#define DEF_MAFENETRE
#include <QtWidgets>
class MaFenetre : public QWidget // On hérite de QWidget (IMPORTANT)
{
public:
MaFenetre();
private:
QPushButton *m_bouton;
};
#endif
MaFenetre.cpp
#include "MaFenetre.h"
MaFenetre::MaFenetre() : QWidget()
{
setFixedSize(300, 150);
m_bouton = new QPushButton("Quitter", this);
m_bouton->setFont(QFont("Comic Sans MS", 14));
m_bouton->move(110, 50);
// Connexion du clic du bouton à la fermeture de l'application
QObject::connect(m_bouton, SIGNAL(clicked()), qApp, SLOT(quit()));
}
I have shared with a below sample code i hope it would be help for you.
#include "test1.h"
#include "ui_test1.h"
#include<QDebug>
test1::test1(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::test1)
{
ui->setupUi(this);
stack = new QStackedWidget(this);
tes = new test2();
stack->addWidget(ui->pushButton);
stack->addWidget(tes);
this->setCentralWidget(stack);
stack->setCurrentIndex(0);
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(slotDisplayFen()));
}
test1::~test1()
{
delete ui;
}
void test1::slotDisplayFen()
{
qDebug()<<"test";
stack->setCurrentIndex(1);
}
The answer is just to define a custom signal on the desired window to switch , and that signal will be sent to the main window so it will display the right switch for you

Qt5/C++ release mouse during mousePressEvent

I've a QGridLayout where each cell contains my custom widget QFrameExtended defined as follow:
In .h:
#ifndef QFRAMEEXTENDED_H
#define QFRAMEEXTENDED_H
#include <QObject>
#include <QFrame>
class QFrameExtended : public QFrame
{
Q_OBJECT
private:
public:
int id;
explicit QFrameExtended(QWidget *parent = 0);
signals:
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void pressed(QFrameExtended *);
void released(QFrameExtended *);
public slots:
void on_mouse_press();
void on_mouse_release();
};
#endif // QFRAMEEXTENDED_H
In .cpp:
#include "qframe_extended.h"
QFrameExtended::QFrameExtended(QWidget *parent) : QFrame(parent)
{
this->id = /* Imagine here there is a function to generate an id */ ;
connect( this, SIGNAL( mousePressEvent(QMouseEvent*) ), this, SLOT( on_mouse_press() ) );
connect( this, SIGNAL( mouseReleaseEvent(QMouseEvent*) ), this, SLOT( on_mouse_release() ) );
}
void QFrameExtended::on_mouse_press() {
emit pressed(this);
}
void QFrameExtended::on_mouse_release() {
emit released(this);
}
My form creates the QGridLayout with the QFrameExtended widgets and for each of them defines an event handler:
/* ... */
/* This snippet of code is inside a loop that is creating frame objects */
connect(frame, &QFrameExtended::pressed, this, &MyForm::on_mouse_press);
connect(frame, &QFrameExtended::released, this, &MyForm::on_mouse_release);
/* ... */
and finally these are the event handlers:
void MyForm::on_mouse_press(QFrameExtended *frame) {
qDebug() << "Pressed here: " << frame->id << endl;
}
void MyForm::on_mouse_release(QFrameExtended *frame) {
qDebug() << "Released here: " << frame->id << endl;
}
When I click on a cell (i.e. a QFrameExtended widget) without release the button, I would see printed on the console the id of the cell. After I moved the mouse over another cell, when I release the button I would see printed the second id.
An example is an output like this:
Pressed here: 1
Released here: 3
but the reality is that when I press the mouse button over a QFrameExtended, he starting to grab all mouse events until I release the button. This is the expected behaviour:
Qt automatically grabs the mouse when a mouse button is pressed inside a widget; the widget will continue to receive mouse events until the last mouse button is released.
From: http://doc.qt.io/qt-4.8/qmouseevent.html
How can I change this behaviour? I'll really appreciate if you can give me also an example
Ok, I resolved following the tip of peppe. I tried to extend the QGridLayout but layouts don't support mouse events, because don't inherit from QWidget. So, I extended the QWidget that contains the layout.
In .h:
#ifndef QWIDGETEXTENDED_H
#define QWIDGETEXTENDED_H
#include <QWidget>
#include <QString>
#include <QMouseEvent>
#include "qframe_extended.h"
class QWidgetExtended : public QWidget
{
Q_OBJECT
public:
explicit QWidgetExtended(QWidget *parent = 0);
protected:
virtual void mousePressEvent(QMouseEvent *);
virtual void mouseReleaseEvent(QMouseEvent *);
signals:
void pressed(QFrameExtended *);
void released(QFrameExtended *);
};
#endif
In .cpp:
#include "qwidget_extended.h"
#include "qframe_extended.h"
QWidgetExtended::QWidgetExtended(QWidget *parent) : QWidget(parent)
{
}
void QWidgetExtended::mousePressEvent(QMouseEvent *event) {
QFrameExtended frame;
QWidget *widget = this->childAt(event->pos());
if (widget != NULL) {
QString widgetClassName(widget->metaObject()->className());
//I don't use explicitly the string because if one day someone changes the name of the class, the compiler will output an error
QString className(frame.metaObject()->className());
if (widgetClassName == className) {
emit pressed(dynamic_cast<QFrameExtended*> (widget));
}
}
}
void QWidgetExtended::mouseReleaseEvent(QMouseEvent *event) {
QFrameExtended frame;
QWidget *widget = this->childAt(event->pos());
if (widget != NULL) {
QString widgetClassName(widget->metaObject()->className());
//I don't use explicitly the string because if one day someone changes the name of the class, the compiler will output an error
QString className(frame.metaObject()->className());
if (widgetClassName == className) {
emit released(dynamic_cast<QFrameExtended*> (widget));
}
}
}

Qml Image doesn't refresh on source change and signal reception

I created "fruit_swap" project in Qt Creator bt choosing-- Application -> Qt Quick Application -> Qt 5.5.
In fruit_swap, 'main()' function calls forkSwapper() which forks a process that swaps fruit image (apple <--> pear) once every second.
The swapping is done inside setImageURL() method which also emits "imageURLChanged" signal for the qml. From the output(shown below at the bottom), the signal is proven to be delivered to the qml side.
I was expecting the qml Image swapping. However, it didn't. The first image shown('pear') stayed motionlessly. What could have I done wrong? Any suggestion is welcome. I uploading every single source code below.
fruit_swap.pro
/* generated by Qt Creator */
TEMPLATE = app
QT += qml quick
CONFIG += c++11
SOURCES += main.cpp \
imageitem.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
HEADERS += \
imageitem.h
DISTFILES += \
FruitFrame.qml
imageitem.h
/* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */
#include <QQuickPaintedItem>
/**
* #brief QQuickItem to show images/pixmaps/colors in a QML item
*
* As opposed to the Image from plain qml, this works on
* QImages, QPixmaps and QColors
*/
class ImageItem : public QQuickPaintedItem
{
// Q_PROPERTY(QVariant imageData READ imageData() WRITE setImageData
// NOTIFY imageDataChanged)
Q_OBJECT
Q_PROPERTY(QVariant imageURL READ imageURL() WRITE setImageURL
NOTIFY imageURLChanged)
public:
explicit ImageItem(QQuickItem *parent = 0);
/**
* \reimpl
*/
Q_INVOKABLE void paint(QPainter* painter) Q_DECL_OVERRIDE;
/**
* #brief image data u-ed by this item
* #return a QVariant wrapping the data
*/
QVariant imageData() const;
/**
* #brief Sets the image data
* #param newData
*/
void setImageData(const QVariant& newData);
QVariant imageURL() const;
/**
* #brief Sets the image data
* #param newData
*/
void setImageURL(const QVariant& fileName);
Q_SIGNALS:
/**
* #brief imageChanged
*/
void imageDataChanged();
void imageURLChanged();
private:
enum Type {
Unknown,
Pixmap,
Image,
Color
};
Type m_type;
QVariant m_imageData;
QVariant m_imageURL;
QRectF scaledRect(const QRect& sourceRect) const;
};
#endif // IMAGEITEM_H
imageitem.cpp
/* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */
#include "imageitem.h"
#include <QPainter>
#include <qobjectdefs.h>
ImageItem::ImageItem(QQuickItem *parent) :
QQuickPaintedItem(parent)
{
m_imageURL = QUrl::fromLocalFile(QString("apple.jpg"));
}
void ImageItem::paint(QPainter* painter)
{
switch(m_type) {
case Unknown: {
return;
}
case Image: {
QImage image = m_imageData.value<QImage>();
painter->drawImage(scaledRect(image.rect()), image);
return;
}
case Pixmap: {
QPixmap pixmap = m_imageData.value<QPixmap>();
painter->drawPixmap(scaledRect(pixmap.rect()).toRect(), pixmap);
return;
}
case Color: {
QColor color = m_imageData.value<QColor>();
painter->fillRect(contentsBoundingRect(),color);
return;
}
}
}
QVariant ImageItem::imageData() const
{
return m_imageData;
}
QVariant ImageItem::imageURL() const
{
return m_imageURL;
}
void ImageItem::setImageURL(const QVariant &fileName)
{
m_imageURL = QUrl::fromLocalFile(fileName.value<QString>());
if (m_imageURL.canConvert<QUrl>()) {
QUrl url = m_imageURL.value<QUrl>();
if (!url.isEmpty() && url.isValid()
&& url.isLocalFile())
{
qDebug() << "URL is valid";
} else {
qDebug() << "URL is INvalid";
}
} else {
qDebug() << "URL is INvalid";
}
emit imageURLChanged();
}
void ImageItem::setImageData(const QVariant& newData)
{
switch(newData.userType()) {
case QMetaType::QPixmap: {
m_type = Pixmap;
break;
}
case QMetaType::QImage: {
m_type = Image;
break;
}
case QMetaType::QColor: {
m_type = Color;
break;
}
default: {
m_type = Unknown;
break;
}
}
m_imageData = newData;
emit imageDataChanged();
}
QRectF ImageItem::scaledRect(const QRect& sourceRect) const
{
QRectF targetRect = contentsBoundingRect();
QSizeF scaledSize;
double widthScale = targetRect.width() / sourceRect.width();
double heightScale = targetRect.height() / sourceRect.height();
if(widthScale < heightScale) {
scaledSize.setHeight(sourceRect.height() * widthScale);
scaledSize.setWidth(sourceRect.width() *widthScale);
} else {
scaledSize.setHeight(sourceRect.height() * heightScale);
scaledSize.setWidth(sourceRect.width() *heightScale);
}
QRectF result = QRectF(targetRect.left() + targetRect.width() /2 - scaledSize.width() /2,
targetRect.top() + targetRect.height()/2 - scaledSize.height()/2,
scaledSize.width(),scaledSize.height());
// QRectF result(QPointF(0,0),scaledSize);
qDebug() << result << targetRect << sourceRect << widthScale << heightScale ;
return result;
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QImage>
#include <unistd.h>
#include "imageitem.h"
void forkSwapper(ImageItem * fImage);
int main(int argc, char *argv[])
{
qmlRegisterType<ImageItem>("ImageItem",1,0,"ImageItem");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
ImageItem *fImage = new ImageItem();
fImage->setImageURL("fruit.jpg");
engine.rootContext()->setContextProperty("cpp_imageURL", fImage);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
forkSwapper(fImage);
return app.exec();
}
void forkSwapper(ImageItem * fImage) {
int pid = fork();
if (pid == 0) {
int i = 0;
while (true) {
if (i++ % 2 == 0)
fImage->setImageURL("apple.jpg");
//std::system("cp apple.jpg fruit.jpg");
else
fImage->setImageURL("pear.jpg");
//std::system("cp pear.jpg fruit.jpg");
qDebug() << "fruit image changed";
sleep(1);
}
_exit (EXIT_FAILURE);
} else {
qDebug() << "swapper forked, PID:" << pid;
}
}
FruitFrame.qml
import QtQuick 2.5
import ImageItem 1.0
Rectangle {
property alias mouseArea: mouseArea
width: 360
height: 360
MouseArea {
id: mouseArea
anchors.fill: parent
Connections {
target: cpp_imageURL
onImageURLChanged: {
fruit_image.update();
// fruit_image.source = cpp_imageURL.imageURL;
console.log("image UURL-" + cpp_imageURL.imageURL);
}
}
Image {
id: fruit_image
x: 39
y: 94
width: 274
height: 204
source: cpp_imageURL.imageURL
cache: false
}
}
Text {
anchors.centerIn: parent
text: "Hello World"
anchors.verticalCenterOffset: -137
anchors.horizontalCenterOffset: -104
}
}
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import ImageItem 1.0
Window {
visible: true
width: 360
height: 460
FruitFrame {
anchors.fill: parent
mouseArea.onClicked: {
Qt.quit();
}
}
}
Application Output
Starting /home/jbpark03/wem/fruit_swap/build/fruit_swap...
QML debugging is enabled. Only use this in a safe environment.
URL is valid
URL is valid
qml: image UURL-file:apple.jpg
fruit image changed
swapper forked, PID: 3078
URL is valid
qml: image UURL-file:pear.jpg
fruit image changed
URL is valid
qml: image UURL-file:apple.jpg
fruit image changed
URL is valid
qml: image UURL-file:pear.jpg
fruit image changed
URL is valid
qml: image UURL-file:apple.jpg
END.
The code works perfectly well. I think the problem is you're blocking the Qt application because you're using sleep.
In fact, you see the image pear.jpg because is the first image shown after fruit.jpg and before any sleep.
If, for example, you use a QTimer or a QThread, you will check the image is properly updated.
Example:
mytimer.h
#ifndef MYTIMER_H
#define MYTIMER_H
#include <QObject>
#include <QTimer>
#include "imageitem.h"
class MyTimer : public QObject
{
Q_OBJECT
public:
explicit MyTimer(ImageItem * fImage, QObject *parent = 0);
private:
QTimer *timer;
ImageItem *myImage;
signals:
public slots:
void update();
};
#endif // MYTIMER_H
mytimer.cpp
#include <QDebug>
#include <QTest>
#include "mytimer.h"
MyTimer::MyTimer(ImageItem * fImage, QObject *parent) : QObject(parent)
{
myImage = fImage;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
}
void MyTimer::update()
{
myImage->setImageURL(":pear.jpg");
QTest::qWait(250);
myImage->setImageURL(":apple.jpg");
}
With this timer, we're going to change the image every 1 second. Now, in our main.cpp:
#include "mytimer.h"
int main(int argc, char *argv[])
{
qmlRegisterType<ImageItem>("ImageItem",1,0,"ImageItem");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
ImageItem *fImage = new ImageItem();
MyTimer *timer = new MyTimer(fImage);
fImage->setImageURL(":fruit.jpg");
engine.rootContext()->setContextProperty("cpp_imageURL", fImage);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}

Qt sending Object from a form to mainwindow

I have an assignment and I'm not too sure on how to approach it,at the moment I have 2 window.
-> MainWindow and PlayerForm.
From a menu, I call PlayerFrom and with this form I create a object player.
My question is How can I send back this object to a label in my main window ?
Player Slot :
void MainWindow::on_actionJoueur_triggered()
{
FormulaireJoueur *fj = new FormulaireJoueur;
fj->show();
}
Form OK Slot :
void FormulaireJoueur::on_OkJoueur_clicked()
{
try
{
std::string Nom = (ui->J_Nom->text()).toStdString();
std::string Prenom = (ui->J_Prenom->text()).toStdString();
std::string Telephone = (ui->J_Phone->text()).toStdString();
std::string Position = (ui->J_Pos->text()).toStdString();
QDate Date = ui->J_Date->date();
int jour = Date.day();
int mois = Date.month();
int annee = Date.year();
util::Date DateJoueur(jour,mois,annee);
Joueur NouveauJoueur(Nom,Prenom,DateJoueur,Telephone,Position);
std::string Message = NouveauJoueur.reqPersonneFormate();
}
catch(ContratException e)
{
QMessageBox::information(this,"Erreur","Erreur lors de la création du joueur.");
}
}
FormulaireJoueur.h :
#ifndef FORMULAIREJOUEUR_H
#define FORMULAIREJOUEUR_H
#include <QMainWindow>
namespace Ui {
class FormulaireJoueur;
}
class FormulaireJoueur : public QMainWindow
{
Q_OBJECT
public:
explicit FormulaireJoueur(QWidget *parent = 0);
~FormulaireJoueur();
private slots:
void on_OkJoueur_clicked();
void on_AnnulerJoueur_clicked();
private:
Ui::FormulaireJoueur *ui;
};
#endif // FORMULAIREJOUEUR_H
Container :
Annuaire AnnuairePrincipal("Canadiens");
AnnuairePrincipal.AjouterPersonne(NouveauJoueur);
edit : FormulaireJoueur should inherits from QDialog as it is a dialog
edit again : closeEvent forgotten
add Joueur at your FormulaireJoueur class, and add a public getter to it
I assumed that you use directly the Joueur type and that the copy constructor is correct
Joueur FormulaireJoueur::getJoueur()
{
return this->_joueur;
}
in your MainWindow.h add a slot
void FomulaireJoueurFinished(int return)
then in your player slot :
void MainWindow::on_actionJoueur_triggered()
{
FormulaireJoueur *fj = new FormulaireJoueur;
connect(fj, SIGNAL(finished ( int)), this, SLOT(FomulaireJoueurFinished(int return));
fj->show();
}
then in MainWindow.cpp
void MainWindow::FomulaireJoueurFinished(int return)
{
if (return == QDialog::Accepted)
this->AnnuairePrincipal.AjouterPersonne((static_cast<FormulaireJoueur *>(sender))->getJoueur());
}
you also should override closeEvent of the FormulaireJoueur Dialog
void QDialog::closeEvent ( QCloseEvent * e ) [virtual protected]
to integrate your verification and generation of Joueur