光盘完成-qt-动画

`QPropertyAnimation` 是 Qt 中用于属性动画的类,它允许你动画化任何 QObject 的属性。当你使用 `QPropertyAnimation`,你应该注意以下几点:

1. **对象和属性的类型**:

   - `QPropertyAnimation` 仅支持继承自 `QObject` 的对象,并且属性必须是可访问的(即具有公共的 setter 和 getter 函数)。

   - 属性的类型必须是 Qt 的内建类型或者是通过 `Q_DECLARE_METATYPE` 宏注册过的自定义类型。

2. **属性的可动画性**:

   - 不是所有属性都可以动画化。例如,大部分集合属性(如 `QList`, `QVector` 等)通常不能直接动画化。

   - `QPropertyAnimation` 主要用于动画化数值和颜色属性。

3. **设置目标对象和属性**:

   - 在创建 `QPropertyAnimation` 实例后,需要使用 `setTargetObject()` 方法设置动画的目标对象。

   - 使用 `setPropertyName()` 方法设置要动画化的属性的名称。

4. **动画持续时间和值范围**:

   - 使用 `setDuration()` 设置动画的持续时间(毫秒)。

   - 使用 `setStartValue()` 和 `setEndValue()` 设置属性的起始值和结束值。

5. **启动动画**:

   - 使用 `start()` 方法启动动画。

**示例**:

假设你有一个 `QLabel` 对象,你想动画化它的 `geometry` 属性(即其位置和大小)。

```cpp

QLabel *label = new QLabel("Hello, Qt!");

label->setGeometry(100, 100, 100, 30); // 设置初始位置和大小

QPropertyAnimation *animation = new QPropertyAnimation(label, "geometry");

animation->setDuration(1000); // 设置动画持续时间为1秒

animation->setStartValue(QRect(100, 100, 100, 30)); // 初始位置和大小

animation->setEndValue(QRect(200, 200, 200, 60)); // 结束位置和大小

animation->start(); // 启动动画

```

在上述示例中,我们创建了一个 `QPropertyAnimation` 对象,并设置其目标对象为 `label`,属性名称为 "geometry"。然后,我们设置了动画的持续时间、起始值和结束值,并启动了动画。

确保目标对象存在且有效,以及属性名称正确且可动画化,这样才能确保 `QPropertyAnimation` 正常工作。


test 2:
#include //旋转特性
//0959
class DiskItem : public QObject,public QGraphicsItem
{
 Q_OBJECT
 Q_INTERFACES(QGraphicsItem)
 //0627 0959 这里写的 anagle-anagle
 Q_PROPERTY(qreal anagle READ rotation WRITE setRotation)
 

fx分析:

这段代码定义了一个名为 `DiskItem` 的类,该类同时继承自 `QObject` 和 `QGraphicsItem` 类。让我们逐行分析这段代码:

```cpp

#include //旋转特性

```

- 这行代码包含了 Qt 中用于属性动画的头文件。

```cpp

class DiskItem : public QObject,public QGraphicsItem

{

    Q_OBJECT

    Q_INTERFACES(QGraphicsItem)

    //0627 0959 这里写的 anagle-anagle

    Q_PROPERTY(qreal anagle READ rotation WRITE setRotation)

```

- 定义了一个名为 `DiskItem` 的类,该类同时继承自 `QObject` 和 `QGraphicsItem` 类。

- 使用 `Q_OBJECT` 宏声明了该类,以便使用 Qt 的元对象系统,这允许在类中使用信号和槽机制等 Qt 特性。

- 使用 `Q_INTERFACES(QGraphicsItem)` 宏声明了该类实现了 `QGraphicsItem` 接口,这是为了让 Qt 的图形系统能够正确处理该类的对象。

- 使用 `Q_PROPERTY` 宏声明了一个属性,该属性名为 `anagle`,是一个浮点数类型 (`qreal`)。该属性的读取函数为 `rotation()`,写入函数为 `setRotation()`。这表示该类的对象可以被动态地旋转,而且这个旋转属性可以通过属性动画系统来动画化。

总的来说,这段代码定义了一个 `DiskItem` 类,该类是一个自定义的图形项,可以被动态地旋转,而且可以通过 Qt 的属性动画系统来实现旋转动画。


test3

DiskItem::DiskItem(QObject *parent) : QObject(parent),

