PDA

View Full Version : Problem with slot



beerkg
13th August 2006, 15:47
Hi,

I've got this slot:

void mySlot(int flags);

next i connect this slot with some button:

connect(button1,SIGNAL(clicked()),this,SLOT(mySlot (1)));

when i click the button nothing happens. Earlier i had this same slot without any arguments and everything works well. I dont know why it isnt working now.

Thanks.

jpn
13th August 2006, 15:58
You can put only argument types (and they must match with a few exceptions) into connect statement. You cannot put any parameter values nor names.

Further reading: Signals and Slots (http://doc.trolltech.com/4.1/signalsandslots.html)

PS. You can give the "flags" parameter a default value and leave it out of the connect statement..

mickey
13th August 2006, 16:04
because signal argument has to be the same type of slot argument;
you're trying to connect signal(void) to slot(int); you should see a "console message" that says this; I think you can't in this way.....
For your aim, you can use QSignalMapper class; otherwise you can know the button clicked so:


class::myslot() {
QPushButton* button = (QPushButton*) sender();
if (button == button1) ..........
}

beerkg
13th August 2006, 16:13
Thanks guys for fast replay. I've solved my problem. I wanted this slot to has argument that i could know the sender. Now this is not neded. I found this method in the documentation: sender() which returns a pointer to the object that sent the signal. So all my problems are solved. Once again thank you.

mistertoony
22nd March 2007, 15:23
I have a slightly different situation. I have a two sliders (horizontal, vertical), which I would like to scale items in a QGraphicsView. I tried to implement this in the following way:

public slots:
void process(int, int);

//this would idealy draw the items, add them to scene, and display in view without any scaling
connect(pushButton, SIGNAL(clicked()), this, SLOT(process(1,1)));

//this would scale horizontally only
connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(process(int,1)));

//this would scale vertically only
connect(verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(process(1,int)));

In this way, process would receive the parameter for a horizontal change in scale, without any changes in the vertical scale. And vice versa. However, as previously noted neither the button nor sliders work in this case. What is the best way to accomplish this?

high_flyer
22nd March 2007, 15:40
//this would idealy draw the items, add them to scene, and display in view without any scaling
connect(pushButton, SIGNAL(clicked()), this, SLOT(process(1,1)));


As it was said in the post above, you can give values in a connect() statment.
i.e you can't do this-> process(1,1).
Also, this connect statment makes no sense, since clicked() doesn't deliver any paremeters.
you should do:

connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));
And define process() accordingly.



//this would scale horizontally only
connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(process(int,1)));


Again the same thing:

connect(horizontalSlider, SIGNAL(valueChangedRight(int)), this, SLOT(processRight(int)));
connect(horizontalSlider, SIGNAL(valueChangedLeft(int)), this, SLOT(processLeft(int)));

I know these signals do not exist, but the connect statment is correct.
You will have to insert some logic that analyzes if it is an incriment or decriment, by the current and previous slider values.
so:


connect(horizontalSlider, SIGNAL(valueChangedRight(int)), this, SLOT(process(int)));

void MyClass::process(int pos)
{
if(pos > prevPos) //we moved right
else //we moved left
}

mistertoony
22nd March 2007, 16:03
Your post is very helpful and has helped me to understand the signals and slots much better. However my problem is that by creating new slots (for example, processRight(int) and processLeft(int)) I do not have access to the items created under the original process() which are required for me to scale. Maybe I have overlooked a point that you have made that allows me to accomplish this?

high_flyer
22nd March 2007, 16:07
Did you read the last part of my post? (may be not, since I edit it)
You don't need to create new slots, make one slot that connects to the valueChangedRight(int) signal, and use logic code to see if you moved right or left.

mistertoony
22nd March 2007, 16:22
I hope you are not getting frustrated, but I have difficulty understanding how this works. Based on what I understand I have:


public slots:
void process();
void processRight(int);

and:


test1::test1() {
setupUi(this);

connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));
connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(processRight(int)));
}

void test1::processRight(int pos) {
}

void test1::process() {
QGraphicsScene *scene = new QGraphicsScene(0,0,samples*10,-115);
QGraphicsPathItem *polyItemA = scene->addPath(pathA, QPen(Qt::green), QBrush(Qt::green, Qt::NoBrush));
graphicsView->setScene(scene);
}

