PDA

View Full Version : Allow Many QWidgets to be Shown into One QWidget ?



Fatla
16th June 2008, 19:47
I've created Many (.UI) , made a (Header File + .cpp) to each .UI in order to implement their own slots , & Linked them by making a widget to be shown using :



// CustomSlot2 implements the slots inside the 2nd .UI
CustomSlot2* widget = new CustomSlot2();
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->show();


CustomSlot2 Constructor's Code is :


CustomSlot2::CustomSlot2(QWidget *parent): QWidget(parent)
{
formTwo.setupUi(this);

}


So far so Good . However , by making this approach there's a flicker when you Open & Hide/Close Windows .
I've thought in an alternative way ;that I'll Drag & Drop a QWidget into my Main Window using QT Design.
The Problem : How Could I open my .UIs into the QWidget that I've added @ MainWindow .

The MainWindow's header file generated by "make" :



class Ui_MainForm
{
public:
QPushButton *btnProcess;
QLineEdit *txtInput;
QLineEdit *txtResult;
QPushButton *btnNext;
QWidget *widget;
//........................ etc


Thanks .

aamer4yu
17th June 2008, 05:34
The ui must be creating classes for you, isnt it ?
well add those classes/windows into ur main window as u would add a widget...
hope i understand what you meant

Fatla
17th June 2008, 13:10
well add those classes/windows into ur main window as u would add a widget...

How could I make all the .UIs show in the same Widget @ Main Window ?


hope i understand what you meant
Actually , It's My mistake that I didn't clarify my Problem well .
So , Let me clarify it again ;
Now , I'm @ QT Design then I create a normal widget ,add ctrls into it.
I make the previous step 4 times . So now I've 4 .UIs that have there own ctrls into it .
To Each UI, I create its (.h + .cpp ) to implement my own slots .
Well now I open ,using QT Design ,the 1st .ui I 've made & Drag & Drop Widget into it , which is located into Container Section .
The Problem : is how to make other .UIs open into the widget I created @ the 1st .ui I 've made .

Thanks .

jpn
17th June 2008, 17:39
You can add a plain QWidget on the form and promote (http://doc.trolltech.com/4.4/designer-using-custom-widgets.html#promoting-widgets) it as a custom widget (which loads another ui).

Fatla
17th June 2008, 22:15
Thanks aamer4yu.
Perfect jpn :) .

It works now after using Promoting .
@ the MainWindow I've added a plain QWidget into it .
I've noticed that its header file generated by "make" creates instance of CustomSlot (which implements the slots of the form appears into the plain widget @ MainWindow form .

The Problem :now I want to replace the .UI that opened into the plain widget @ MainWindow with another .UI @ SAme plain Widget


Header File's code generated of MainWindow that Contains the plain widget :



class Ui_MainForm
{
public:
CustomSlot *MiniWidget; // MiniWidget = The Plain widget

void setupUi(QWidget *MainForm)
{
if (MainForm->objectName().isEmpty())
MainForm->setObjectName(QString::fromUtf8("MainForm"));
MainForm->resize(530, 402);
MiniWidget = new CustomSlot(MainForm);
MiniWidget->setObjectName(QString::fromUtf8("MiniWidget"));
MiniWidget->setGeometry(QRect(39, 29, 451, 301));

retranslateUi(MainForm);

QMetaObject::connectSlotsByName(MainForm);
} // setupUi

void retranslateUi(QWidget *MainForm)
{
MainForm->setWindowTitle(QApplication::translate("MainForm", "Main Form", 0, QApplication::UnicodeUTF8));
Q_UNUSED(MainForm);
} // retranslateUi

};

namespace Ui {
class MainForm: public Ui_MainForm {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MAINWINDOW_H



Main.cpp 's code :



#include <QApplication>
#include "ui_MainWindow.h"
#include "MainApp.cpp"

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

MainApp widget;
widget.show();

return app.exec();


}


The MainApp's code that implements slots of the MainWindow :


MainApp::MainApp(QWidget *parent): QWidget(parent)
{
ui.setupUi(this);
}



Thanks

aamer4yu
18th June 2008, 05:34
What do u mean replace ? If you mean to show another widget in same area, you can have a look at QStackedWidget. It allows you to show one widget at a time in the same area :)

Fatla
18th June 2008, 08:37
So , do you mean that there 's NO Way to use the plain widget to solve my problem ?!!
Mmmm what about using many plain widgets @ the MainWindow & specify each one of them to a .ui ?!!
If I follow that way , how could I ctrl in showing & closing/hiding the plain widgets ?

Thanks

jpn
18th June 2008, 09:07
Just place a stacked widget on your form as proposed. Then make each page of the stack contain a different custom widget (which all load their own ui files). Switching from one custom widget to another is only a matter of switching the current widget in the stack.

Fatla
19th June 2008, 15:49
Just place a stacked widget on your form as proposed. Then make each page of the stack contain a different custom widget (which all load their own ui files). Switching from one custom widget to another is only a matter of switching the current widget in the stack.

Actually I put set of plain widgets over each other @ my MainWindow .
Then I promote each one to the proper .ui .
Then @ my main : I've created instance of QStackedWidget & put into it the plain widgets that I've just created .

Problems :
- Program doesn't run even an .exe is generated + Exception is appeared
- I was thinking that after creating my instance of StackedObject, I'll use it to ctrl which UI is going to be appeared , How could I achieve smth like that ?!!

My Main 's code :


#include <QApplication>
#include "ui_MainWindow.h"
#include "MainApp.cpp"
#include <QStackedWidget>


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

QStackedWidget *StackedWidget = new QStackedWidget;
Ui_MainForm ui;

StackedWidget->addWidget(ui.MiniWidget);
StackedWidget->addWidget(ui.MiniWidget2);

MainApp Widget;
Widget.show();
return app.exec();

}



