How can I get information back after closing my main window in Qt?
Hi I am new to C ++ and I am trying to create a program on Ubuntu that will display the output of the Opengazer software (gaze tracking software) on multiple devices and return a single coordinate. This is done by opening a UDP socket for each device, which then sends text output of the form [Xcoordinate Ycoordinate] to the main program, where the numbers will be compared and then the correct coordinate will be printed.
I found that creating a gui in Qt is the best way to set the relative positions of each device. Basically, the problem I ran into was getting the UDP socket information to the main program. In the getInfo function I create a main window in which my devices (another class called DeviceWidget) are created and can be navigated to set their relative positions. Each DeviceWidget has a UDP socket associated with it. I would like to return a QList of all DeviceWidgets when the window is closed, but I find it difficult because when the window is closed, all children are destroyed. I also read that buttons cannot return values, so that won't work either.
I am posting main.cpp and window.cpp. I can post more, but I believe these are the only ones that are needed.
Any ideas? Thank you for your time.
Main.cpp
#include <QApplication>
#include "window.h"
#include "devicewidget.h"
#include <QTimer>
QList<DeviceWidget*> getInfo(int argc, char *argv[]);
void delay();
int main(int argc, char *argv[])
{
bool run = true;
int numDevices, space, size;
DeviceWidget *point;
QList<DeviceWidget*> dList = getInfo(argc, argv);
numDevices = dList.size();
int xPos[numDevices], yPos[numDevices];
QString buffers[numDevices], xString, yString;
//begin tracking gaze
if(run)
{
for(int i=0; i<numDevices; i++)
{
//get output of opengazers
point = dList.at(i);
buffers[i] = point->Server->getBuffer();
space = buffers[i].indexOf(" ");
size = buffers[i].size();
xString = buffers[i].left(space);
yString = buffers[i].right(size-space-1);
xPos[i] = xString.toInt();
yPos[i] = yString.toInt();
}
//print coordinate
for(int i=0; i<numDevices; i++)
{
if((dList.at(i)->getXRes()/6<xPos[i]<dList.at(i)->getXRes()*5/6) && (dList.at(i)->getXRes()/4<xPos[i]<dList.at(i)->getXRes()*3/4))
{
qDebug() << xPos[i]+dList.at(i)->getXPos()*9-dList.at(0)->getXPos()*9 << " " << yPos[i]+dList.at(i)->getYPos()*9-dList.at(0)->getYPos()*9;
}
}
delay();
}
return 0;
}
QList<DeviceWidget*> getInfo(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
a.exec();
return w.getList();
}
void delay()
{
QTime dieTime= QTime::currentTime().addSecs(1);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
window.cpp
#include "window.h"
#include <QFrame>
#include <QPushButton>
#include <QVBoxLayout>
#include <devicewidget.h>
#include <QWidget>
#include <QDesktopWidget>
#include <QList>
#include "portdialog.h"
#include "udp.h"
Window::Window(QWidget *parent) :
QWidget(parent),
frame(new QFrame(this)),
addButton(new QPushButton("Add Device", this)),
doneButton(new QPushButton("Done", this))
{
QVBoxLayout *layout = new QVBoxLayout;
frame->setLineWidth(2);
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
QPoint topLeft(0,0);
QPoint bottomRight(100,100);
const QRect rect(topLeft, bottomRight);
frame->setFrameRect(rect);
frame->setFixedHeight(300);
frame->setFixedWidth(500);
layout->addWidget(frame);
layout->addWidget(addButton);
layout->addWidget(doneButton);
setLayout(layout);
connect(addButton, SIGNAL(released()), this, SLOT(on_addButton_pressed()));
connect(doneButton, SIGNAL(released()), this, SLOT(on_doneButton_pressed()));
DeviceWidget *primary = new DeviceWidget(frame, 200, 200, 20230);
primary->setFixedHeight(getResolutionY()/10);
primary->setFixedWidth(getResolutionX()/10);
primary->show();
primary->move(200,200);
list.append(primary);
}
void Window::on_addButton_pressed()
{
//pop-up for port
PortDialog *pop = new PortDialog(this);
pop->exec();
int port = pop->getPort();
/*int xRes = pop->getXRes();
int yRes = pop->getYRes();*/
int xRes = 1360;
int yRes = 760;
//create and show widget
DeviceWidget *secondary = new DeviceWidget(frame, 200, 200, port);
secondary->createServer(port, xRes, yRes);
secondary->setFixedHeight(secondary->getYRes() / 9);
secondary->setFixedWidth(secondary->getXRes() / 9);
secondary->show();
secondary->move(200,200);
list.append(secondary);
}
void Window::on_doneButton_pressed()
{
this->close();
}
int Window::getResolutionX()
{
QDesktopWidget widget;
QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
return mainScreenSize.width();
}
int Window::getResolutionY()
{
QDesktopWidget widget;
QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
return mainScreenSize.height();
}
QList<DeviceWidget*> Window::getList()
{
return list;
}
source to share
It's a good thing too much code, I think next time I'll try to be more concise. (We don't care if your frame is 300x500 or whatever: p)
I don't like what you did here:
PortDialog *pop = new PortDialog(this);
pop->exec();
int port = pop->getPort();
I think you can overcome your problem using signal and slots. In your PortDialog you do your stuff when you want to get a value (computed, user written, whatever) you justemit(sigPortValue(int val));
And in your function, void Window::on_addButton_pressed()
you can write
void Window::on_addButton_pressed()
{
//pop-up for port
PortDialog *pop = new PortDialog(this);
connect(pop, SIGNAL(sigPortValue(int), this, SLOT(slotHandlePortValue(int));
pop->exec();
[...]
}
and obviously handling the port value in the slot discussed above. So the first point.
The second point was about QList. To be clear, this QList<DeviceWidget*> getInfo(...)
is a function that returns a copy of a QList. QList about what? Pointers to DeviceWidget. When you copy a list, you are copying the contents of the list (as you specify here), but you are not specifying objects. And since your DeviceWidgets have a MainWindow as a parent, they are removed (you got that right!).
I see two solutions:
orphan decision
Instead of writing, DeviceWidget *primary = new DeviceWidget(frame, 200, 200, 20230);
you can omit frame
, so without any parent the DeviceWidget won't be automatically deleted. Pay attention to the correct delete
object though!
another way of communication
Instead of trying to pass information directly in code, you can store the information in a file, but it's up to you to decide which is the best solution for your needs.
Hope this helps you;)
source to share
If your Window can be retrieved from a QDialog, you can use it QDialog::exec()
to control the event loop locally.
If I understand your question correctly, it seems that you are doing something similar to what you are asking: it shows QDialog
with QTextEdit
which you can enter text, and as soon as you close that window, the main function just continues, shows QDialog
which gets information from QTextEdit
and displays it.
Does this help or am I misunderstanding where your problem is?
#include <QApplication>
#include <QDialog>
#include <QGridLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QLabel>
int main(int argc, char** argv)
{
QApplication app(argc,argv);
// show a dialog that lets you enter text
QDialog dialog;
QGridLayout layout(&dialog);
QTextEdit edit;
layout.addWidget(&edit);
// this will block until the window is closed
dialog.exec();
// open a new dialog....
QDialog closeMe;
QGridLayout layout2(&closeMe);
QLabel label;
// ... retrieve the text from the dialog we created first
label.setText(QObject::tr("You entered: ")+edit.toPlainText());
QPushButton button("Click here to close application");
layout2.addWidget(&label,0,0);
layout2.addWidget(&button,1,0);
QObject::connect( &button, SIGNAL( clicked() ), &closeMe, SLOT( accept() ) );
closeMe.show();
return app.exec();
}
source to share