You are saying that I need to write code in the function processRight(int) to determine whether it increments/decrements? But I still do not understand how I will be able to scale my item, for instance (polyItemA->scale(x,y).

high_flyer
22nd March 2007, 17:37
I hope you are not getting frustrated
not at all, this forum is for people to ask questions.
If I would get frustrated I would not answer questions here (and ask some as well) ;)

You are saying that I need to write code in the function processRight(int)
No I said:

You don't need to create new slots, make one slot that connects to the valueChangedRight(int) signal,
So:


//deifne in test1.h:
// m_prevPos; //initialize at start
test1::test1() {
setupUi(this);
connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));
connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(processSlider(int)));
}
void test1::processSlider(int pos) {
if(pos<m_prevPos)
{
//your code for what ever happens when you move left
}
else {
//your code for what ecer happens when you move right
}
m_prevPos = pos;
}

mistertoony
23rd March 2007, 15:24
Thanks for the further clarification. The only problem with the code posted above is that the function processSlider:
//your code for what ever happens when you move left When I move left, the code that I would enter here needs to access an item that I call in process() (polyItemA). How can I access this item from processSlider?

high_flyer
23rd March 2007, 15:32
I don't see the problem...
Just access it as you would in process()...

mistertoony
26th March 2007, 17:11
I don't see the problem...
Just access it as you would in process()...

error C2065: 'polyItemA' : undeclared identifier

high_flyer
26th March 2007, 17:28
post your code please

mistertoony
26th March 2007, 17:39
test1::test1() {
setupUi(this);

connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));
connect(horizontalSlider, SIGNAL(valueChangedRight(int)), this, SLOT(processRight(int)));
}

void test1::processRight(int pos) {
if(pos>prev_pos) {
polyItemA->scale(pos,1);
}
prev_pos = pos;
}

void test1::process() {

std::string string2 = "test.scf.scf";

ReadSFF sff(string2);

//int bases = sff.getNum();
//QString Q_bases = QString::number(bases);
//textEdit->append("Number of Bases: " + Q_bases);

uint_4 samples = sff.returnNumSamples();
//QString Q_samples = QString::number(samples);
//textEdit->append("Number of Samples: " + Q_samples);

uint_2 *sA = new uint_2[samples];
uint_2 *sC = new uint_2[samples];
uint_2 *sG = new uint_2[samples];
uint_2 *sT = new uint_2[samples];
const int size = samples;

QPolygonF polygonA;
QPolygonF polygonC;
QPolygonF polygonG;
QPolygonF polygonT;

int xScale = 10;
int yScale = 10;

for (int i=0; i<size; i++) {
sA[i] = sff.returnSamples_A(i);
sC[i] = sff.returnSamples_C(i);
sG[i] = sff.returnSamples_G(i);
sT[i] = sff.returnSamples_T(i);

if ((sA[i]/yScale) > 125) {
polygonA << QPointF(xScale*i,-125);
} else {
polygonA << QPointF(xScale*i,-(sA[i]/yScale));
}

if ((sC[i]/yScale) > 125) {
polygonC << QPointF(xScale*i,-125);
} else {
polygonC << QPointF(xScale*i,-(sC[i]/yScale));
}

if ((sG[i]/yScale) > 125) {
polygonG << QPointF(xScale*i,-125);
} else {
polygonG << QPointF(xScale*i,-(sG[i]/yScale));
}

if ((sT[i]/yScale) > 125) {
polygonT << QPointF(xScale*i,-125);
} else {
polygonT << QPointF(xScale*i,-(sT[i]/yScale));
}
}

QGraphicsScene *scene = new QGraphicsScene(0,0,samples*10,-115);

QPainterPath segPath;
segPath.lineTo(0,-5);
segPath.closeSubpath();

QPainterPath pathA;
QPainterPath pathC;
QPainterPath pathG;
QPainterPath pathT;

pathA.addPolygon(polygonA);
pathC.addPolygon(polygonC);
pathG.addPolygon(polygonG);
pathT.addPolygon(polygonT);

QGraphicsPathItem *polyItemA = scene->addPath(pathA, QPen(Qt::green), QBrush(Qt::green, Qt::NoBrush));
QGraphicsPathItem *polyItemC = scene->addPath(pathC, QPen(Qt::blue), QBrush(Qt::green, Qt::NoBrush));
QGraphicsPathItem *polyItemG = scene->addPath(pathG, QPen(Qt::black), QBrush(Qt::green, Qt::NoBrush));
QGraphicsPathItem *polyItemT = scene->addPath(pathT, QPen(Qt::red), QBrush(Qt::green, Qt::NoBrush));
// QGraphicsPathItem *segPath1 = scene->addPath(segPath, QPen(Qt::gray), QBrush(Qt::green, Qt::NoBrush));
// QGraphicsPathItem *segPath2 = scene->addPath(segPath, QPen(Qt::gray), QBrush(Qt::green, Qt::NoBrush));

polyItemA->setPos(0,0);
polyItemC->setPos(0,0);
polyItemG->setPos(0,0);
polyItemT->setPos(0,0);
// segPath1->setPos(0,-20);
// segPath2->setPos(10,-20);

//polyItemA->scale(xSlide,1);

graphicsView->setScene(scene);


}

