PDA

View Full Version : inheritence problem?



poporacer
17th November 2010, 04:51
I have a MainWindow widget that has a stacked Widget. I want to create a class for each of the pages for the stacked widget to keep the code a little neater. When I build the program I get an error that I think might be resolved by the correct inheritence (I am a newbie, so I am not sure). The error is 'ui' was not declared in this scope. The error is identified in my class for one of the pages of the stacked widget. ui isn't a class so I am not sure how to reference it. It looks like it is a pointer to the class MainWindow which inherits the class QMainWindow. (At least this is what I think is happening). Here is what I have so far:
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>



namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();


protected:
void changeEvent(QEvent *e);
void closeEvent (QCloseEvent *event);


private:
Ui::MainWindow *ui;
bool updateDb();
bool saveDataCheck();
bool m_IsDirty;
void updateData();
void writeSettings();
void readSettings() ;

private slots:
void on_txtFname_textChanged();
void on_txtLname_textChanged();
void on_txtMname_textChanged();
void on_txtAddress_textChanged();
void on_cmbName_currentIndexChanged();

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "database.h"
#include <QtSql>
#include <QSqlError>
#include <QDebug>
#include <QtGui>
#include "namewidget.h"


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
nameWidget * name= new nameWidget;
m_IsDirty=false;
ui->setupUi(this);
ui->MainStackWidget->setCurrentIndex(0);
name->updateNameComboBox();
readSettings();
updateRiderData();

}
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

namewidget.h

#ifndef NAMEWIDGET_H
#define NAMEWIDGET_H



class nameWidget //Inheritence here?

{
public:
nameWidget();
void updateNameComboBox();


};

#endif // RIDERWIDGET_H
namewidget.cpp

#include "namewidget.h"
#include "ui_mainwindow.h"
#include <QtSql>
#include "mainwindow.h"

nameWidget::nameWidget()
{
}
void nameWidget::updateNameComboBox()
{

QSqlQuery query;
query.exec("SELECT id,LName, FName FROM name");
ui->cmbName->blockSignals(true); //error here- ui was not declared in this scope
ui->cmbName->clear(); // I am sure I will get the same error here

while (query.next())
{
ui->cmbName->addItem(query.value (2).toString()+ " "
+ query.value (1).toString(), query.value (0).toInt());
ui->cmbName->blockSignals(false);
}
}

I am trying to learn but keep getting a few glitches on the way. I searched to no avail.

Thanks

ChrisW67
17th November 2010, 05:57
Is "nameWidget" supposed to be the combo box?

poporacer
17th November 2010, 14:30
The nameWidget class is going to be the class for one of the pages of the stacked widgets. It will be used to perform the functions of that page. Populate the page, update the lineedit widgets when the user makes a selection in the combobox, etc.

janorcutt
17th November 2010, 18:10
your nameWidget should inherit QWidget and add the Q_OBJECT macro just like in the MainWindow class definition.
then you can use signals and slots. I suggest this because it seems like a good way to keep the ui manipulation in the MainWindow class.
you can then pass a QStringList with the relevant data to a slot function that can update the comboboxes.

hope this helps a little

poporacer
18th November 2010, 02:24
Lets see if I understand, If I inherit Qwidget and add Q_OBJECT, I think this will only allow me to use signals and slots and pass the information back to MainWindow. Then the majority of my code for populating/updating the linewidgets will still be in the MainWindow class. This defeats what I was trying to acccomplish. I wanted the actions that take place on each page of the stacked widget to be in a separate class....maybe my understanding of Object Programming is a little flawed. Any suggestions on a better wat to accomplish this, or just keep my code all in the MainWindow class?

ChrisW67
18th November 2010, 03:56
Where's the problem... put the UI for each page in a separate class rather than all in the main window class if that is what you want. If you put all the UI construction in the main window class then most of the UI interaction code will also be in that class (all of it, if the UI is incorporated by private composition as is the case in you example).

Timoteo
18th November 2010, 04:00
Also, how is nameWidget going to be a widget without being a widget or having one?

poporacer
18th November 2010, 04:34
ChrisW, I do not know how to put the UI in the class? And I figured that I would have to put the UI in either the protected or public declaration when I figured out what I needed to do. Could you provide a little more information on how to implement the UI in the class or an example?

Timoteo, nameWidget isnt a widget, I used the name to identify the class that is a reference to the stacked widget....I guess I should use a different name for the class. I will change that.

ChrisW67
18th November 2010, 04:57
If you are using Qt Creator:

Open your project
Right click and select Add New...
Select Qt, Qt Designer Form Class, then Choose...
Select QWidget (or whatever) as the template
Provide file names and whether to save in a version control.
Build the new form
Done.


If you using Designer outside QtCreator:

Open Designer
Select QWidget or another template
Build the new form
Save the UI file and add it to your project's FORMS variable
Done.


See "Using Custom Widgets with Qt Designer" in Assistant for how to insert these new widgets into the QStackedwidget in the QMainWindow.