  animation(new QPropertyAnimation(this,"anagle",this))//anagle 必须和前面的一致

{

  diskImg.load(":/Image/disk.png");

  animation->setDuration(8000);//ms

  animation->setStartValue(0);

  animation->setEndValue(360);

  animation->setLoopCount(-1);//-1无限xunh

}


分析:

这段代码是 `DiskItem` 类的构造函数实现。让我们逐行分析:

```cpp

DiskItem::DiskItem(QObject *parent) : QObject(parent),

  animation(new QPropertyAnimation(this,"anagle",this))//anagle 必须和前面的一致

{

```

- 这是 `DiskItem` 类的构造函数。在构造函数中,首先调用了父类 `QObject` 的构造函数,将 `parent` 作为参数传递,以确保正确地初始化对象的父对象关系。

- 接着,使用成员初始化列表初始化了一个 `QPropertyAnimation` 对象 `animation`,该动画对象的目标对象为 `this`,即当前 `DiskItem` 对象。属性名称为 "anagle",这里应该是笔误,应该为 "angle",与前面的 `Q_PROPERTY` 宏中声明的属性名称一致。

  

```cpp

  diskImg.load(":/Image/disk.png");

```

- 加载了一个名为 "disk.png" 的图像文件。这个文件应该在资源文件(Resource File)中,路径以 `:/Image/disk.png` 表示。加载后的图像将会存储在 `diskImg` 变量中。

```cpp

  animation->setDuration(8000);//ms

```

- 设置了动画的持续时间为 8000 毫秒,即 8 秒。

```cpp

  animation->setStartValue(0);

  animation->setEndValue(360);

```

- 设置了动画的起始值和结束值分别为 0 和 360。这意味着该动画将从 0 度旋转到 360 度。

```cpp

  animation->setLoopCount(-1);//-1无限xunh

}

```

- 设置了动画的循环次数为 -1,表示无限循环。这意味着动画将会一直循环播放,直到手动停止。

总的来说,这段代码完成了 `DiskItem` 对象的初始化工作,包括加载图像、设置旋转动画的属性、起始值、结束值和循环次数。


test5;l
 void update(const QRectF &rect = QRectF());

这段代码定义了一个名为 `update` 的函数,它接受一个 `QRectF` 类型的参数 `rect`,默认值为一个空的 `QRectF` 对象。

```cpp

void update(const QRectF &rect = QRectF());

```

这个函数的作用是更新对象的内容,并且它可能只更新给定的矩形区域。这意味着,如果提供了一个矩形参数,那么只会更新该矩形范围内的内容;如果没有提供参数,则可能更新整个对象的内容。

在 Qt 中,`update()` 函数用于通知系统需要重绘(即调用绘图事件函数 `paintEvent()`)一个部分或全部的窗口部件,以响应程序中的数据或状态的变化。这个函数是间接调用的,通常在需要更新 UI 时会由 Qt 系统自动调用,但也可以手动调用。

例如,在一个自定义的图形项类中,当对象的内部数据发生变化需要重新绘制时,可以调用 `update()` 函数来触发重绘。

```cpp

// 例子:在自定义图形项类中调用 update() 函数

void MyGraphicsItem::setData(/* some data */) {

    // 更新数据

    // ...

    

    // 调用 update() 函数,通知系统需要重新绘制对象

    update();

}

```

如果想要只更新部分区域,可以传递一个矩形参数:

```cpp

// 例子:只更新给定的矩形区域

QRectF dirtyRect(/* calculate dirty rectangle */);

update(dirtyRect);

```

这样可以提高性能,避免不必要的重绘。


test6
 virtual QRectF boundingRect() const ;

这段代码定义了一个名为 `boundingRect` 的虚函数,返回一个 `QRectF` 类型的矩形。这个函数是用于在 Qt 的图形系统中确定对象的边界矩形(Bounding Rectangle)的。

```cpp

virtual QRectF boundingRect() const;

```

在 Qt 中,当自定义一个图形项(Graphics Item)时,需要实现这个函数。这个函数返回的矩形描述了对象在场景中所占的空间,用于确定对象的绘制区域,以及鼠标事件的碰撞检测等。

通常情况下,`boundingRect` 函数应该返回一个能够包围整个对象的矩形,即使这个矩形比对象的实际形状稍大也没有关系,但不应该返回一个比对象实际形状更小的矩形。

例如,如果有一个自定义的圆形图形项类 `CircleItem`,那么 `boundingRect` 函数可以这样实现:

```cpp

QRectF CircleItem::boundingRect() const {

    qreal radius = /* calculate radius */;

    return QRectF(-radius, -radius, 2 * radius, 2 * radius).adjusted(-1, -1, 1, 1);

}

```

这个函数返回的矩形以圆心为原点,边长为直径的矩形,稍微扩大了一点以确保能够完全包围圆形。


test7
QRectF DiskItem::boundingRect() const
{
 return QRectF(diskImg.width()/ -2.0,diskImg.height()/-2.0,diskImg.width(),diskImg.height());
}

这是 `DiskItem` 类的 `boundingRect` 函数的实现,它返回一个 `QRectF` 类型的矩形,该矩形描述了对象的边界区域。通过查看代码,我们可以了解它是如何计算边界矩形的。

```cpp

QRectF DiskItem::boundingRect() const

{

    return QRectF(diskImg.width() / -2.0, diskImg.height() / -2.0, diskImg.width(), diskImg.height());

}

```

在这段代码中:

1. **x 和 y 的起始位置**:矩形的左上角坐标计算为 `diskImg.width() / -2.0` 和 `diskImg.height() / -2.0`,这意味着矩形是以其中心点为基准,向左和向上偏移半个图像宽度和高度。这表明 `DiskItem` 对象是围绕其中心点进行定位和旋转的。

2. **宽度和高度**:矩形的宽度和高度分别为 `diskImg.width()` 和 `diskImg.height()`,即矩形的大小与 `diskImg` 图像的宽度和高度相同。

结合这些信息,`boundingRect` 函数的实现将返回一个矩形,该矩形的中心位于 `(0, 0)`,宽度和高度分别为 `diskImg` 图像的宽度和高度。这种边界矩形用于确定绘制区域,并帮助 Qt 图形系统执行碰撞检测和场景布局。

因此,`boundingRect` 的定义和 `diskImg` 图像的尺寸有关,确保该矩形能完全包含整个图像。

 


tset 8
 //paint
 virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

Q_UNUSED(option)
 Q_UNUSED(widget)

`Q_UNUSED(option)` 和 `Q_UNUSED(widget)` 是用来告诉编译器,我们在函数中声明了这两个参数,但是在函数体内并没有使用它们。这样做的目的是为了避免编译器产生未使用参数的警告。

有时候,在函数签名中可能会包含一些参数,但在函数实现中并不需要使用它们,这可能是因为函数的设计考虑到了未来可能的扩展或者兼容性。在这种情况下,为了避免编译器发出未使用参数的警告,我们可以使用 `Q_UNUSED` 宏来明确告诉编译器这些参数是有意未使用的。


test i9
test 10:
Q_SIGNALS:
 void mediaChanged(const QMediaContent &media);
 void currentMediaChanged(const QMediaContent &media);
 
 void stateChanged(QMediaPlayer::State newState);
 void mediaStatusChanged(QMediaPlayer::MediaStatus status);