Project Problem Solving Record (C++&Qt)

Project Problem Solving Record (C++&Qt)


I am a rookie.
This blog is mainly used to record the C++ and Qt problems encountered in the project.
It will be updated from time to time.


General knowledge points

  • The functions defined in the class definition are all **inline functions**, even if the inline specifier is not used;

Pros: When the function body is small, inlining the function can make the object code more efficient. Inlining is encouraged for accessor functions and other performance-critical functions with short function bodies.
Cons: Overuse of inlining will slow down the program. Inlining may increase or decrease the object code size, depending on the size of the inlined function.
Conclusion: A reasonable rule of thumb is to not inline functions longer than 10 lines.

  • There are three ways of inheritance: public, protected, and private:
  1. Public inheritance: the access attributes of public members, protected members, and private members of the base class become: public, protected, and private in the derived class respectively
  2. protected inheritance: base class public members, protected members, and private members access attributes become: protected, protected, private respectively in derived classes
  3. Private inheritance: The access attributes of public members, protected members and private members of the base class become: private, private and private respectively in the derived class.

If the inheritance does not show that the declaration is private, protected, or public inheritance, the default is private inheritance, and the default public inheritance in struct:

  • A virtual function is a function declared using the keyword virtual in a base class. When you redefine a virtual function defined in a base class in a derived class, you tell the compiler not to statically link to that function.
    What we want is that at any point in the program we can choose which function to call based on the type of object being called. This operation is called dynamic linking, or late binding. (The official statement is a bit abstract, and there are examples later to understand it better)

Add const and statement block after the function

This is to modify the entire function as const, which means "the member data cannot be changed in the function body". If you declare a const instance of this class, it can only call const-decorated functions.

    QColor textColor() const { return myTextColor; }                    // 把整个函数修饰为const,后面的花括号是函数实现
    QColor itemColor() const { return myItemColor; }
    QColor lineColor() const { return myLineColor; }

Constructor

A class constructor is a special member function of a class that is executed every time a new object of the class is created.

Has the following characteristics

  • The name of the constructor is exactly the same as the name of the class
  • Will not return any type, and will not return void
  • Constructors can be used to set initial values ​​for certain member variables

** Example: **
The example comes from the rookie tutorial:
https://www.runoob.com/cplusplus/cpp-constructor-destructor.html

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

** operation result: **

Object is being created, length = 10
Length of line : 10
Length of line : 6

A class destructor is a special member function of a class that is executed every time a created object is deleted.

Has the following characteristics

  • The name of the destructor is exactly the same as the name of the class, just prefixed with a tilde (~)
  • It does not return any value and cannot take any parameters.
  • Destructors help to release resources before exiting the program (such as closing files, freeing memory, etc.).

Example:
The example comes from the rookie tutorial:
https://www.runoob.com/cplusplus/cpp-constructor-destructor.html

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();   // 这是构造函数声明
      ~Line();  // 这是析构函数声明
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
Line::~Line(void)
{
    cout << "Object is being deleted" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;

   return 0;	 // 自动调用析构函数
}

** operation result: **

Object is being created
Length of line : 6
Object is being deleted

override

The override reserved word indicates that the current function overrides the virtual function of the base class
**Purpose**:

  1. In the case of many functions, the reader can be prompted that a certain function rewrites the virtual function of the base class (indicating that the virtual function is inherited from the base class, not defined by the derived class itself);
  2. Force the compiler to check whether a function overrides the base class virtual function, and report an error if it does not.

virtual function

The role of virtual functions: to explain in professional terms is to achieve polymorphism (Polymorphism), polymorphism is to separate the interface from the implementation; to explain in a visual language is to achieve a common method, but adopt different methods due to individual differences strategy.
Example:
The example comes from Baidu Know:
https://zhidao.baidu.com/question/1797274966344020227.html

#include<iostream>
usingnamespacestd;
classA
{
public:
	voidprint()
	{
		cout<<"ThisisA"<<endl;
	}
};
classB:publicA
{
public:
	voidprint()
	{
		cout<<"ThisisB"<<endl;
	}
};
int main()
{
	//为了在以后便于区分,我这段main()代码叫做main1
	Aa;
	Bb;
	a.print();
	b.print();
	return0;
}

The output results are "ThisisA" and "ThisisB" respectively. Through the print() interface of class A and class B, it can be seen that these two classes adopt different strategies due to individual differences, but does this really achieve polymorphism? No, another key point of polymorphism is that all objects are manipulated with pointers or references to the base class. Then change the code at main() now.

intmain()
{
	//main2
	Aa;
	Bb;
	A*p1=&a;
	A*p2=&b;
	p1->print();
	p2->print();
	return0;
}

Run it to see the result, yo, suddenly looking back, the result is two This is A. Here comes the problem, p2 clearly points to the object of class B but calls the print() function of class A. This is not the result we expected, so to solve this problem, we need to use virtual functions

classA
{
	public:
	virtualvoidprint(){cout<<"ThisisA"<<endl;}
	};
