OESF | ELSI | pdaXrom | OpenZaurus | Zaurus Themes | Community Links | Ibiblio

IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> Newbie Qt and CPP questions: Variable Sharing
jdf
post Mar 6 2004, 09:43 PM
Post #1





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



Bear with me, I am new to CPP and am having a problem with variables. The only reason I haven't given up yet, is because of the support I got off this board so far!!

I have a Class called "HandMade" . Handmade is derived from QVBox class. Handmade includes a listbox, a slider, an ADD button, a REMOVE button. When you press ADD, whatever value the slider displays is added to listbox. When you press delete, whatever value is current in the listbox is deleted from list box.

The HandMade class also includes another class “TicTacToe”. Basically this is the last item in the QVBox.

(As you can tell, I just slapped TWO example programs into ONE to learn some fundamentals!!)

Now, it all works!! The buttons update the listbox from the slider etc.. And the tictactoe game works right along below it. Kind of 2 independent widgets functioning on the same page.

Now HOW Can I get the TicTacToe class to TALK TO the LISTBOX in HandMade class? For example, when I tap a box in the TicTacToe grid (call it TTT) a mousePressEvent is generated. In TTT, the mouseevent calls a function to draw the X or O etc.. This all works fine.

I want to add something to the mousePressEvent that will also ADD TO THE LISTBOX a number from 1 to 9.

The 2 class files are listed below my signature.

Note that in HandMade *lb is a variable to reference the listbox.
I assume if “lb” was global or accessable I could just do:
lb->insertItem( “9” );
But that doesn’t work inside the Class TicTacToe!
I just get this error message:
Error E2451 tictactoe.cpp 50: Undefined symbol 'lb' in function TicTacToe::mousePressEvent(QMouseEvent *)

Anyone care to help a newbie learn about this!!

Thankx in advance
JDF

***** handmaid.h ********
#ifndef HANDMADE_H
#define HANDMADE_H

// My main widget is derived from the QVBox widget
#include <qvbox.h>

// these "forward declarations" tell the compiler what other
// classes I WILL BE using without having to fully use
// the class declarations. The actual class declarations are included
// in the implementation file as <qlistbox> and <qlcdnumber>.
class QLCDNumber;
class QListBox;
class TicTacToe;

// This is the start of MY new class I am making called handmade
// It is based on QVBoz class
class HandMade : public QVBox
{
// Must have this Qt Keyword in order to use signals/slots/etc...
Q_OBJECT

public:
// This is the CONSTRUCTOR declaration
HandMade( QWidget *parent=0, char *name=0 );
QListBox *lb;
TicTacToe *kybd;

protected slots:
// These are SLOTS
void addNumber();
void removeNumber();

protected:
//These pointer values are used by the slots
QLCDNumber *lcd;
//QListBox *lb;
//Need to watch the keybopard
//TicTacToe *kybd;

};

#endif

***** tictactoe.h ********
#ifndef TICTACTOE_H
#define TICTACTOE_H

#include <qwidget.h>

class TicTacToe : public QWidget
{
Q_OBJECT
public:
TicTacToe(QWidget *parent = 0, const char *name = 0);

protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);

private:
enum { Empty = '-', Cross = 'X', Nought = 'O' };
QRect cellRect(int row, int col) const;
int cellWidth() const { return width() / 3; }
int cellHeight() const { return height() / 3; }
char board[3][3];
};

#endif
Go to the top of the page
 
+Quote Post
Mickeyl
post Mar 7 2004, 05:18 AM
Post #2





Group: Members
Posts: 1,497
Joined: 12-November 03
From: Germany
Member No.: 907



You should take a look into the signal/slot mechanism. Emit a signal in one widget and connect that to a slot in the other widget. Refer to the TT documentation for a signal/slot primer.
Go to the top of the page
 
+Quote Post
jdf
post Mar 7 2004, 10:37 AM
Post #3





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



I got slots and signals going. I am missing some basic structure or something. The problem is between 2 different classes as above. HOW do I for example call/connect the the "void addNumber();" slot in the HandMade widget. Really I just want to call/execute this without using a signal from the tittactoe "mousePressEvent(QMouseEvent *event);" .
JDF
Go to the top of the page
 
+Quote Post
markb
post Mar 7 2004, 12:36 PM
Post #4





Group: Members
Posts: 54
Joined: 28-February 04
From: Birmingham, UK
Member No.: 2,080



Without seeing all the code, I could be getting this completely wrong.
But I'll try anyway.

