Author Topic: Newbie Qt and CPP questions: Variable Sharing  (Read 5261 times)

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« on: March 07, 2004, 12:43:19 am »
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
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

Mickeyl

  • Hero Member
  • *****
  • Posts: 1495
    • View Profile
    • http://www.Vanille.de
Newbie Qt and CPP questions: Variable Sharing
« Reply #1 on: March 07, 2004, 08:18:22 am »
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.
Cheers,

Michael 'Mickey' Lauer | Embedded Linux Freelancer | www.Vanille-Media.de
Consider donating, if you like the software I contribute to.

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #2 on: March 07, 2004, 01:37:57 pm »
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
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

markb

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #3 on: March 07, 2004, 03:36:37 pm »
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: [Select]
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: [Select]
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: [Select]
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.

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #4 on: March 07, 2004, 07:57:14 pm »
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
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #5 on: March 08, 2004, 01:14:42 am »
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);  


}
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

markb

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #6 on: March 08, 2004, 02:44:53 pm »
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. :-)

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #7 on: March 08, 2004, 08:22:22 pm »
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
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #8 on: March 08, 2004, 08:46:54 pm »
If anyone else cares to look at the source I have attached the source!
Thankx\'
John
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

markb

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #9 on: March 09, 2004, 03:09:48 pm »
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

jdf

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #10 on: March 10, 2004, 09:21:58 am »
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
JDF
SL-5500; CF MODEM; CF Wireless; CF & SD Storage;
Fedora CORE 1; WinXP

markb

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://
Newbie Qt and CPP questions: Variable Sharing
« Reply #11 on: March 10, 2004, 03:30:20 pm »
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: [Select]
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