high_flyer
26th March 2007, 17:45
The compiler is right:
Look at test1::processRight(int pos) :
You are using polyItemA without defining it first.
Try:


void test1::processRight(int pos) {
if(pos>prev_pos) {
QGraphicsPathItem *polyItemA = scene->addPath(pathA, QPen(Qt::green), QBrush(Qt::green, Qt::NoBrush));
polyItemA->scale(pos,1);
}
prev_pos = pos;
}

mistertoony
26th March 2007, 17:47
After trying your suggestion, I get the error:


.\test1.cpp(15) : error C2065: 'pathA' : undeclared identifier

I am wondering if there is even a way to accomplish this without getting all the data and drawing all the polygons again. Is this the best way to scale using the sliders?

high_flyer
26th March 2007, 17:49
Well, then define 'pathA'.
These compiler errors are VERY clear, try thinking on your own a second before you post them here.
You posted 2 minutes after my post with the new error, which is exactly the same as the one before.
We help gladly, but try to think the problem on your own first!

mistertoony
26th March 2007, 17:55
I am only showing you this, to explain to you that the polygons I am drawing are based on large data sets that must be imported and stored. I originally tried to explain that the process() function brings in all of this data, stores the data using QPolygonF, adds the polygon as a QPainterPath, and adds the path as a QGraphicsPathItem. I then explained that all the items I need to scale were stored and created under the process() function, and if you are now telling I essentially need to re-input the data in the same data structures and essentially copy all the code from process() into processRight(), then I believe there was a misunderstanding along the way. This was something that I was initially trying to avoid. But if you are telling me that this is the only solution, then okay.

high_flyer
26th March 2007, 18:05
I originally tried to explain that the process() function brings in all of this data and draws the polygons. I then explained the items I need to scale were stored and created under the process() function,
At least I understood it defferently.
Your original problem was getting the signal/slots to work.
I didn't pay any attention to what you were trying to do IN your code, I was just trying to help you get your code to work, and to explain to you the syntax rules for connecting signal and slot.

and if you are now telling I essentially need to re-input the data in the same data structures and essentially copy all the code from process() into processRight().
I never said anything about that.
If at all then this (more than once):

You don't need to create new slots, make one slot that connects to the valueChangedRight(int) signal,

This is true, provided you can do all the work in one slot, that reacts to hte valueChangedRight(int) signal.
So basically you can do the following:


test1::test1() {
setupUi(this);
//connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));
connect(horizontalSlider, SIGNAL(valueChangedRight(int)), this, SLOT(process(int)));
}

