Adding one ui file into another - c++

Suppose i have designer files with there respective classes say form.ui , form.h , form.cpp and myclass.ui , myclass.h , myclass,cpp . Now what i want is 2 different things .
Now i have a widget and a layout in the myclass.ui file and i now using addLayout function i add the form.ui file into it . Now i want it so that whole of the form.ui file content should come into small layout space by self adjusting . But that is not happening . So how could i achieve that

QUILoader is your solution but maybe not the best, specially if you have custom actions & functions for your form.ui in your form.h & form.cpp. The easiest way its to promote a widget inside your widget and then make it not visible. When you have to show it, you can just change the hidden state.
In another case, you can create it dynamically and manage the memory by yourself.

Example of QUiLoader:
// your main widget
MyClass *myclass = new MyClass();
// to generate a widget with a .ui file
QUiLoader loader;
QFile file("form.ui");
file.open(QFile::ReadOnly);
QWidget *myForm = loader.load(&file, this);
file.close();
// insert the widget in your main container
myclass->layout()->addWidget(myForm);

Related

How to create or modify a QT form (after compilation) based on a text file

I would like to create a windows application that displays a window based on a existing text file. For example, I may have a text file with the following information:
window_size 400, 300
push_button 2
radio_button 5
My program should be able to read this text file and create a window of 400 x 300 pixels, with 2 push buttons and 5 radio buttons. Of course, the content of the text file may change and is unpredictable. Please ignore at this moment other nessesary data, like the position and size of the buttons, I just need to know if its possible to do this, and a general idea on how to do it.
I'm using Qt with C++. I may change Qt if there is a better option to do this, but I must stick with C++.
You should parse and set accordingly.
Create a QWidget, parse the first line of the text file, set its size. Then parse next lines to get the number of buttons, create widgets dynamically. Something like:
// main
// ...
QString geoLine = stream.readLine();
int width = geoLine.split(" ")[1].toInt();
int height = geoLine.split(" ")[2].toInt();
QWidget * widget = new QWidget();
widget->setGeometry(0, 0, width, height);
// create a layout for the child widgets, then create and add them dynamically.
QVBoxLayout * layout = new QVBoxLayout();
int nButtons = stream.readLine().split(" ")[1];
// full control of dynamically created objects
QList<QPushButton *> buttons;
while(nButtons > 0) {
QPushButton * button = new QPushButton();
buttons.append(button);
layout.addWidget(button);
nButtons--;
}
// same for radio buttons
// ...
widget->setLayout(layout);
widget->show();
// ... etc, app exec,
qDeleteAll(buttons);
delete widget;
return 0;
If you want to learn the widget type from push_button or radio_button directives; you must switch - case onto those parsed strings.
There is also completely another way. You can create a form (.ui) file using an XML data. You must create a ui class (like the template designer form class created by Qt), and create its .ui file according to your text file - parsed and converted to a proper XML.
As far as I know Qt handles the widget creations using that XML information, and generates the file ui_YourClass.h..
As canberk said you can use native Qt UI file format .ui by usage of QUiLoader class - see reference http://doc-snapshot.qt-project.org/qt5-5.4/quiloader.html

How to provide user options with expanding layouts QVBoxLayout in QT

I currently have 3 Vertical Layouts in my form. I want to provide the user the option of resizing them to their liking by stretching them. Can this be achieved with Vertical layouts ?
You can use QSplitter as said before. Even being not possible to add it by Designer, there is a way to solve. Create those frames in your widget (which have no layout), and in your cpp and h file you will do that:
in header, write
class YourClass : public QSplitter
instead
class YourClass : public QWidget
and replace in your cpp these declaration on constructor
QWidget(parent)
for
QSplitter(parent)
I guess it does (or almost, perhaps some other changes will be necessary, as add include files).
EDIT: at this time usin code in a QMainWindow class:
QSpliter *splitter = new QSplitter(this) //or declare 'splitter' in .h file.
splitter->setOrientation(Qt::Vertical);
splitter->addWidget(widget1);
splitter->addWidget(widget2);
splitter->addWidget(widget3);
setCentralWidget(splitter);
As of 4.8.6, it's possible to add a QSplitter in Qt Designer by using the Lay out [horizontally/vertically] in splitter layout option. It's somewhat surprising that it's not listed in the widget box, but you can use it.

Multiple QWidets into one QMainWindow

I am currently learing Qt, and I am stuck on the problem of using multiple QWidgets and one QMainWindow.
I have setup a project which contains 2 QWidgets and one QMainWindow. This is my idea of using it: design both QWidgets as needed, add them to the mainwindow object, connect the buttons to the correct slots and switch the centerwidget when needed. So I started off with one QMainWindow and then added two QWidgets, including the cpp file, the h file and the ui file. On both QWidgets I added one QPushButton, and called it pushButtonConvert.
Then I went to the cpp file attached to the QMainWindow (mainwindow.cpp) and did the following:
EpochToHuman * epochToHuman = new EpochToHuman();
HumanToEpoch * humanToEpoch = new HumanToEpoch();
Up until this point everything is fine. Now I want to connect the buttons to slots in the mainwindow object, but I can not find the buttons. epochToHuman->pushButtonConvert does not seem to exist, and I can not find any other way to get to the buttons. So am I thinking in a way that is not correct, according to Qt or am I missing something?
Another try at clarifying what I want:
I want to use the elements in a QWidget in QMainWindows' cpp file. I want to be able to do things like this:
//In object MainWindow.cpp
QWidget * a = new QWidget
//Let's say a is a custom widget with a label in it. This label is called Label
a->Label->setText("Hello, World!");
//This gives an error because a does not have a member called Label
//How can I change the text on the label of a?
//And I think if I will be able to change the text of this label, I will also be able to dance around with buttons as needed.
You can connect the pushButtonConvert button to MainWindow::convertFromEpochToHuman in the constructor of MainWindow, with:
connect(epochToHuman->ui->pushButtonConvert, SIGNAL(clicked(bool)), this, SLOT(convertFromEpochToHuman()));
You'll need to make the ui member public first, like you have done for HumanToEpoch.
You should move the declaration of your widgets into MainWindow.h:
// ...
private:
Ui::MainWindow *ui;
EpochToHuman * epochToHuman;
HumanToEpoch * humanToEpoch;
// ...
and initialise them like this:
epochToHuman = new EpochToHuman(this);
humanToEpoch = new HumanToEpoch(this);