classB:publicA
	{
	public:
	voidprint(){cout<<"ThisisB"<<endl;}
};

There is no doubt that the member function print() of class A has become a virtual function, so has the print() of class B become a virtual function? The answer is Yes, we only need to set the member functions of the base class to virtual, and the corresponding functions of its derived classes will automatically become virtual functions. Therefore, print() of class B has also become a virtual function. Then whether you need to use the virtual keyword to modify the corresponding function of the derived class is your own question.
Now re-run the code of main2, so that the output results are This is A and This is B.
Summary: When the pointer to the base class operates its polymorphic class object, it will call its corresponding function according to different class objects. This function is a virtual function.

QGraphicsScene and QGraphicsview and item

The QGraphics graphics view framework consists of 3 parts:

  • QGraphics Scene
  • Graphics Item
  • Graphics View

Scene is responsible for providing the scene of the graphic view framework, which is equivalent to a canvas, manages all Items, and has the following functions:

  1. A quick interface for managing a large number of graphical items.
  2. Propagate events to each graphic item
  3. Manage the state of graphical items, such as selection, focus handling, etc.
  4. Provides rendering without conversion, mainly for printing

Add: addItem(item) // the coordinates of the scene
Delete: removeItem(item)
Set the background as a picture: setBackgroundBrush(QPixmap(""))
Scene boundary rectangle: setSceneRect(QRectF())

View provides an instance window to observe QGraphicsScene. The view window is a scrollable area that provides a scroll bar for navigating through large scenes.
Zoom in and out: QGraphicsView::scale(xScale, yScale); //Scale xScale and yScale times in the x and y directions respectively. If it is 1.0 times, no scaling will be performed.
view and scene: QGraphicsView::setScene() // view binds scene, view and scene are displayed in a center-aligned manner

Item provides a lightweight foundation for writing your own custom items. This includes defining the item's geometry, collision detection, its drawing implementation and item interaction via event handlers.
For ease of use, Qt provides some of the most commonly used basic standard primitives:

  • QGraphicsEllipseItem provides an ellipse object
  • QGraphicsLineItem provides line objects
  • QGraphicsPathItem provides path objects
  • QGraphicsPixmapItem provides image objects
  • QGraphicsPolygonItem provides polygon objects
  • QGraphicsRectItem provides a rectangle object
  • QGraphicsSimpleTextItem provides a text label object
  • QGraphicsTextItem provides advanced text browsing objects.
    When these do not meet the requirements (for example: when some specific shapes are required), they often need to be customized. The usual way is to inherit QGraphicsItem (QGraphicsObject)

Reference:
https://blog.csdn.net/Bing_Lee/article/details/106106414
https://blog.csdn.net/xiezhongyuan07/article/details/79262573

Custom Item

Two virtual functions must be rewritten
void paint(): Draw the content of the item in local coordinates
QRectF boundingRect(): Return the outer boundary of the item as a rectangle Called by QGraphicsView to determine what area needs to be redrawn
In addition, there may be Other requirements need to be attached, such as:

  • QPainterPath shape() The item's shape is used by contains() and collidesWithPath() for collision detection. Defaults to boundingRect() if not implemented.
  • Use signal/slot, attribute mechanism: inherit QObject and QGraphicsItem (or directly inherit QGraphicsObject)
  • Handle mouse events: reimplement mouse···Event()
  • Handle keyboard events: reimplement key···Event()
  • Handle drag and drop events: reimplement drag···Event(), dropEvent(), etc.

The figure below shows the main settings of the two functions
[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-cGzESUGz-1633746670045)(D:\Downloads\shape&boundingRect.png)] for
reference :
https://www.cnblogs.com/klcf0220/p/10316510.html

Limit the movement range of Items inside QGraphicsScene

In the project, the item will move with the mouse and move to a place other than the view window. To limit the moving range of the item, the data shows that QGraphicsItem provides a virtual function ItemPositionChange function to notify the position of the belonging QGraphicsItem is about to change,
QVariant QGraphicsItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
and the value The value is the future position coordinates of QGraphicsItem

QVariant Networkitem::itemChange(GraphicsItemChange change, const QVariant& value)
{
    if (change == ItemPositionChange && scene()) // 控件是否发生移动
    {
        for (Arrow* arrow : qAsConst(arrows))	// 更新arrow
            arrow->updatePosition();

        QPointF newPos = value.toPointF(); 		//即将要移动的位置
        QRectF rect(0, 0, scene()->width(), scene()->height()); 	// 限制的区域,scene需要提前设定好大小
        if (!rect.contains(newPos)) // 是否在区域内
        {
            newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));		// 设置限制
            newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
            return newPos;
        }
    }
    return QGraphicsItem::itemChange(change, value);		// Qt图形机制,不必深究
}

Reference:
https://blog.csdn.net/diaotaoning2896/article/details/102055010

Guess you like

Origin blog.csdn.net/p3116002589/article/details/120438168