24、深入理解Processing中的函数使用

深入理解Processing中的函数使用

1. 函数的复用

在编程中,函数的复用是一项非常实用的特性。以绘制气球为例,我们可以通过定义一个绘制气球的函数,然后多次调用该函数来在画布上绘制多个气球。

首先,我们有一个简单的绘制单个气球的程序:

void setup()
{
    size(200, 200);
    balloon();
}
void balloon()
{
    int lineLength = 50;
    int diameter = 20;
    int column = int( random(width) );
    int row = int( random(height) );
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

setup() 函数中的 balloon() 函数调用完成后,程序执行结束。

若要绘制多个气球,我们可以多次调用 balloon() 函数。例如,绘制三个气球的代码如下:

void setup()
{
    size(200, 200);
    balloon();
    balloon();
    balloon();
}
void balloon()
{
    int lineLength = 50;
    int diameter = 20;
    int column = int( random(width) );
    int row = int( random(height) );
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

每次调用 balloon() 函数时,执行流程如下:
1. 执行流程跳转到 balloon() 函数。
2. 执行 balloon() 函数体内的绘制气球的语句。
3. 执行流程返回到调用 balloon() 函数的位置。

另外,我们还可以使用 for 循环来实现绘制多个气球的功能。例如,绘制五个气球的代码如下:

void setup()
{
    size(200, 200);
    for (int count = 1; count <= 5; count = count + 1)
    {
        balloon();
    }
}
void balloon()
{
    int lineLength = 50;
    int diameter = 20;
    int column = int( random(width) );
    int row = int( random(height) );
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

每次 for 循环执行时,都会调用 balloon() 函数,从而在画布上绘制一个随机位置的气球。

2. 函数的参数和参数传递

在前面的例子中, balloon() 函数的参数列表为空。但实际上,函数可以定义参数,以便在调用时传递所需的信息。参数是函数定义中要求传递的信息项,而在调用函数时提供的对应信息项则称为参数。

2.1 添加单个参数

BalloonDraw 程序为例,当前气球的直径是在 balloon() 函数内部通过赋值语句和局部变量指定的:

void setup()
{
    size(200, 200);
    balloon();
}
void balloon()
{
    int lineLength = 50;
    int diameter = 20;
    int column = int( random(width) );
    int row = int( random(height) );
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

为了使气球的直径可以根据我们的需求进行调整,我们需要为 balloon() 函数添加一个参数。在函数头中声明参数变量,就像定义其他变量一样,先指定变量的类型,再指定变量的名称。因此,我们将 balloon() 函数的头修改为:

void balloon(int diameter)

此时,我们有了一个名为 diameter 的参数变量,用于存储调用 balloon() 函数时传递的直径参数值。

由于参数变量是局部变量,其作用域仅限于函数内部。因此,我们需要删除 balloon() 函数体内原来的 int diameter = 20; 语句,修改后的代码如下:

void balloon(int diameter)
{
    int lineLength = 50;
    int column = int( random(width) );
    int row = int( random(height) );
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

然而,当修改了函数定义后,调用 balloon() 函数时会出现错误,因为现在调用函数时必须提供一个参数。错误信息为: The function balloon() expects parameters like "balloon(int)"

为了解决这个问题,我们需要在调用 balloon() 函数时提供一个参数。例如,传递直径为40的参数:

void setup()
{
    size(200, 200);
    balloon(40);
}

这样,当程序运行时, setup() 函数被自动调用,执行到 balloon(40) 时,执行流程跳转到 balloon() 函数,参数值40被传递给 diameter 参数变量,然后执行 balloon() 函数体内的语句,绘制一个直径为40像素的气球。

2.2 添加多个参数

如果我们希望气球可以绘制在指定的像素位置,而不是随机位置,我们需要为 balloon() 函数添加更多的参数。在函数头中添加 column row 参数:

void balloon(int column, int row, int diameter)

添加参数后, balloon() 函数体内原来的随机生成 column row 的语句会出现错误,因为现在有了同名的局部变量。我们需要删除这些语句,修改后的代码如下:

void setup()
{
    size(200, 200);
    balloon(40); // 这里会报错,后续会修改
}
void balloon(int column, int row, int diameter)
{
    int lineLength = 50;
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

此时,调用 balloon() 函数时会再次出现错误,错误信息为: The function balloon() expects parameters like "balloon(int, int, int)"

为了解决这个问题,我们需要在调用 balloon() 函数时提供三个参数。例如,绘制一个中心位于像素列75、像素行100,直径为30像素的气球:

void setup()
{
    size(200, 200);
    balloon(75, 100, 30);
}

在调用函数时,参数的顺序和类型必须与函数定义中的参数列表匹配。第一个参数75会被赋值给 column 参数变量,第二个参数100会被赋值给 row 参数变量,第三个参数30会被赋值给 diameter 参数变量。

下面是函数调用和参数传递的流程图:

graph TD;
    A[开始] --> B[调用setup()函数];
    B --> C[调用size()函数设置画布大小];
    C --> D[调用balloon(75, 100, 30)函数];
    D --> E[跳转到balloon()函数];
    E --> F[将参数75赋值给column,100赋值给row,30赋值给diameter];
    F --> G[执行balloon()函数体内的语句];
    G --> H[绘制气球];
    H --> I[返回调用处];
    I --> J[setup()函数执行结束];
    J --> K[程序结束];
3. Processing中的其他特殊void函数

在Processing中,除了我们自定义的函数外,还有一些特殊的 void 函数,这些函数会自动调用或在特定的鼠标或键盘事件发生时调用。这些函数对于创建动画和交互性非常有用,但对于初学者来说可能会有些困惑。

3.1 draw() 函数

setup() 函数是一个特殊的 void 函数,当我们定义了 setup() 函数时,Processing会自动调用它,且只调用一次。而 draw() 函数是另一个特殊的Processing函数,它提供了一种不同类型的重复机制。

如果我们定义了 draw() 函数,当程序运行且 setup() 函数的操作完成后,Processing会自动反复调用 draw() 函数,直到我们停止程序。这种自动重复调用 draw() 函数的特性在大多数编程语言中是没有的,但它对于创建动画和交互性至关重要。

下面是一个简单的示例,展示了 setup() 函数和 draw() 函数的使用:

void setup()
{
    println("setup() was called");
}
void draw()
{
    println("draw() was called");
}

当运行这个程序时,Processing会先调用 setup() 函数,输出 setup() was called ,然后开始反复调用 draw() 函数,不断输出 draw() was called ,直到我们停止程序。

在使用 draw() 函数时,需要考虑以下两个关键事实:
1. draw() 函数会在 setup() 函数调用完成后立即自动调用。
2. draw() 函数会被反复调用,因此其中包含的语句会不断执行。

综上所述,通过函数的复用、参数传递以及特殊函数的使用,我们可以在Processing中实现更加复杂和灵活的程序。函数的复用可以提高代码的可维护性和可扩展性,参数传递可以使函数更加通用,而特殊函数则为创建动画和交互性提供了强大的支持。

深入理解Processing中的函数使用

4. 特殊函数在动画和交互中的应用

特殊函数在Processing中为动画和交互的实现提供了强大的支持,下面我们将进一步探讨它们在实际应用中的具体用法。

4.1 draw() 函数实现简单动画

draw() 函数的自动重复调用特性非常适合用于创建动画。我们可以通过在 draw() 函数中不断更新图形的位置、大小或颜色等属性,来实现动画效果。

以下是一个简单的动画示例,让一个圆形在画布上不断移动:

int x = 0; // 圆形的初始x坐标

void setup() {
    size(400, 400);
}

void draw() {
    background(255); // 每次绘制前清除画布
    ellipse(x, height/2, 50, 50); // 绘制圆形
    x = x + 2; // 更新圆形的x坐标
    if (x > width) {
        x = 0; // 如果圆形移出画布,重置x坐标
    }
}

在这个示例中, setup() 函数用于设置画布的大小。 draw() 函数会不断被调用,每次调用时,先清除画布,然后绘制一个圆形,接着更新圆形的 x 坐标,使其向右移动。当圆形移出画布时,将 x 坐标重置为0,从而实现圆形在画布上循环移动的动画效果。

4.2 鼠标和键盘事件相关的特殊函数

除了 setup() draw() 函数外,Processing还提供了一些与鼠标和键盘事件相关的特殊函数,这些函数会在特定的鼠标或键盘事件发生时自动调用。

  • mousePressed() :当鼠标按钮被按下时调用。
  • mouseReleased() :当鼠标按钮被释放时调用。
  • keyPressed() :当键盘上的某个键被按下时调用。
  • keyReleased() :当键盘上的某个键被释放时调用。

以下是一个简单的示例,展示了 mousePressed() 函数的使用:

void setup() {
    size(400, 400);
}

void draw() {
    background(255);
}

void mousePressed() {
    fill(random(255), random(255), random(255)); // 随机填充颜色
    ellipse(mouseX, mouseY, 50, 50); // 在鼠标点击位置绘制圆形
}

在这个示例中, setup() 函数设置画布大小, draw() 函数不断清除画布。当鼠标按钮被按下时, mousePressed() 函数会被调用,它会随机生成一种颜色,并在鼠标点击的位置绘制一个圆形。

下面是这些特殊函数的调用时机总结表格:
| 函数名 | 调用时机 |
| ---- | ---- |
| setup() | 程序开始时自动调用,且只调用一次 |
| draw() | setup() 函数执行完成后,自动反复调用,直到程序停止 |
| mousePressed() | 鼠标按钮被按下时调用 |
| mouseReleased() | 鼠标按钮被释放时调用 |
| keyPressed() | 键盘上的某个键被按下时调用 |
| keyReleased() | 键盘上的某个键被释放时调用 |

5. 函数使用的最佳实践

在使用函数时,遵循一些最佳实践可以提高代码的可读性、可维护性和可扩展性。

5.1 函数的单一职责原则

每个函数应该只负责完成一个明确的任务。例如,在前面的气球绘制示例中, balloon() 函数只负责绘制一个气球,这样可以使函数的功能更加清晰,便于理解和维护。如果一个函数承担了过多的任务,会导致代码变得复杂,难以调试和修改。

5.2 参数的合理使用

在定义函数时,要合理使用参数。参数应该是函数完成任务所必需的信息,避免使用过多不必要的参数。同时,要确保参数的类型和顺序在函数定义和调用时保持一致,以避免出现错误。

5.3 注释和文档

为函数添加适当的注释和文档是非常重要的。注释可以帮助其他开发者(也包括未来的自己)理解函数的功能、参数的含义和返回值等信息。例如,在 balloon() 函数前添加注释,说明该函数的作用和参数的用途:

/**
 * 绘制一个气球
 * @param column 气球中心的列坐标
 * @param row 气球中心的行坐标
 * @param diameter 气球的直径
 */
void balloon(int column, int row, int diameter) {
    int lineLength = 50;
    line(column, row, column, row + lineLength);
    fill(255, 0, 0);
    ellipse(column, row, diameter, diameter);
}

下面是函数使用最佳实践的流程图:

graph TD;
    A[定义函数] --> B[遵循单一职责原则];
    B --> C[合理使用参数];
    C --> D[添加注释和文档];
    D --> E[函数调用];
    E --> F[检查参数匹配];
    F --> G[执行函数];
    G --> H[返回结果];

通过遵循这些最佳实践,我们可以编写出更加健壮、易于维护的代码,提高编程效率和代码质量。

综上所述,Processing中的函数使用涵盖了函数的复用、参数传递、特殊函数的应用以及最佳实践等多个方面。掌握这些知识和技巧,可以帮助我们更好地利用Processing进行编程,创建出更加复杂、有趣的程序,实现动画和交互效果。

采用PyQt5框架与Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层和用户界面层。数据持久化方案支持SQLite轻量级数据库与MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入与单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史与违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验与后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值