Can I emit signal from a public function?
-
Hello,
I have a simple GUI that must show and hide. I`ve made the following definitions:
@
void* doSomething2(void*);class SimpleGUI : QObject {
Q_OBJECTpublic:
SimpleGUI(QApplication* , int, char**);
~SimpleGUI();
bool isActive;
QWidget* getWindow();
signals:
void showWindow();
private slots:
void doSomething(void);void callDirwalk(void); void activate(); void deactivate(); void printDiagnostics();
private:
FILE* fp;
SimpleGUI();
SimpleGUI* self ;QApplication* qapp; QWidget* window; QPushButton *yes; QPushButton *no; QTextEdit *text; QString fname;
public:
static int argc;
static char** argv;
private:
int w;
int h;
unsigned long timeSleep;
QHBoxLayout* align;
QVBoxLayout* textLay ;
QVBoxLayout buttonsLay;
QVBoxLayout qvb;
void* doSth(void*);public:
void showApp();
void hideApp();
};
@The idea is that I connect the slots this way:
@
QObject::connect(no, SIGNAL(clicked()), window, SLOT(hide()) );
QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );
@
And from the SimpleGUI pointer, lets say spl->showApp(), the showApp body emits showWindow() signal, so this should work. But qtcreator gives me a build error: @ /home/ilian/QT5/build-SampleGame-Desktop_Qt_5_3_0_GCC_32bit-Debug/moc_SimpleGUI.cpp:147: error: multiple definition of
SimpleGUI::showWindow()'
@
no idea really... I am quite new in Qt but I am following the examples, and I don`t get why I am having this error. These are the last lines of moc:
@
// SIGNAL 0
void SimpleGUI::showWindow()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}
QT_END_MOC_NAMESPACE@
-
Hi,
You didn't implement showWindow did you ?
-
void showWindow(); is signal. Signals should not be implemented by you(programmer). So go to your cpp file and remove the showWindow(...) implementation. Then it should go fine.
-
Oh, I did... OK, that fixed the qtcreator error report. But still leaves me the question - consider this code:
@
/* somewherer in a separate main() */
startTime = endTime = time(NULL);
int qtstarted = initQtApp(spl, argc, argv);while ( 1 ) { sleep(1); if ( endTime - startTime > (5) ) { char buff[512]=""; spl->showApp(); sprintf(buff, "%d is time difference\n", endTime - startTime); writeToFile(buff, LOGOTHER, "a+"); } else { endTime = time(NULL); } }
/* ------------------------- /
int initQtApp(SimpleGUI spl, int argc, char* argv[]) {
QApplication* app= new QApplication(argc, argv);
if ( spl == NULL) spl = new SimpleGUI(app, argc, argv);
char buff[256]="";
sprintf(buff,"App created in %p, SimpleGUI in %p\n", app, spl);
writeToFile(buff, LOGOTHER, "a+");
return app->exec();
}
@
In SimpleGUI.cpp:
@
...
void SimpleGUI::showApp() {
emit showWindow();
}
@
in constructor:
@
...
QObject::connect(this, SIGNAL(showWindow()),
window, SLOT(show()) );
@
when the time is reached, spl->showApp() does nothing...
[quote author="SGaist" date="1410948603"]Hi,You didn't implement showWindow did you ?[/quote]
-
what is it supposed to do ? What is the implementation of showApp ? That should help to answer your qn.
-
I`ve update my previous poll with showApp() implementation and QObject::connect to the window and my app. showApp() emits showWinodw() signal, which is connected to window SLOT(show()). See my prev post.
-
@QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );@
When the signal showWindow().. happens, it should show the 'window' widget. When the signal is emitted what is the status of 'window'. Is it shown already somewhere ?
In order to check that, it really working, you can try with following.
QPushButton *button = new QPushButton("Showme");
QObject::connect(this, SIGNAL(showWindow()), button, SLOT(show()) )See what happens. If this is working, you must some logic issue in your program.
- There must be some logic issue
- 'window' object may have parent and parent is already shown.
-
No, I
ve never showed the window. The constructor, just connects, signals, prepares buttons, texts, etc. Then does nothing. I
ve edited the while(1) loop to wait 2 sec then call spl->showApp() without conditions, and it never shows.
[quote author="Dheerendra" date="1410955300"]@QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );@When the signal showWindow().. happens, it should show the 'window' widget. When the signal is emitted what is the status of 'window'. Is it shown already somewhere ?
In order to check that, it really working, you can try with following.
QPushButton *button = new QPushButton("Showme");
QObject::connect(this, SIGNAL(showWindow()), button, SLOT(show()) )See what happens. If this is working, you must some logic issue in your program.
- There must be some logic issue
- 'window' object may have parent and parent is already shown.
[/quote]
-
As far as I am getting any progress, it appears, that showApp() must appear before app->exec() function, otherwise it does not work. However, this makes writing the app to be called from a UNIX daemon hard. How exactly to handle this exec() problem? I just want my GUI to show in fixed intervals.
-
Did you try with pushbutton example I gave you ? Did it show pushbutton ? Also can you show me the piece of code where you are creating window object ?
-
Yes, the SIGNAL/SLOT is working, I`ve tried it out. But it appeared that everything must happen in oreder and finishes with app->exec(). Here is my code in the while(1) loop, it works only one time, it shows the app jsut once. Once I press the PRINT TO LOG BUTTON, which is connected to window SLOT(hide()), it never appears
@
time_t startTime ;
time_t endTime ;
startTime = endTime = time(NULL);
SimpleGUI* spl = NULL;
while (1) {
sleep(2);
if ( endTime - startTime > (2) ) {
char buff[512]="";
sprintf(buff, "%d is time difference\n",
endTime - startTime);
writeToFile(buff, LOGOTHER, "a+");
int qtstarted = initQtApp(spl, argc, argv);
}
else {
endTime = time(NULL);
}
}
...
int initQtApp(SimpleGUI* sp, int argc, char* argv[]) {
QApplication* qapp= new QApplication(argc, argv);
if ( sp != NULL ) sp->showApp();
else {
sp = new SimpleGUI(qapp, argc, argv);
sp->showApp();
}
char buff[256]="";
sprintf(buff,"App created in %p, SimpleGUI in %p\n", qapp, sp);
writeToFile(buff, LOGOTHER, "a+");
return qapp->exec();
}
@
initQtApp simulates a main()
And here is the constcution of the SimpleGUI, only the important part:
@
SimpleGUI::SimpleGUI(QApplication* app, int args, char** argvs)
: qapp(app) {
isActive = true;
window = new QWidget;
yes = new QPushButton("STOP DAEMON");
no = new QPushButton("PRINT TO LOG FILE");
buttonsLay = new QVBoxLayout;
textLay = new QVBoxLayout;
qvb = new QVBoxLayout;
align = new QHBoxLayout;
text = new QTextEdit("TEST FOR TEXT AREA");
text->setEnabled(false);
text->setMaximumHeight(200);
text->setMaximumWidth(200);
text->setMinimumHeight(200);
text->setMinimumWidth(200);window->setMinimumHeight(320); window->setMaximumHeight(320); window->setMinimumWidth(320); window->setMaximumWidth(320); yes->setMinimumWidth(200); yes->setMaximumWidth(200); no->setMinimumWidth(200); no->setMaximumWidth(200); textLay->addWidget(text); buttonsLay->addWidget(yes); buttonsLay->addWidget(no); qvb->addLayout(textLay); qvb->addLayout(buttonsLay); align->addLayout(qvb); window->setLayout(align); SimpleGUI::argc = args; SimpleGUI::argv = argvs; QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show())); QObject::connect(no, SIGNAL(clicked()), this, SLOT(callDirwalk()) ); QObject::connect(no, SIGNAL(clicked()), window, SLOT(hide())) ; //[1] ok - stops daemon QObject::connect(yes, SIGNAL(clicked()), this, SLOT(deactivate()) );
}
QWidget* SimpleGUI::getWindow() {
return window;
}void SimpleGUI::callDirwalk() {
//thread main()
writeToFile("Called dirwalk on separate thread\n", LOGOTHER, "a+");
pthread_t t;
int res =0;
res = pthread_create(&t, NULL, doSomething2, NULL);}
void SimpleGUI::activate() {
}
void SimpleGUI::deactivate() {
delete this;
}
void SimpleGUI::printDiagnostics() {}
void SimpleGUI::showApp() {
emit this->showWindow();
}
void SimpleGUI::hideApp() {
window->hide();
}void SimpleGUI::doSomething() {
delete this;
QObject::connect(qapp, SIGNAL(aboutToQuit()),
qapp, SLOT(quit()) );
//}
@
[quote author="Dheerendra" date="1410958444"]Did you try with pushbutton example I gave you ? Did it show pushbutton ? Also can you show me the piece of code where you are creating window object ?[/quote] -
Another thing, when I press window
s X on the frame, it reappears again, but globs memory as much as I close it from X. I
ve tried to make some instances static, but it does nothing at all... Just to tell you that my log file says:
@
App created in 0x96807d8, SimpleGUI in 0x9783f20App created in 0x96807d8, SimpleGUI in 0x97cf758
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x97e5320
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x97f0d00
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x9800e80
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x98077f8
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x980dcb8
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x9813978
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x981a6f8
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x9824fd0
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x982b618
4 is time difference
App created in 0x96807d8, SimpleGUI in 0x9831c30
App terminated
App created in 0x93ad7d8, SimpleGUI in 0x94b0f98
App created in 0x9462210, SimpleGUI in 0x94fc8d0
5 is time difference
App created in 0x94fc6f0, SimpleGUI in 0x951cdb8
5 is time difference
App created in 0x95138a0, SimpleGUI in 0x951cf78
App terminated
@
If initQtApp() has non-static QApplication variable, if its static App
s address is constant, just SimpleGUI changes. But the previous GUI is not freed properly and task manager reports increase in MB needed for the program ... :( -
Your code is pretty convoluted for what seems to be a simple task. Can you tell us what exactly would you like to achieve ?
-
Yes. I am starting a daemon in linux. In fixed intervals, I want it do display an UI in Qt. The UI is responsible to call 3 special functions, all involving an iteration in a list ( as stack ). The 3 functions are Qt independant in pure C. It`s a directory walk, which puts all filenames and dir names in a linked list. Then, depending on the callback, you can either print directories/files, delete them, or crypt them. I tough it will be as simple as that, but ... here I am stuck here.
-
I`ve made this in Java with a new thread which sleeps for N time, then shows the frame, the user click just hides it... Simple. But I want this app to be different. The UI must be versatile, either Qt, either GTK, maybe JUCE++. So I want logics to be separate from the UI. I am saying it because, many would suggest that I have to do it in pure Qt.
-
If you want to write a real daemon, then don't put GUI code in it. A daemon doesn't have a GUI.
Completely separate both and use e.g. D-Bus or another RPC to communicated with your daemon.
-
This is not what I wanted to hear. I can simply put a sleep in GUI constructor or method, then just emit show - hide. It
s simple and tested, however, I wanted that kind of behaviour, and almost achieved it, but it appears my old code with recreation of Qt app will be added :( Too bad it
s not as simple as just show hide.
[quote author="SGaist" date="1411025456"]If you want to write a real daemon, then don't put GUI code in it. A daemon doesn't have a GUI.Completely separate both and use e.g. D-Bus or another RPC to communicated with your daemon.[/quote]
-
Then don't make it a daemon. Just to be sure we understand each other, a thread running in the background doesn't qualify as daemon.
Have a look at QThread's documentation and the worker object part. You can couple that with e.g. a QTimer and then you have your function called at regular interval done in a thread.
-
Yes, I
ve figured it out... The java thing I
ve made... A sleeping thread with show/hide. OK, since I am not the type that will just walk aside Ive came with a solution, just a bit messy but, worked like a charm. Here is the daemon infinite loop: @ qapp = new QApplication(argc, argv); while (1) { do { sleep(1); initQtApp(NULL, argc, argv, 0); /* ok logic */ if ( endTime - startTime > (5) ) { char buff[512]=""; sprintf(buff, "%d is time difference\n", endTime - startTime); writeToFile(buff, LOGOTHER, "a+"); } else { endTime = time(NULL); } } while ( qapp->exec() == 0); } @ Now... qapp is global static variable. initQtApp() has local SimpleGUI pointer that is recreated everytime. I
ve figured out that app->exec() will behave for the SimpleGUI associated with. So my log file says:
@
App created in 0x95207d8, SimpleGUI in 0x962f0d8
8 is time difference
-1 is isRunning now
App terminated
App created in 0x95207d8, SimpleGUI in 0x9677820
8 is time difference
Called dirwalk on separate thread
Called a separate thread foo()
CREATED:2014:09:18:14:28:46
App created in 0x95207d8, SimpleGUI in 0x967a000
8 is time difference
Called dirwalk on separate thread
Called a separate thread foo()
@
Pressing the STOP DAEMON just calls a SLOT that simply deletes window, textframe and the 2 buttons, nothing much, also reports some variables for the daemon shared with get/set functions, since they are static. This loop is not final one, but somehow manages to create a new GUI in every second, then wait, and when I destroy it, it just recreates it. TODO is to connect the right signals and slots to the coresponding buttons, and one question actually - can I disable the X button close function? It behaves right now, since close destroys the window, and daemon recreates it but still...
[quote author="SGaist" date="1411033968"]Then don't make it a daemon. Just to be sure we understand each other, a thread running in the background doesn't qualify as daemon.Have a look at QThread's documentation and the worker object part. You can couple that with e.g. a QTimer and then you have your function called at regular interval done in a thread.[/quote]