-------------------------------------------------------------------------
MainWindow's generated code that contains the plain widgetS :




#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QWidget>
#include <customslot2.h>
#include "customslot.h"

QT_BEGIN_NAMESPACE

class Ui_MainForm
{
public:
// These are the Plain Widgets I created
CustomSlot *MiniWidget;
CustomSlot2 *MiniWidget2;

void setupUi(QWidget *MainForm)
{
if (MainForm->objectName().isEmpty())
MainForm->setObjectName(QString::fromUtf8("MainForm"));
MainForm->resize(530, 402);
MiniWidget = new CustomSlot(MainForm);
MiniWidget->setObjectName(QString::fromUtf8("MiniWidget"));
MiniWidget->setGeometry(QRect(39, 29, 451, 301));
MiniWidget2 = new CustomSlot2(MiniWidget);
MiniWidget2->setObjectName(QString::fromUtf8("MiniWidget2"));
MiniWidget2->setGeometry(QRect(0, 110, 461, 301));

retranslateUi(MainForm);

QMetaObject::connectSlotsByName(MainForm);
} // setupUi

void retranslateUi(QWidget *MainForm)
{
MainForm->setWindowTitle(QApplication::translate("MainForm", "Main Form", 0, QApplication::UnicodeUTF8));
Q_UNUSED(MainForm);
} // retranslateUi

};