poporacer
18th November 2010, 15:18
I followed your directions but ran into a problem. I was able to get all your steps done and then read the "using custom widgets". I am not sure what to do to get this widget into the stacked widget. I wasn't sure if I promote the new ui....I tried but couldn't figure how to do it. And there was nothing in Assistant on how to insert a widget into another widget. I promoted a widget (Don't know what I really did) but then couldn't do anything with it. Now I can't get rid of this now as well. I think I follow the logic, let me know if this is the case.
1. Create a Qdialog ui for each page of the stackedwidget and have all the elements and functionality that I want for that page encapsulated in that class.
2. Somehow insert this ui into the respective page for the stacked widget.
Is this correct?

Where do I go from here?

marcvanriet
18th November 2010, 21:03
Hi,

You create a dialog derived from QDialog for each of the pages (that is, just like you create any normal dialog that you would just show with show() or exec() ). ChrisW67 told you the instructions. The slots for this dialog (so what happens when you press a button) are also in the cpp for this form class. Nothing special here.

Then, in the constructor of your main dialog, create a new instance of this dialog class (I guess you know you have to include the header file to do this).

After creating this instance, Then, add it to your stackedwidget, using the addWidget() method. You can do the same technique if you use a QTabWidget by the way.

You may check this thread for an example : QStackedWidget-and-QTabWidget-Structure-Advice (http://www.qtcentre.org/threads/36032-QStackedWidget-and-QTabWidget-Structure-Advice)

Hope this helps,
Marc

poporacer
21st November 2010, 06:40
Ok....Things are starting to get clearer...still a couple of problems. To help make it understandable but brief I have my MainWindow class that has a stacked widget on it. Then I have my NamePage class.
My first problem is probably basic C++ stuff, but I can't seem to resolve it. In my NamePage class I have some functions that I need to call from my MainWindow class in a couple of places. I declare a pointer to a NamePage class on the heap in my constructor for the MainWindow class (called name). I thought that by doing so, I could reference the functions in each place in my MainWindow class, but it doesn't work that way. Do I have to create a pointer to a class in each function where I need to access the functions. What is the best way to do that.
The second issue is how to reference a lineedit widget on the NamePage ui from the MainWindow class.

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
NamePage *name=new NamePage;
ui->setupUi(this);
ui->MainStackWidget->setCurrentIndex(0);
name->updateRiderComboBox();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(name->saveNameDataCheck())// name not declared in this scope
{
writeSettings();
event->accept();
}
else
{
writeSettings();
event->ignore();
}
}

Timoteo
21st November 2010, 07:18
You need 'name' to be a member of MainWindow to do what you describe. Creating a pointer in each function will not only leak memory like crazy, but you won't be accessing the same NamePage each time. Remember, a pointer is a memory address. This memory address is where an instance of the class (an object) resides. Each time ask for a new X, a pointer to an X is given (a new allocation).

Instead of just plugging in code until it (appears) to work, why don't you instead read some books on programming?

poporacer
21st November 2010, 16:17
So how do you make name a member of MainWindow? I have read a couple of books on C++ programming. I also have the C++ Gui programming book for QT that I have read in its entirety and refer to on a regular basis. That was my concern about creating a new class and pointer for each function and trying to manage the memory to make sure all pointers are deleted when they need to be, and that is why I didn't continue and asked my question here. I thought that by creating a pointer to a memory location to my class on the heap that I could access it elsewhere. I am not just plugging in code to see if it works. When I get advice here I try to research it as well to understand what I am doing. Sometimes responses are vague (to a newbie) and one doesn't get much further in thier program. I do try different code in order to understand how it works, not to make it work.

Timoteo
21st November 2010, 17:22
class MainWindow
{
private:
NamePage* name;
}

What you are confusing is scope and duration. A heap object does have an indefinite duration, but that doesn't influence the scope of the pointer. The pointer itself (that is, the variable that contains the memory address of the heap object) is passing out of visibility and being destroyed when you exit your constructor in your original code. The heap object lives on, though.

poporacer
24th November 2010, 05:34
Well, things are better and worse...I think The link you sent me helped, but I think the code they posted might be wrong.

ui->stackedWidget->addWidget( frmRealParts, "Realparts" );
From the information I have read, addWidget only takes one parmeter, I could not find an overloaded function that takes two parameters. Am I looking at this wrong?
Now for the question. How do I access the widgets on the Name class widget on the stacked widget from the MainWindow class? For example, I want to access a combo box (cmbName) that is on the dialog that was added to the stacked widget.
I looked and couldn't find anything. I thought something to the effect of name->ui->cmbName but that isn't right.
And one problem I have is now I can't close the program. The Close button doesn't close the program and also clicking on the X in the main window doesn't close the window. This was working before and about the only thing I changed was moving the code for the stacked widget page from the MainWindow class to the Name class. I will keep looking but any hints what might be going on?