void test1::process(int pos) {
//adjust your original process() code so that it will remember the last pos,
//and check based on current pos values if the movement is to the left or right.
{

mistertoony
26th March 2007, 18:24
I originally used the the following connect function to display the plots with a given standard scale:


connect(pushButton, SIGNAL(clicked()), this, SLOT(process()));

I have revised the code under your recommendation, and the horizontal scale functions correctly. Thank you for this. However, when I first execute the program the graphicsView is empty and the plots only appears once I move the horizontal slider. Under your advise that "provided you can do all the work in one slot," do you have any suggestions to initialize the plot into graphicsView before any changes are made to the horizontal slider.

Additionally, I am also considering how I would be able to implement the code/logic to configure the connect function:

connect(verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(processRight(int)));

Maybe having one slot will not serve well in my application? Do you agree?

high_flyer
26th March 2007, 19:05
do you have any suggestions to initialize the plot into graphicsView before any changes are made to the horizontal slider.

Slots are normal member functions, you can call them any time, not just as a reaction to a signal.
You could call your slot with the current slider value something like:
process(slider->value());
In your initialization function.

Additionally, I am also considering how I would be able to implement the code/logic to configure the connect function:
But I showed you already how you can use the current slider position...
I am not sure what it is you are considering...

Please note - the code I am suggesting is not a code that you should copy/paste in your code, rather, its only in order to illustrate in code what I mean in words.
You should adapt it to your code.
You have to remember I don't know what it is you are trying to do, I don't know your code and what you have done so far, so I can't really give you code that neseceraly will compile for you.
It might work when the code is short and simple, but don't expect it to be so.
If you have a design question, then you should explain what is the task you are trying to achieve, what have you done so far, and what the problem is.
We then can try and give suggestion that might be helpful.

Generally - when you want your code to react to slider movement, and you want to know in which direction the slider has moved - that was answered here.
If you still didn't understand it, then ask again, and try to focus in on what it is you still need explained.

mistertoony
27th March 2007, 16:41
can you refer to me to the class/function references where i you could check which slider sent the current position so that i could accomplish the scaling with one slot.

high_flyer
27th March 2007, 16:58
QObject::sender ()

mistertoony
2nd April 2007, 16:08
high_flyer,

i have been trying to look at this all weekend and i am having trouble understanding how to implement sender(), i don't even understand how it is used in the examples i found online? would you be able to help me out.

high_flyer
3rd April 2007, 09:01
i have been trying to look at this all weekend and i am having trouble understanding how to implement sender()
Why would you want to implmenet sender()?
I don't know what more can I say that the docs are not saying...
May be if you explain what it is you have trouble understanding I could help you more...


QObject * QObject::sender () const [protected]

Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; otherwise it returns 0. The pointer is valid only during the execution of the slot that calls this function.

The pointer returned by this function becomes invalid if the sender is destroyed, or if the slot is disconnected from the sender's signal.

Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

See also QSignalMapper.


Just do something like:


if(sender()==someObjPtr)
{
//do something
}

wysota
3rd April 2007, 09:17
I just read this thread a few times and I think you might have an incorrect design in your code... Are you creating a new graphics scene each time the slider is used? I don't think you really want it this way, do you? Shouldn't you just scale/move/whatever items on the existing scene?

mistertoony
3rd April 2007, 15:21
I just read this thread a few times and I think you might have an incorrect design in your code... Are you creating a new graphics scene each time the slider is used? I don't think you really want it this way, do you? Shouldn't you just scale/move/whatever items on the existing scene?

you're exactly right, this is what i have been trying to achieve in my code this whole time. do you have any suggestions on the code's design? i have been trying to find a way to simply adjust the scale of the item's on an existing scene, without creating a new scene everytime the slider is changed. i have been led in so many directions, i do not believe the current code accomplishes this well.

high_flyer
3rd April 2007, 15:47
mistertoony:
Your original post deals with signal slot problem.
Which is what I was trying to help you with, and as I said, I didn't look in to you code to see what it is you wanted to do in the slots.
If you have an additional problem as wysota is suggesting than you have two seperate problems:
1. gettings the vertical and horizontal scale factors from the user (using signal slots sounds logical for that)
2. dealing with the drawing of your scene - when you already have the scale factors at hand.

So, did you solve problem 1?
For problem 2 I suggest a new thread.

wysota
3rd April 2007, 19:54
I think both problems are bound with each other. Solving problem 2 is easy - use QGraphicsView::scale() to scale the view (there are simmilar methods to translate or rotate the view). Now having this problem solved you may see you may not need any slots with arguments - just make a slot "adjustScale" in the parent widget of the view and in this slot check positions of scrollbars or whatever you have and use scale(), translate() or rotate() to transform the view.