namespace Ui {
class MainForm: public Ui_MainForm {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MAINWINDOW_H



Thanks

Fatla
20th June 2008, 15:38
I've tried many times to use QStackedWidget . However , I'm facing a few difficulties with it .
Problem : How Could I use it into my app ,mentioned b4 ?!!

Fatla
21st June 2008, 23:10
I've made a little progress .
I've just noticed that there's @ QT Design smth called "stacked Widget" .

I 've promoted to the Stacked Widget one of my .UI .

Problem :
- I got an error : 'class CustomSlot' has no member named 'addWidget' ?!!
- I 've noticed that I can add any number of pages @ Stacked Widget , so How Can I promote different .UI , to each page I 've ?

Header File 's code that has the custom Widget




#ifndef UI_FORM2_H
#define UI_FORM2_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QRadioButton>
#include <QtGui/QTableView>
#include <QtGui/QWidget>
#include <customslot.h>

QT_BEGIN_NAMESPACE

class Ui_FormTWo
{
public:
QPushButton *btnGender;
QGroupBox *gpBoxGender;
QRadioButton *rdBtnMale;
QRadioButton *rdBtnFemale;
QLabel *lblSelectedFilePath;
QPushButton *btnBrowse;
QPushButton *pushButton;
QLineEdit *txtFileData;
QPushButton *pushButton_2;
QPushButton *btnReadImage;
QTableView *TableViewData;
QPushButton *btnSaveAs;
CustomSlot *stackedWidget;
QWidget *Form1;
QWidget *Form2;

void setupUi(QWidget *FormTwo)
{
stackedWidget = new CustomSlot(FormTwo);
stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
stackedWidget->setGeometry(QRect(540, 230, 171, 131));
Form1 = new QWidget();
Form1->setObjectName(QString::fromUtf8("Form1"));
Form1->setGeometry(QRect(0, 0, 171, 131));
stackedWidget->addWidget(Form1);
Form2 = new QWidget();
Form2->setObjectName(QString::fromUtf8("Form2"));
Form2->setGeometry(QRect(0, 0, 171, 131));
stackedWidget->addWidget(Form2);

retranslateUi(FormTwo);

stackedWidget->setCurrentIndex(0);



} // setupUi

void retranslateUi(QWidget *FormTanya)
{
// ...........................etc
} // retranslateUi

};

namespace Ui {
class FormTwo: public Ui_FormTwo {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_FORM2_H



---------------------------------------------------------------------------------
My CustomSlot 's code :


#include"CustomSlot.h"
#include "ui_Test.h"

#include "ui_Form2.h"
#include"CustomSlot2.cpp"



CustomSlot::CustomSlot(QWidget *parent): QWidget(parent)
{
ui.setupUi(this);
}
// ......................etc


Thanks .

wysota
22nd June 2008, 00:12
Please use proper language instead of sms slang. And please read QStackedWidget docs, by the way :) Promoting widgets is not the same as placing one widget in another and I think you are mixing the two.

Fatla
22nd June 2008, 03:16
Promoting widgets is not the same as placing one widget in another and I think you are mixing the two.

YES I WAS .
I'd already read the QStackedWidget from the docs b4 many times . However after what you 'd just told me , things become more clear now .

I've made a simple app that just contains : Button + Custom Widget (Dragged & Dropped using QT Desgin)

I want each time the user clicks the button , different .UIs to be shown .

Problem :
-Every time I run the app , Exception is appeared
-I just added these line at my main :




Ui_FormTwo FormTwoObj; // UI that contains my Stacked Widget

CustomSlot *CustomSlotObj; // The class that implements slots of UI I want to display to the user

FormTwo.stackedWidget->addWidget(CustomSlotObj);


- I Still don't understand well the QStackedWidget . What I Understand that QStackedWidget is a stack that you can push & pop like the normal stack with the capability of controlling with the index of Removing / Wanted objects in the stack .
So now How could I make an object at stack to be appeared to the user ?


Please use proper language instead of sms slang.
Thanks for notifying me :)


Thanks .

wysota
22nd June 2008, 08:38
Treat the stacked widget as a book where you can add or remove pages (but this is not the important part here) and where you can open the book at any page at any moment and view that page (that's the important part) and only that page.

Fatla
23rd June 2008, 01:05
That's Wonderful .
1/2 of my problem 's been solved .

I've just noticed that when I drag & drop QStackedWidget using QT Design , Pages (instance of Widgets ) are created & added to the stacked widget .
I can add any number of pages I want & add the controls into it . I can control which widget to be displayed .
It works so great .

The second half of my problem :
- Whenever I try to declare instace of my .UI & add it to the QStackedWidget , Exception is appeared .
I've tried :
addWidget(WidgetObj);
widget(index );
insertWidget (index , WidgetObj);

CustomSlot's code that implements slots of the .UI & also has the QStackedWidget :



#include"CustomSlot2.h"
#include "ui_Form2.h"
#include "CustomSlot.h"



CustomSlot2::CustomSlot2(QWidget *parent): QWidget(parent)
{
formTwo.setupUi(this);

//CustomSlot is the class that implement the slots of the .UI that I want to add at QStackedWidget
CustomSlot *CustomSlotObj ;
//formTwo.stackedWidget->addWidget(CustomSlotObj);

// I've already just 2 pages at QStackedWidget , The third on is going to be in index 2
formTwo.stackedWidget->insertWidget(2,CustomSlotObj);

QWidget *WidgetObj;
WidgetObj= formTwo.stackedWidget->widget (2) ;


WidgetObj->show();


}




Thanks .

jpn
23rd June 2008, 07:00
"CustomSlot *CustomSlotObj;" produces nothing but a dangling pointer which points to some random memory garbage. You forgot to actually instantiate something with C++ operator new.

Fatla
23rd June 2008, 22:43
Perfect , it works now .
However I still have simple issues :

1- When I add my .UI at the QStacked Widget , it successfully appears & I can just control it using Keyboard (i.e. the UI that I've added at QStacked Widget contains QLineEdit + Button I can't press the button using the mouse I should use my "Tab" in order to go to that control then press "Space" ) ?!!

2- According to what I've have understood that only one widget at QStackedWidget can be displayed at once to the user .
I just have one QWidget that is put by default at QStackedWidget , when I drag & drop the stack using QT Design . Then at this page I've added a button . Then using the code I 've added my .UI at the stack then show it .
What 's weird : that both QWidgets that have the button + the other Widget that I 've add by code are displayed ?

Thanks .

jpn
24th June 2008, 06:39
Sounds like you created the form as a child of the stacked widget but you didn't actually add the widget to the stack widget. That's at least one reason why it wouldn't be managed by the stacked widget.

Fatla
24th June 2008, 12:42
How is that ?!!

Part of Header files 's code generated to the form that contains the QStackedWidget :





#include <QtGui/QStackedWidget>
#include <QtGui/QWidget>


class Ui_FormTwo
{
public:
QStackedWidget *stackedWidget;
QWidget *page;

void setupUi(QWidget *FormTwo)
{
stackedWidget = new QStackedWidget(FormTwo);
stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
stackedWidget->setGeometry(QRect(460, 130, 551, 371));
page = new QWidget();
page->setObjectName(QString::fromUtf8("page"));
page->setGeometry(QRect(0, 0, 551, 371));
stackedWidget->addWidget(page);

retranslateUi(FormTwo);

stackedWidget->setCurrentIndex(0);

// ......................etc

} // setupUi




---------------------------------------------------------------
Temporarily , I've added the code that add my .UI to the stack at the constructor of the form that has the stack object :




CustomSlot2::CustomSlot2(QWidget *parent): QWidget(parent)
{
formTwo.setupUi(this);

CustomSlot *CustomSlotObj=new CustomSlot() ;

formTwo.stackedWidget->insertWidget(1,CustomSlotObj);

QWidget *WidgetObj;
WidgetObj= formTwo.stackedWidget->widget (1) ;

WidgetObj->show();


}



Thanks .

jpn
24th June 2008, 12:54
Aha, now I realized what's wrong.




QWidget *WidgetObj;
WidgetObj= formTwo.stackedWidget->widget (1) ;

WidgetObj->show();


This is not the way you use QStackedWidget. You are supposed to use QStackedWidget::setCurrentIndex() or setCurrentWidget().

Fatla
25th June 2008, 03:22
Thanks , it works successfully .
I 've one more question :

- I've added many QWidgets into stack . Now I need when the turn comes to a particular widget to be shown , I can access its variables .



#include "Container.h"



Container::Container(QWidget *parent): QWidget(parent)
{
ContainerUi.setupUi(this);

PageIndex=1;


CustomSlot1 *CustomSlot1Obj =new CustomSlot1();
CustomSlot2 *CustomSlot2Obj=new CustomSlot12();
CustomSlot3 *CustomSlot3Obj=new CustomSlot3();
//........................ to CustomSlot9


// Push objects into the QStackedWidget
ContainerUi.StackedWidget->addWidget(CustomSlot1);
ContainerUi.StackedWidget->addWidget(CustomSlot2);
ContainerUi.StackedWidget->addWidget(CustomSlot3);
//.................. pust the other Widgets into the Stack


ContainerUi.StackedWidget->setCurrentIndex(PageIndex);
PageIndex++;

}

void Container :: NextPage()
{



int CurrentIndex=ContainerUi.StackedWidget->currentIndex ();
if(PageIndex <10)
{

if(CurrentIndex==3 )
{
CustomSLot3 *widget ;
widget=ContainerUi.StackedWidget->widget (3);
// GrainSizeFlag is a public variable at CustomSlot3
if(widget->GrainSizeFlag==true)
::PageIndex=7;



}
ContainerUi.StackedWidget->setCurrentIndex(PageIndex);
PageIndex++;

}


}



By default the Stack contains one widget . So my "CustomSlot" 'll go to the index [1].
As a result of that , CustomSlot3 'll go to index [3].

I've an error that tells ms : Invalid Conversion QWidget* to CustomSlot3*

Thanks .

wysota
25th June 2008, 07:30
I suggest you keep all pointers as member variables of the containing class and access them directly instead of fetching the pointer through current widget of the stack (it is possible of course - you'd have to cast the pointer received to a proper type).

Fatla
4th July 2008, 23:01
It has been a long time since my last reply .
Things were going so fine & the resources over web were extremely helpful .

Currently , I was looking for property/function that DeActivate child widget
(e.g. If I've a Widget that has a QPushButton . When the user press that button another widget 'll be shown & TOTALLY DeActivate the previouse widget .
So the user won't be able even to close / maximize/minimize the old widget )

I've tried :
isActiveWindow():Just make the widget on top .
setEnabled:Disable all the controls into widget but not the toolbar (i.e. the user will be able to close / maximize/minimize widget)

Thanks .

Fatla
5th July 2008, 13:15
I've found a solution to the problem :





this->setEnabled(false);

HMENU menu = ::GetSystemMenu(this->winId(), FALSE);

::DeleteMenu(menu, SC_CLOSE, MF_BYCOMMAND);

::EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);


That of course after including : #include <qt_windows.h>

Fatla
5th July 2008, 16:06
Now I've 2 issues :
1- How could I also disable "Maximize" & "Minimize" ?
2- How could I enable them after I've just disabled them ?


Thanks .

Fatla
5th July 2008, 21:14
I've solved the 2nd issue by :



void MainWindow::EnableToolBar()
{
MainWindowMenu = ::GetSystemMenu(this->winId(), TRUE);

}

wysota
6th July 2008, 09:29
Why would you want to disable maximizing/minimizing a window? Don't you think it is an extreme interference in the user's desktop? As for closing, you don't need any windows related functions, simply reimplement closeEvent() for your widget and ignore the event if you want to prevent the window from being closed. You can disable the maximize/minimize buttons if you really want to, by either hiding them using window flags or by removing the window from the window manager's control (by using window flags again). To disable the contents of a window simply disable() it (or setEnabled(false)).