MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
In this section of code, after : what does
QMainWindow(parent),
ui(new Ui::MainWindow)
mean?
This is actually a C++ question. What you're looking at are called initialization lists. The QMainWindow(parent) calls that constructor for MainWindow's superclass (QMainWindow) and ui(new Ui::MainWindow) constructs ui member.
By way of further explanation, observe that the class generated by the user interface compiler is also called (in this case) MainWindow, but it belongs to the namespace Ui, so its full name is Ui::MainWindow. This is emphatically not the same as the MainWindow class that inherits from QMainWindow. However, the QMainWindow-derived class has a member pointer (called ui) to a Ui::MainWindow, which is initialized in the constructor, as explained above. Have a look at the uic-generated file ui_mainwindow.h to see how all the pieces fit together. Note also that the members of Ui::MainWindow are all public and therefore fully accessible within MainWindow.
An alternative design is to merge the identity of the two MainWindow classes using multiple inheritance, deriving your own MainWindow from both QMainWindow and Ui::MainWindow. However, the code generated by current version of QtCreator follows the composition pattern rather than the inheritance pattern.
These two lines are the so-called initialization list and are executed at "creation" time of each instance of this class. Each class inheriting another should contain a call to the superclass' constructor in this list.
You could also write:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui = new Ui::MainWindow();
ui->setupUi(this);
}
which one could find better readable. But using an initialization list is slightly faster and is being optimized by the compiler. Note that these lists can only be used in constructors and you cannot call any functions of the object - because it doesn't "live" yet. But you may set the value of some attributes and refer to them in following statements (to avoid code redundancy for example), like in the following example:
#define DEFAULT_VALUE 1.0
class MyClass {
public:
MyClass() :
value1(DEFAULT_VALUE),
value2(value1)
{
}
MyClass(qreal value) :
value1(value),
value2(value1)
{
}
private:
qreal value1;
qreal value2;
};
Note that most compilers give you a warning if the order of the members in your initialization list doesn't match the order in the class definition.
Related
I have a Qt-GUI called "mainWindow".
In the constructor I am using a class called "testclass", which uses a widget from the GUI.
mainWindow::mainWindow(QWidget *parent): QMainWindow(parent)
{
testclass window_test(ui.Widget);
window_test.function();
}
Now I would like to access functions of "window_test" outside of the constructor.
I tried to add
testclass window_test(ui.Widget);
as a class member to the mainWindow class but I can't access ui.Widget there.
Whats the best way to handle this situation?
Have you declared the prototypes of your functions in the header file of your mainWindow? It may simply be a scope issue.
I added the instance of "testclass" to mainWindow.h but I had to use a standard constructor for it. Therefore I declared a new function to pass the widget to the class.
If you have to pass a parameter to the constructor of your member variable window_test, you can do it like this:
mainWindow::mainWindow(QWidget *parent) : QMainWindow(parent),
window_test(ui.Widget)
{
}
The declaration of the member variable is simply
class mainWindow {
...
testwindow window_test;
};
If ui is itself a member variable of mainWindow which has a constructor, the order of declaration can be important. ui should then be declared before window_test so it is already constructed when it's used.
The MainWindow code generated by QtCreator says:
namespace Ui {
class MainWindow; // forward-declare Ui::MainWindow (?)
}
class MainWindow : public QMainWindow // Declare MainWindow class (Ui::MainWindow?)
{
Q_OBJECT
public:
explicit MainWindow( QWidget *parent = 0 );
/**/ ~MainWindow( void );
// ...
private:
Ui::MainWindow *ui;
// ...
};
main() does:
MainWindow w;
w.show( );
MainWindow::MainWindow( QWidget *parent ) does:
ui( new Ui::MainWindow ) // Initialization
I don't understand why a MainWindow instance has a pointer to another/a different/a new MainWindow in its ui instance variable. I instrumented the MainWindow::MainWindow constructor, and I can see it's only being called once. So presumably that's the automatic variable on the stack in main(). But what about the ui( new Ui::MainWindow ) that happens in the constructor? That's creating a MainWindow on the heap, isn't it? How is it being initialized?
Maybe the subsequent ui->setupUi( this ) in the constructor is doing some magic? Otherwise, it seems like this would recurse to stack crash, as each new MainWindow creates a new MainWindow to populate its ui instance variable.
The Ui::MainWindow class is code generated by uic from the respective QtDesigner file.
It is not a widget but a helper that contains code to populate a widget.
So in your case it is code that is used to populate a QMainWindow derived class named MainWindow.
Ui::MainWindow is held as a pointer to allow forward declaration and avoid build dependencies of code including MainWindow's header to the generate code (which will change everytime you change something in QtDesigner)
There are two different classes in play here:
::MainWindow
::Ui::MainWindow
I wouldn't go so far as to say they are not related - but they are not the same class.
I have several different classes derived from QGraphicsItem or its children (like QGraphicsRectItem). I am at the point when I need to copy selected objects of those classes while not knowing exactly which one I copy.
Since QGraphicsScene::selectedItems() return a list of selected items I decided to use it, however I cannot copy the QGraphicsItem since its an abstract class. To address this I am trying to copy the object using malloc and memcpy.
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene();
item = new QGraphicsRectItem(50,50,50,50);
item->setFlag(QGraphicsItem::ItemIsSelectable);
scene->addItem(item);
item->setSelected(true);
ui->graphicsView->setScene(scene);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
for(QGraphicsItem *item : scene->selectedItems())
{
QGraphicsItem *copiedItem=(QGraphicsItem *)malloc(sizeof(*item));
memcpy(copiedItem, item, sizeof(*copiedItem));
copiedItem->moveBy(50, 50);
scene->addItem(copiedItem);
qDebug() << item;
qDebug() << copiedItem;
}
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QGraphicsScene *scene;
QGraphicsRectItem *item;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
GUI consisting of QGraphicsView and QPushButton is sufficient for this example.
This code seem to work, item and copiedItem have different addresses but the same properties as qDebug() returns.
The scene however return the following error:
QGraphicsScene::addItem: item has already been added to this scene
I don't quite understand why the scene thinks the items are the same while they have different addresses. Is there any way to solve this issue?
EDIT:
If possible I would like to do this without modifying the code of classes derived from QGraphicsItem, since this is a group work and I would not like to bug other functionalities.
If you look at the class definition inside qgraphicsitem.h, you'll see the following:
private:
Q_DISABLE_COPY(QGraphicsItem)
Q_DECLARE_PRIVATE(QGraphicsItem)
What this means is that, by design, you are not supposed to copy a QGraphicsItem, each object is supposed to be unique.
EDIT:
I would imagine that the reason that you are denied the copying ability is because QGraphicsItem follows the Composite Design Pattern. Creating a copy of a single object that has child items would result in child items having more than one parent. To get round that, you'd have to not only copy the item you're interested in but every child in the child hierarchy as well. For very large hierarchies, this can become a very time-consuming operation.
If you really feel that you need to make copies, you can create a cloning factory function/class that creates a clone of the QGraphicsItem and all it's children by going through all the object's properties and transferring them to a newly created QGraphicsItem.
If this is not feasible, perhaps think about accomplishing your goal in a different way.
You really want to be using the copy constructor or the assignment operator, not malloc and memcpy. This is how you copy objects in C++:
QGraphicsItem copiedItem = *item;
The problem of copying a class by block copying its memory with malloc is that if the class contains pointers to objects or arrays, then only a shallow copy will occur.
In your case of getting pointers to a QGraphicsItem, you'll need to identify the type of item you're copying (its actual child class, not base class) and use the copy constructor. QGraphicsItem includes a function called type(), which returns an int that indicates which item it is. You can also add to this in your own derived classes by implementing the type() function. For example, from the Qt docs: -
class CustomItem : public QGraphicsItem
{
...
enum { Type = UserType + 1 };
int type() const
{
// Enable the use of qgraphicsitem_cast with this item.
return Type;
}
...
};
Alternatively, if all the classes are your own type, you could use your own system.
Once you know the type, you can then copy the item with its copy constructor: -
// Example, assuming type denotes a QGraphicsItemRect
QGraphicsItemRect rect = (*originalRect);
Note that if you have inherited from QGraphicsItem and added members that are pointers, you'll need to add your own copy constructor to ensure a deep copy occurs, instead of a shallow copy.
I am trying to understand the following code.(I am learning C++)
class DefaultDevice : public Device {
public:
DefaultDevice() :
ui(new DefaultUI) {
}
private:
RecoveryUI* ui;
};
class DefaultUI : public ScreenRecoveryUI {
...
}
I am having little trouble understanding ui(new DefaultUI) part.
As I understand it is part of initialization before DefaultDevice() constructor is executed.
Then, from my understanding, it is going to call ReocoveryUI constructor with new DefaultUI argument. But, RecoveryUI class does not have any constructor with such argument.(sorry for not posing RecoveryUI class. it's too long :( if anyone interested in, it is Android Open source code)
so what does this 'new DefaultUI' do?
If that is a valid and working code, It seems RecoveryUI is a base class for DefaultUI.
ui(new DefaultUI) creates an object and assigns it to ui.
So, ui points to its child object.
It is not run before the ctor, it is part of the ctor. It's called an initializer list and it's used to initialize the (non-static) member variables of a class.
I just have those questions about those code sinppets from the C++ GUI Programming with Qt 4 book:
GoToCellDialog::GoToCellDialog(QWidget *parent):QDialog(parent)
Does that mean we are inheriting QDialog(parent)? Or, what exactly does this mean?
setupUi(this);
Here, this code snippet is part of the gotocelldialog.cpp file, which is the implementation of gotocelldialog.h header file. What do we mean by this in this context? What are we trying to setup? And, what kind of setup will that be?
Thanks.
GoToCellDialog::GoToCellDialog(QWidget *parent) : QDialog(parent)
: signifies an initializer list. And it meant, parent is being passed as a parameter to QDialog constructor. I assume GoToCellDialog is derived from QDialog and so sending parent to it's constructor. So, before even body of GoToCellDialog is executed, QDialog constructor is executed.
This example should give you an idea -
class foo
{
int number ;
public:
foo(int i) : number(i) // Means copying value of i to number
{}
};
class bar : public foo
{
public:
bar(int temp) : foo(temp)
{ // <- Before getting here, foo sub object must be constructed.
// Because the order of construction takes from parent to child.
}
};
In the above example, definitely an argument for foo constructor must be passed while instantiation of bar. So, initializer list is the only way because there is no default constructor( i.e., constructor with no arguments) available for foo.
To answer your questions:
Does that mean we are inheriting QDialog(parent)?
Yes, this is basic C++ inheritance.
setupUi(this);
In short: The 'User Interface compiler' (uic) compiles/translates the xml file to C++ code which will be compiled and linked. The setupUi() function ensures that the Qt designer widgets you made (generated C++ code) are setup to be used by your code by Building the Widget tree.