By the way, although I've done lots of C++, I'm new to Qt myself, so I hope I don't lead you astray with my limited knowledge. :-)

When a user clicks in the TicTacToe widget, a mouse press event is generated. And the mousePressEvent method gets called.
I'm guessing that somewhere in that method, it takes the coordinates of the mouse press, and decides which square the user clicked in.
Maybe at that point you have a number for the square: 1-9.
(There are lots of ways this could be done, I'm just guessing at one of them.)

At that point in the mousePressEvent method, you could generate a signal.
Let's say you generate a signal called clickedSquare, that takes the square number as a parameter:

CODE
emit clickedSquare( squareNumber )

You'll need to change the declaration of the TicTacToe widget to say that it has a signal.

Now you want that signal to be handled by a slot in your HandMade class. (The class that has access to the list box).
Lets say it's a method called addToList:

CODE
void HandMade::addToList( int number )

{

 //  ... code to add a number to the list

}

(Not forgetting to change the class declaration to include the slot)

Now you can connect the signal and slot together.
In the constructor for HandMade, after you have created your widgets you can do this:

CODE
connect( kybd, SIGNAL(clickedSquare(int)),

 this, SLOT(addToList(int)) );


Where kybd is your TicTacToe object.

I hope that is of some help.
I'm sure someone with more Qt experience could offer you a better solution or explanation.

- Mark

p.s.
I know you said
"without using a signal from the tittactoe "mousePressEvent"
But I'm not sure how to do that.
So my reply may not be what you're after. Sorry.
Go to the top of the page
 
+Quote Post
jdf
post Mar 7 2004, 04:57 PM
Post #5





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



markb,

Yes that is how I finally got it working after much struggle/learning. ( Your post would have saved me some time, if you had posted before I asked!! )

What you wrote seems to be exactly the way to do it using Qt. If i figure out how to do it without signals and slots, I'll post here! Genrally how does CPP deal with a global/shared variable. Can it be accessed/changed in the child classes since CPP doesn't use signals/slots? Do I need some kind of "setter or getter" function declared?

Thankx markb
jdf
Go to the top of the page
 
+Quote Post
jdf
post Mar 7 2004, 10:14 PM
Post #6





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



So I get the value of the cell passed back to the main widget by emitting a signal that goes into a slot in the main widget. In that slot I can verify that the proper number has been recieved. I convert the number to a Qstring so that I can try to put it into an existing QLabel that is in this widget. The number is properly converted, but am unable to update the label.

ANY IDEAS??!!

Below is the pertinent code:

THIS IS THE SLOT that recieves the signal
void j_uconvert::sl_KYBDentry(int cell)
{
/* convert the integer to a string */
QString str = QString::number( cell );

/* debug: verify that the integer is recieved and converted to string properly
*/
int ret = QMessageBox::warning(this, tr("in SLOT"),
str,
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No | QMessageBox::Escape);

// AL DISPLAYS WELL IN THE MESSAGE BOX
// Now try to update the Qlabel named le_basevalue

// allbelow caused error runtime
// le_basevalue->setText( "hello" );

//try emitting a signal and connecting it in constructor
//added signal to the .h file and added this to the constructor
// connect(jmainwindow, SIGNAL(sig_basefix(QString)), le_basevalue, SLOT(setText(Qstring)) );
// the label is never updated
emit sig_basefix(str);


}
Go to the top of the page
 
+Quote Post
markb
post Mar 8 2004, 11:44 AM
Post #7





Group: Members
Posts: 54
Joined: 28-February 04
From: Birmingham, UK
Member No.: 2,080



Hi jdf,

In one post you say that you'll try to get it working without signals & slots.
I think there might be a little bit of confusion here.

If you're trying to handle some event or action, and want to be told when that happens, then signals/slots are the way to do it.
That event/action could be a GUI related thing, like a button press, or a list item selection. Or it could be a non-gui thing, such as waiting for a variable to change, or a limit to be reached.
(The code that changes the variable will emit a signal to let you know it has changed. Anything interested in that variable changing can be connected to the signal, so it will be called when it changes.)

On the other hand, you seem to have a problem with accessing some variables in one class, from code inside another class.
(Stop me, if I've got the wrong idea here.)

Generally the way to do it is through access methods.
But object oriented design is quite a big topic, and this may not be the best place to discuss it. I could offer some suggestions after I've seen your code.

I didn't quite understand your last bit of code.
Your comment says that you get a runtime error when you try to set the text in your le_basevalue label widget. I couldn't see that variable anywhere else in the code. Has it been set up? Does it already have some text that you can see?

It might be easier for me to see the problem if I could reproduce it myself.

I'll send you a private message. Maybe you could tar up your source code and send it to me, and I'll have a look.

Meanwhile, someone else may be able to offer more help than me.

- Mark

p.s.
I've just got home from work and my C860 has arrived!
It's being charged now. I haven't turned it on yet.
I'm supposed to wait 8 hours. I don't think I'll manage that. :-)
Go to the top of the page
 
+Quote Post
jdf
post Mar 8 2004, 05:22 PM
Post #8





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



markb,

Congratulations on the new arrival! Treat it nice!

I just sent off the tar of my source.
Yeah I don't want to discuss too much about oop here. since I know nothing! I have a book and am working through it step by step.

You'll see in my source the Qlabel is started with some default text and it displays properly.
I'll understand if you are distracted by the new toy!
JDF
Go to the top of the page
 
+Quote Post
jdf
post Mar 8 2004, 05:46 PM
Post #9





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



If anyone else cares to look at the source I have attached the source!
Thankx'
John
Go to the top of the page
 
+Quote Post
markb
post Mar 9 2004, 12:09 PM
Post #10





Group: Members
Posts: 54
Joined: 28-February 04
From: Birmingham, UK
Member No.: 2,080



jdf,

I've fixed your code and sent it back to you with a description of what I changed.
It was probably just a simple oversight, but I included an explanation of a few C++ concepts as well just in case.

I hope it helps.
Good luck with your coding project.

- Mark
Go to the top of the page
 
+Quote Post
jdf
post Mar 10 2004, 06:21 AM
Post #11





Group: Members
Posts: 33
Joined: 28-February 04
Member No.: 2,078



markb did a bang up job finding my problem and explaining some of the technicalities of my errors.

Just in case some other NEWBIES hit the same wall as me I am posting the solution here. It may seem trivial and obvious now (even to me) but it escaped me!

Basically I had a QLineEdit that I created in my widget constructor. I then wanted to update that label using the “setText” method in another part of the program. Since I wanted access to the QLineEdit from a place outside the constructor I put the QLineEdit reference (le_basevalue) in the .h file declaration. I could not get it working!! I made a subtle (for me) error. Here is excerpts:

In “ucvt.h”
Protected:
QLineEdit* le_basevalue;

In “ucvt.cpp” in the ucvt constructor:
QVBox *jmainwindow = new QVBox( this );
QLineEdit *le_basevalue = new QLineEdit( jmainwindow, "le_basevalue" );
le_basevalue->setText( "hello" ); // This sets it up and works fine

In another function/method still in class ucvt
le_basevalue->setText( "goodbye”); //Never worked! Still says hello!
---------------------
The error is that in the constructor I was actually declaring a NEW LOCAL variable with the same name as my “global” variable le_basevalue. Since this is local, my global le_basevalue was never being set or used in the constructor.

The constructor line should be done this way:
le_basevalue = new QLineEdit( jmainwindow, "le_basevalue" );

This uses the already declared “global” le_basevalue and not a new declaration of a new local variable!!
Problem solved!!
---------------------------
To make sure I don’t make the same mistake in the future, and until it becomes habit for me I have done it this way and it works to….
QLineEdit *temp = new QLineEdit( jmainwindow, "le_basevalue" );
le_basevalue = temp;

Thankx markb!!!!
jdf
Go to the top of the page
 
+Quote Post
markb
post Mar 10 2004, 12:30 PM
Post #12





Group: Members
Posts: 54
Joined: 28-February 04
From: Birmingham, UK
Member No.: 2,080



Hi jdf,

There's a common technique that helps people to avoid these sorts of problems.
If you have a naming convention for your member variables, then it makes it easy to spot when you're using a local variable or a member variable.

e.g. prefix all member variables with "m_"

CODE
class MyPoint

{

private:

   int m_x;

   int m_y;



public:

   MyPoint(int x, int y);

   double distance( int x, int y );

};



MyPoint::MyPoint( int x, int y )

{

   m_x = x;

   m_y = y;

}



double MyPoint::distance( int x, int y )

{

   int dx = x-m_x;

   int dy = y-m_y;

   double dist = sqrt( (double)(dx*dx + dy*dy);

   return dist;

}

Personally I find it makes it obvious when you're assigning to a member variable.

You can pick any convention you like.
I've seen the m_ prefix used a lot, as well as just _.
e.g. _x and _y ;

Just a thought.

- Mark
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 28th December 2014 - 12:47 AM