PDA

View Full Version : QPushButton and connect problem(((



make
11th June 2011, 09:56
hi! I am new to qt and now I have a little problem((



int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QWidget wnd;
wnd.resize(200, 100);
wnd.setWindowTitle("w3.cpp");
wnd.show();

QPushButton *btn = new QPushButton("Press Me", &wnd);
QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setText("hi!")));
btn->move(50, 40);
btn->show();

return app.exec();
}


i just want to do such thing - after clicking button its text changes to "hi"))
where is my mistake??? help please((

Lesiok
11th June 2011, 10:04
Signal void my_signal() must be connected to slot void my_slot(). Read about QSignalMapper

wysota
11th June 2011, 10:06
http://www.qtcentre.org/faq.php?faq=qt_signalslot#faq_qt_signalslot_with_v alues

Zlatomir
11th June 2011, 10:08
There are a lot of issues there:
1) the signature of signal must match with the one of the slot (or the slot must be available to be called with the arguments of the signal - in case the slot has default values for arguments)
2) on the connect statement you don't pass variable names, you don't pass variable values - you can write there only type names

What you want it can be done by inheriting your own button from QPushButton and write it a slot SetDefaultText and code the string parameter to have a default value.

You can read more about signals and slots here (http://doc.qt.nokia.com/4.7/signalsandslots.html)

make
11th June 2011, 12:36
i've rewritten my code a bit but it still does not work((


//w3.cpp
#include <mybutton.h>
#include <QObject>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

mybutton *btn = new mybutton("Press me)))");
QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setTxt("hi!")));
btn->show();

return app.exec();
}




//mybutton.h
#include <QtGui>
#include <QString>

class mybutton : public QPushButton
{
public:
mybutton();
mybutton(QString txt);

public slots:
void setTxt(QString txt);
};





//mybutton.cpp
#include <mybutton.h>

mybutton::mybutton()
{
}

mybutton::mybutton(QString txt)
{
setText(txt);
}

void mybutton::setTxt(QString txt)
{
setText(txt);
emit clicked();
}

what should i do??

wysota
11th June 2011, 12:43
Follow the link I gave you. Pay attention to how your signal/slot connection looks like.

make
11th June 2011, 17:22
Can someone tell me what should i do with signals and slots to make my app working??? because i just do not know what to to((( please....

Zlatomir
11th June 2011, 18:22
In your class declaration you forgot some things:
1) the Q_OBJECT macro (you need that for signals and slots to work)
2) you didn't put a default parameter for the slot. (slot declaration should be something like: public slots: void setTxt(QString txt = "Hi!"); ) and connect doesn't have anything else but type - no variable name, no value

//don't forget to Rebuild after you add the Q_OBJECT macro (maybe clean all then run qmake and rebuild)

And also you might want to take a QWidget* as a parent and pass it to the QPushButton constructor (so that you won't have memory leaks in your class)

make
13th June 2011, 10:58
i have finally done that/ but it still does not work((( maybe there are new mistakes??


//mybtn.h
#ifndef MYBTN_H
#define MYBTN_H

#include <QtGui>
#include <QString>

class mybtn : public QPushButton
{
Q_OBJECT

public:
mybtn(QString txt);

public slots:
void setTxt(QString txt = "hi!");
};

#endif


//mybtn.cpp
#include <mybtn.h>

mybtn::mybtn(QString txt)
{
setText(txt);
}

void mybtn::setTxt(QString txt)
{
setText(txt);
emit clicked();
}

//w3.cpp
#include <mybtn.h>
#include <QApplication>
#include <QObject>

int main(int argc, char **argv)
{
QApplication app(argc, argv);

mybtn *btn = new mybtn("Press me))");
QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setTxt(QString)));
btn->show();

return app.exec();
}

the application compiles successfully but the button does not change its text((

Lesiok
13th June 2011, 12:03
Did You read my previous post ? I think : NO.
This is a warning from Qt when Yout try make connection :

QObject::connect: Incompatible sender/receiver arguments
mybtn::clicked() --> mybtn::setTxt(QString)

make
13th June 2011, 12:39
so what should i do with signal clicked()?? i just do not understand((

wysota
13th June 2011, 13:21
Look, here is your connect statement:

QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setTxt(QString)));
It says -- whenever btn emits signal clicked(), call method setTxt() on btn, passing it a QString argument. Now the basic question is, what argument (value) should Qt pass to the setTxt() call in this particular situation? Do you think your statement makes sense? Why? If not, what needs to be changed for it to make sense?

make
13th June 2011, 14:00
but i thought that:



2) on the connect statement you don't pass variable names, you don't pass variable values - you can write there only type names


so i have written the default value in class implementation...

Zlatomir
13th June 2011, 14:19
Yes, what i said remains valid, but in your particular case you don't pass anything - because the clicked signal has void parameters and if the slot (member function) has default arguments (void setTxt(QString txt = "hi!"); ) so it can be called with void parameter ( just setTxt() ) - and it will just use the default value.

So the connect statement will be:

QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setTxt())); //no QString here (it will use the default)

//Read the documentation for signal and slots (i gave you a link in my first post)

LE: Also the setTxt slot should not emit clicked signal (you end up with an infinite loop) so delete/comment the line: emit clicked(); from void mybtn::setTxt(QString txt) {...}

make
14th June 2011, 08:52
Yes!!! thanks to all!! if finally works)) a bit later i will post full working code for other beginners)) (i should say that such little program is done much more simple using gtk)
but now i have the last question:
why is it necessary to write in header file such definitions like:


//myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

//...........

#endif

wysota
14th June 2011, 09:56
It is not necessary to write such definitions. Remove it, try compiling the project and if it fails, read the error message.

As for what you said about GTK -- I somehow doubt it :) Especially that GTK is C-based. We can even make a contest -- you post GTK code that does what you want and I post Qt code that does the same. Then I will post some short Qt program that does something and you'll post its GTK equivalent and we'll compare them together, ok?

make
15th June 2011, 13:08
As for gtk i can say now that i was wrong((( So there will not be any challange because i just do not know gtk on the good level))) some month ago i was choosing DE for using (gnome xfce or kde) and i also looked for information about development native programs for these DE)) that is why i was a bit interested in gtk and Vala)))
here is equivalent in vala


//gtk1.vala
using Gtk;

int main(string argc[])
{
Gtk.init(ref argc);

var wnd = new Window();
wnd.title = "Gtk1";
wnd.set_default_size(300, 50);
wnd.destroy.connect(Gtk.main_quit);

var btn = new Button.with_label("Click me :))");
btn.clicked.connect(() =>
{
btn.label = "Thank you!";
});
wnd.add(btn);

wnd.show_all();

Gtk.main();
return 0;
}



but now i am using kde that is why i started with qt))) that is why i am here)))

here is FULL QT CODE for this simple program))



//mybtn.h
#ifndef MYBTN_H
#define MYBTN_H

#include <QtGui>
#include <QString>

class mybtn : public QPushButton
{
Q_OBJECT

public:
mybtn();
mybtn(QString title);
mybtn(QString title, QWidget *wnd);

public slots:
void setTxt(QString txt = "hi!");
};

#endif





//mybtn.cpp
#include <mybtn.h>

mybtn::mybtn()
{
}

mybtn::mybtn(QString title)
{
setText(title);
}

mybtn::mybtn(QString title, QWidget *wnd) : QPushButton(title, wnd)
{
setText(title);
}

void mybtn::setTxt(QString txt)
{
setText(txt);
}




//w3.cpp
#include <mybtn.h>
#include <QApplication>
#include <QObject>

int main(int argc, char **argv)
{
QApplication app(argc, argv);

QWidget wnd;
wnd.resize(200, 100);
wnd.setWindowTitle("w3");
wnd.show();

mybtn *btn = new mybtn("Press me))", &wnd);
QObject::connect(btn, SIGNAL(clicked()), btn, SLOT(setTxt()));
btn->resize(100, 25);
btn->move(50, 35);
btn->show();

return app.exec();
}

wysota
15th June 2011, 13:24
Cheating by using a language with lambda functions doesn't prove superiority of GTK (try doing the same in C). Especially when Qt can use JavaScript or Python to do a similar cheat ;)

But let's focus on C++ and cheat there:

#include <QtGui>
int main(int argc, char **argv){
QApplication app(argc, argv);
QPushButton b("text");
QSignalMapper m;
m.setMapping(&b, "hi");
connect(&b, SIGNAL(clicked()), &m, SLOT(map()));
connect(&m, SIGNAL(mapped(QString)), &b, SLOT(setText(QString)));
b.show();
return app.exec();
}

make
15th June 2011, 13:41
WOW))) I like it )) thanks for sample))) i could not follow your advice earlier because i just did not understand)

wysota
15th June 2011, 13:58
Remember it is just a cheat that is not good for production use. Normally you wouldn't want to expose a button like that and surely using a QSignalMapper for such thing is an overkill.

Now let's reverse the situation, implement this using GTK/Vala:


#include <QtGui>
int main(int argc, char **argv){
QApplication app(argc, argv);
QWidget window;
QHBoxLayout *l = new QHBoxLayout(&window);
QPushButton *b1 = new QPushButton("b1");
QPushButton *b2 = new QPushButton("b2");
l->addWidget(b1);
l->addWidget(b2);
QSizePolicy policy = b1->sizePolicy();
policy.setHorizontalStretch(1);
b1->setSizePolicy(policy);
policy.setHorizontalStretch(3);
b2->setSizePolicy(policy);
window.show();
return app.exec();
}

In text: prepare a window with two push buttons that occupy the whole width of the window in such a way that the width of the button on the left is always 1/3 the width of the button on the right.

make
15th June 2011, 17:35
you did not understand me((( i do not know neither gtk nor vala(( that code was in samples that is why i showed it to you))

wysota
15th June 2011, 18:38
Well, you didn't say the code you posted was not yours :) Never mind...