Qt doesn't display child widget

How can i access ui files of children of a class. Lets say MainWindow class has twoa child dialog. I want to access LINEEDIT of dialog so that i can take text from there. Similarly how can i access ui files of parent inside child class in QT. Note: I havn't inherited any thing from Parent class.
I have writen the following code, in order to display a dialog but it won't show!
void MainWindow::displaydialog()
{
ItemDialog dialog= new ItemDialog(this);
dialog->show(); // it is not displaying the dialog
}
and how can i access the ui widgets like check whether ListWidget item has been selected or not.
Here is the code of itemdialog,
#include "itemdialog.h"
#include "ui_itemdialog.h"
#include "mainwindow.h"
ItemDialog::ItemDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ItemDialog)
{
ui->setupUi(this);
setWindowTitle("Status Dialog");
setFixedSize(QWidget::sizeHint());
}
ItemDialog::~ItemDialog()
{
delete ui;
}
void ItemDialog::on_pushButton_clicked()
{
MainWindow obj;
obj.okbuttonclicked(ui->lineEdit->text());
}
Please review an example such as this: http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
It explains how to use the ui files that you generate from Qt Designer. You shouldn't really think of them as "ui files" in the sense of accessing them on the widgets in your class. The idea is that you include them, and then use their setupUi() function to apply them to your given class. At that point, everything you created in qt designer, and that is in that ui file, is now a member of your class. They can be accessed via the naming you used in qt designer.
As for why your dialog isn't showing...I don't know because you only included 3 lines of code as an example. Theoretically it should show if Mydialog was properly set up. You could just try changing it to a QDialog to make sure you didn't do anything wrong with your custom class.
It depends what you want that dialog for. Either it's a modal dialog - some kind of a information display or retrival that blocks the function of your program until user reacts, or it's somekind of toolbox or similar, in which case you probably should not use QDialog.
If a modal dialog with a line edits and/or additional features is what you want, you should read up on QDialog in the doc. See the exec() function. Basic usage would go like this:
void MainWindow::displaydialog()
{
ItemDialog *dialog = new ItemDialog();
if (dialog->exec() == someApropriateReturnStatus)
{
QString somevalue = dialog->someValue();
int dialog->someOtherValue();
//do something with the value
}
delete dialog;
}
The point is that the ItemDialog class handles the UI internally and implements the getter functions accordingly, you should not (in most typical cases) access it's UI from outside.
If a simple line edit is all you want, you'd be better off using one of the standard dialogs already implemented in Qt, have a look at the Standard Dialogs Example

How to specialize a widget according to a file type?

I'm looking for a way to specialize a widget at runtime. I have a form created with Qt Designer. In this form there is a widget that displays user data, like name, age and so on. Then the user chooses a file and according to the type the widget shall display additional information (like to OO example person -> student, teacher).
I tried to put an empty QWidget on my form, assigned a person widget to it and if the user clicks a button I call deleteLater() on person and assign a new Student(). This works but the new widget then doesn't follow the layout.
I also found QStackedWidget. This seems to work but because all possible widgets are created when the form is shown, even if they are never used, this way doesn't feel right.
What would be the way to accomplish this?
Edit: I feel that my question is a bit unclear. What Qt mechanism should be utilized if one wants to replace a QWidget with a specialized (inherited) version of the original widget? I'm looking for the Qt way to do this.
You need to add a widget dynamically to the widget you have drawn in the designer.
// in UI file
QWidget *wdgFromForm;
// in cpp file
QHBoxLayout *const layout(new QHBoxLayout(wdgFromForm));
SpecializedWidget * specializedWidget( new SpecializedWidget(wdgFromForm));
layout->addWidget(specializedWidget);
Maybe the problem is not that the widget is not suitable, but simply that you're not giving time for the widget to update.
You could take a look at processEvents:
http://web.mit.edu/qt-dynamic/www/qapplication.html#details
This looks like a use case for the factory pattern.
#include <map>
#include <string>
struct Whatever;
struct QWidget;
typedef QWidget*(*WidgetCtor)(Whatever*);
typedef std::map<std::string, WidgetCtor> FileFactory;
QWidget* createFoo(Whatever*);
QWidget* createBar(Whatever*);
QWidget* createDefault(Whatever*);
void factory_init(FileFactory& ff)
{
ff["foo"] = createFoo;
ff["bar"] = createBar;
}
QWidget* create_by_factory(const FileFactory& ff, const std::string t, Whatever* w)
{
FileFactory::const_iterator it(ff.find(t));
if(it != ff.end())
{
return it->second(w);
}
else
{
return createDefault(w);
}
}
Adding widgets dynamically to a layout is not a problem.
You might need to call updateGeometry on the containing widget though.