Python-VBA函数之旅-staticmethod函数

目录

一、staticmethod函数的常见应用场景

二、staticmethod函数使用注意事项

三、如何用好staticmethod函数?

1、staticmethod函数:

1-1、Python:

1-2、VBA:

2、推荐阅读:

个人主页: https://blog.csdn.net/ygb_1024?spm=1010.2135.3001.5421

一、staticmethod函数的常见应用场景

        staticmethod函数在Python中用于定义静态方法,这些方法属于类的一部分,但不依赖于类的实例或类本身的状态,静态方法主要用于将工具函数或与类紧密相关的辅助函数与类相关联,但又不需要访问或修改类的实例或类级别的状态。该函数的常见应用场景有:

1、设计模式中的实现:在设计模式中,静态方法可以用于实现如工厂方法模式、单例模式等,工厂方法模式允许子类决定实例化哪一个类,而单例模式确保一个类只有一个实例,并提供一个全局访问点。

2、类级别的缓存:静态方法可以用于实现类级别的缓存,这样所有实例都可以共享缓存的数据,而不是每个实例都有自己的缓存。例如,一个 API 调用类可能使用静态方法来缓存 API 响应,以减少对同一资源的重复请求。

3、工具函数和实用程序:当需要在多个类中重复使用某些工具函数或实用程序时,可以将它们定义为静态方法,这样,这些函数就可以与类一起被导入和使用,而无需单独导入它们。

4、类的初始化或配置:静态方法可以用于执行与类相关的初始化或配置任务,这些任务通常不需要在类的每个实例中重复执行。例如,一个数据库连接类可能使用静态方法来建立与数据库的连接,并将连接对象存储在类变量中,供所有实例共享。

5、与类相关的计算:有时,某些计算或操作与类紧密相关,但并不涉及类的实例状态,这些计算或操作可以定义为静态方法。例如,一个数学类可能包含用于计算特定数学函数(如阶乘、斐波那契数列等)的静态方法。

6、模拟或模拟对象:在测试或模拟环境中,静态方法可以用于模拟类或对象的行为,通过覆盖类的静态方法,可以模拟类的某些行为,以便在测试中验证代码的正确性。

7、与框架或库的集成:当与某些框架或库集成时,可能需要使用静态方法来遵循特定的接口或约定,这些静态方法可能是框架或库期望的回调或钩子函数,用于执行特定的操作或处理特定的事件。

8、函数式编程风格:虽然Python主要是一种面向对象的编程语言,但它也支持函数式编程风格,静态方法可以被视为一种将函数与类相关联的方式,以便在函数式编程和面向对象编程之间实现更平滑的过渡。

9、多线程或异步编程中的回调函数:在多线程或异步编程中,回调函数通常与类相关,但不需要访问类的实例状态,在这种情况下,静态方法可以用作回调函数。

        注意,虽然静态方法在某些高级应用场景中很有用,但它们也应该谨慎使用;过度使用静态方法可能会导致代码难以理解和维护,因为它们破坏了面向对象编程中的封装和继承原则,因此,在决定是否使用静态方法时,应该仔细考虑其优点和缺点,并权衡其对代码质量和可维护性的影响。

二、staticmethod函数使用注意事项

        在Python中,staticmethod()是一个内置函数,用于将一个方法转换为一个静态方法。静态方法不需要类的实例作为第一个参数(即通常的self参数),它们可以通过类本身直接调用,也可以通过类的实例调用,使用staticmethod()函数时,需注意以下事项:

1、不需要实例:静态方法不需要类的实例来调用,因此它们不会接收self参数,如果你尝试在静态方法的定义中包含self参数,它将被视为一个普通的参数,而不是对类实例的引用。

2、可以通过类和实例访问:静态方法可以通过类本身或类的实例来访问。例如,如果你有一个名为MyClass的类,并且它有一个静态方法my_static_method(),你可以通过 MyClass.my_static_method()或my_instance.my_static_method()(其中my_instance是MyClass的一个实例)来调用它。

3、无法访问或修改实例状态:由于静态方法不接收self参数,因此它们无法直接访问或修改类的实例状态,如果你需要在方法中访问或修改实例状态,你应该使用实例方法(即包含self参数的方法)。

4、可用于工厂方法:静态方法经常用作工厂方法,用于创建并返回类的实例,工厂方法可以根据需要创建并配置类的实例,而无需直接调用类的构造函数。

5、不要误用:虽然静态方法在Python中是合法的,但过度使用它们可能会导致代码结构不清晰,在大多数情况下,如果你可以通过实例方法或类方法来实现某个功能,那么最好不要使用静态方法。

6、装饰器语法:从Python 2.6开始,你可以使用@staticmethod装饰器来定义静态方法,而不是使用staticmethod()函数,这通常会使代码更简洁、更易于阅读。

7、静态方法与类方法:虽然静态方法和类方法都不需要实例参数,但类方法会接收类本身作为第一个参数(通常命名为 `cls`),而静态方法则不会;类方法通常用于修改类状态或执行与类本身相关的操作,而静态方法则更常用于执行与类无关的操作。

三、如何用好staticmethod函数?

        在Python中,staticmethod()函数(或更常见的@staticmethod装饰器)通常用于定义那些与类本身紧密相关但不需要访问或修改类实例状态的方法,这些静态方法通常用于执行与类相关的实用功能,但不需要访问类的内部状态或实例

以下是关于如何用好staticmethod()函数的一些建议:

1、明确用途:首先,确定你确实需要一个静态方法,如果方法需要访问或修改实例状态,那么它应该是一个实例方法;如果方法需要访问或修改类状态,那么它应该是一个类方法。

2、使用装饰器语法:Python提供了@staticmethod装饰器,这使得定义静态方法更加简洁,尽可能使用装饰器语法,而不是显式地调用staticmethod()函数。

3、避免不必要的静态方法:如果一个方法既不需要访问类状态也不需要访问实例状态,并且它完全独立于类的其他部分,那么考虑是否应该将其定义为一个模块级别的函数,而不是类的静态方法。

4、使用有意义的名称:为静态方法选择清晰、描述性的名称,以便其他开发者能够理解该方法的作用和用途。

5、避免在静态方法中引用实例属性或方法:静态方法不应该引用实例属性或方法,因为它们不接收实例作为参数,如果静态方法需要访问实例数据,那么它可能更适合作为实例方法。

6、作为工厂方法:静态方法的一个常见用途是作为工厂方法,用于创建并返回类的实例;工厂方法可以根据不同的参数创建和配置类的实例,从而提供更大的灵活性。

7、文档化:为静态方法编写文档字符串(docstring),解释方法的作用、参数、返回值和可能的副作用,这将有助于其他开发者理解如何使用你的静态方法。

8、测试:编写针对静态方法的单元测试,以确保它们按预期工作,测试将帮助你验证方法的正确性,并在未来修改代码时防止引入错误。

        总之,只有通过遵循这些建议,你才能更好地利用Python中的staticmethod()函数,并编写出清晰、可维护和可测试的代码。

1、staticmethod函数:
1-1、Python:
# 1.函数:staticmethod
# 2.功能:用于标示方法为静态方法的装饰器
# 3.语法:
# 3-1、staticmethod(function)
# 3-2、@staticmethod
#      def f(arg1, arg2, ...): ...
# 4.参数:
# 4-1、function:方法名
# 4-2、arg1:方法的参数1
# 4-3、arg2:方法的参数2
# 5.返回值:返回函数的静态方法
# 6.说明:
# 7.示例:
# 用dir()函数获取该函数内置的属性和方法
print(dir(staticmethod))
# ['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__',
# '__ge__', '__get__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__',
# '__isabstractmethod__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
# '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__wrapped__']# 用help()函数获取该函数的文档信息
help(staticmethod)# 应用一:设计模式中的实现
class Product:def __init__(self, name):self.name = namedef use(self):print(f"Using product: {self.name}")
class ProductFactory:@staticmethoddef create_product(product_type):if product_type == "A":return ProductA("Product A")elif product_type == "B":return ProductB("Product B")else:raise ValueError("Invalid product type")
class ProductA(Product):def __init__(self, name):super().__init__(name)print(f"Creating {name} of type A")
class ProductB(Product):def __init__(self, name):super().__init__(name)print(f"Creating {name} of type B")
# 使用工厂方法创建产品
product_a = ProductFactory.create_product("A")
product_a.use()
product_b = ProductFactory.create_product("B")
product_b.use()
# Creating Product A of type A
# Using product: Product A
# Creating Product B of type B
# Using product: Product B
# 尝试创建一个无效类型的产品
# ValueError: Invalid product type
# product_c = ProductFactory.create_product("C")
# product_c.use()# 应用二:类级别的缓存
class CachedClass:_cache = {}  # 类级别的缓存字典@staticmethoddef get_cached_value(key):"""从缓存中获取值"""return CachedClass._cache.get(key)@staticmethoddef set_cached_value(key, value):"""将值存储到缓存中"""CachedClass._cache[key] = value@staticmethoddef compute_expensive_operation(key):"""执行一个昂贵的操作,并缓存结果"""if key not in CachedClass._cache:print(f"Computing value for key {key}...")# 假设这是一个昂贵的操作value = key * 2  # 示例操作CachedClass.set_cached_value(key, value)return CachedClass.get_cached_value(key)
# 使用缓存的示例
print(CachedClass.compute_expensive_operation(1))  # 输出: Computing value for key 1... 和 2
print(CachedClass.compute_expensive_operation(1))  # 直接从缓存中获取,不重新计算
print(CachedClass.compute_expensive_operation(2))  # 输出: Computing value for key 2... 和 4
# Computing value for key 1...
# 2
# 2
# Computing value for key 2...
# 4# 应用三:工具函数和实用程序
class MathUtilities:@staticmethoddef add_numbers(a, b):"""简单的加法工具函数"""return a + b@staticmethoddef multiply_numbers(a, b):"""简单的乘法工具函数"""return a * b@staticmethoddef is_prime(n):"""检查一个数是否为质数的实用程序"""if n <= 1:return Falseelif n == 2:return Trueelif n % 2 == 0:return Falseelse:for i in range(3, int(n ** 0.5) + 1, 2):if n % i == 0:return Falsereturn True
# 使用工具函数和实用程序
print(MathUtilities.add_numbers(5, 3))  # 输出: 8
print(MathUtilities.multiply_numbers(4, 6))  # 输出: 24
print(MathUtilities.is_prime(7))  # 输出: True
print(MathUtilities.is_prime(10))  # 输出: False
# 8
# 24
# True
# False# 应用四:类的初始化或配置
class MyClass:_config = {}  # 类的配置字典,作为类变量存储@staticmethoddef set_config(key, value):"""设置类的配置值"""if key not in MyClass._config:print(f"Setting new config value for {key}")MyClass._config[key] = value@staticmethoddef get_config(key):"""获取类的配置值"""return MyClass._config.get(key)def __init__(self, value, use_default_config=True):"""初始化方法,可以使用默认配置或自定义配置"""if use_default_config:# 如果要使用默认配置,可以从_config中获取self.value = value * MyClass.get_config('multiplier')else:# 否则,直接使用给定的值self.value = value
# 设置类的配置
MyClass.set_config('multiplier', 2)
# 创建类的实例,使用默认配置
instance1 = MyClass(5, use_default_config=True)
print(instance1.value)  # 输出: 10 (因为5 * 2 = 10)
# 创建类的另一个实例,不使用默认配置
instance2 = MyClass(5, use_default_config=False)
print(instance2.value)  # 输出: 5 (因为直接使用给定的值)
# 修改类的配置
MyClass.set_config('multiplier', 3)
# 创建类的另一个实例,使用新的默认配置
instance3 = MyClass(5, use_default_config=True)
print(instance3.value)  # 输出: 15 (因为5 * 3 = 15)
# Setting new config value for multiplier
# 10
# 5
# 15# 应用五:与类相关的计算
import math
class Circle:pi = math.pi  # 圆的π值,作为类变量存储@staticmethoddef area(radius):"""计算圆的面积"""return Circle.pi * (radius ** 2)@staticmethoddef circumference(radius):"""计算圆的周长"""return 2 * Circle.pi * radius
# 使用静态方法进行计算
radius = 5
area_result = Circle.area(radius)
circumference_result = Circle.circumference(radius)
print(f"圆的面积为: {area_result}")
print(f"圆的周长为: {circumference_result}")
# 圆的面积为: 78.53981633974483
# 圆的周长为: 31.41592653589793# 应用六:模拟或模拟对象
class BankAccount:def __init__(self, balance):self.balance = balance@staticmethoddef calculate_interest(balance, interest_rate):"""模拟计算利息的静态方法"""return balance * (interest_rate / 100)def add_interest(self, interest_rate):"""给账户增加利息的方法"""interest = BankAccount.calculate_interest(self.balance, interest_rate)self.balance += interestprint(f"Interest added: {interest}")print(f"New balance: {self.balance}")
# 创建一个银行账户实例
account = BankAccount(1000)
# 使用静态方法计算利息(但通常这步是在add_interest方法内部完成的)
# 这里只是为了演示静态方法的使用
interest = BankAccount.calculate_interest(account.balance, 5)
print(f"Calculated interest: {interest}")
# 使用实例方法给账户增加利息
account.add_interest(5)
# Calculated interest: 50.0
# Interest added: 50.0
# New balance: 1050.0# 应用七:与框架或库的集成
class MessageQueueClient:# 假设有一个全局的消息队列连接或配置# 这里只是示意,实际情况中可能需要更复杂的配置和连接管理QUEUE_CONNECTION = None  # 模拟的消息队列连接@staticmethoddef configure_queue(connection_details):"""配置消息队列连接(静态方法)"""MessageQueueClient.QUEUE_CONNECTION = connection_detailsprint(f"Configured message queue with details: {connection_details}")@staticmethoddef send_message(message):"""发送消息到消息队列(静态方法)"""if MessageQueueClient.QUEUE_CONNECTION is None:raise RuntimeError("Message queue is not configured.")# 这里只是模拟发送消息,实际情况中会使用QUEUE_CONNECTION发送消息print(f"Sending message to queue: {message}")# 假设消息成功发送return True
# 使用静态方法配置消息队列
MessageQueueClient.configure_queue("localhost:1068")
# 使用静态方法发送消息
success = MessageQueueClient.send_message("Hello, Message Queue!")
if success:print("Message sent successfully.")
# Configured message queue with details: localhost:1068
# Sending message to queue: Hello, Message Queue!
# Message sent successfully.# 应用八:函数式编程风格
class MathTools:@staticmethoddef add(a, b):"""函数式风格的加法"""return a + b@staticmethoddef multiply(a, b):"""函数式风格的乘法"""return a * b@staticmethoddef factorial(n):"""函数式风格的阶乘"""if n == 0 or n == 1:return 1return n * MathTools.factorial(n - 1)
# 使用静态方法进行计算
result_add = MathTools.add(3, 4)
result_multiply = MathTools.multiply(5, 6)
result_factorial = MathTools.factorial(5)
print(f"Addition result: {result_add}")
print(f"Multiplication result: {result_multiply}")
print(f"Factorial of 5: {result_factorial}")
# Addition result: 7
# Multiplication result: 30
# Factorial of 5: 120# 应用九:多线程或异步编程中的回调函数
import threading
import time
class MultiThreadDemo:@staticmethoddef worker(thread_name, delay):"""静态方法作为线程的工作函数(回调函数)"""print(f"Thread {thread_name} starting...")time.sleep(delay)print(f"Thread {thread_name} finished.")@staticmethoddef create_and_start_threads(num_threads, delay):"""创建并启动多个线程"""for i in range(num_threads):t = threading.Thread(target=MultiThreadDemo.worker, args=(f"Thread-{i + 1}", delay))t.start()
# 使用静态方法创建并启动线程
MultiThreadDemo.create_and_start_threads(num_threads=3, delay=2)
# 主线程将等待所有其他线程完成(在这个例子中,我们只是简单地让主线程休眠以确保其他线程有机会运行)
time.sleep(5)  # 等待足够长的时间以确保所有线程都完成
print("All threads finished.")
# Thread Thread-1 starting...
# Thread Thread-2 starting...
# Thread Thread-3 starting...
# Thread Thread-1 finished.
# Thread Thread-3 finished.Thread Thread-2 finished.
#
# All threads finished.
1-2、VBA:
略,待后补。
2、推荐阅读:

2-1、Python-VBA函数之旅-property()函数

Python算法之旅:Algorithm

Python函数之旅:Functions

个人主页: https://blog.csdn.net/ygb_1024?spm=1010.2135.3001.5421

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/325188.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HackMyVM-VivifyTech

目录 信息收集 arp nmap nikto whatweb WEB web信息收集 wpscan feroxbuster hydra 提权 系统信息收集 横向渗透 git提权 get root 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 08:00:27:9d:6d:7b, …

【密评】 | 商用密码应用安全性评估从业人员考核题库(9/58)

Hill密码是重要古典密码之一&#xff0c;其加密的核心思想的是&#xff08;&#xff09;。 A.线性变换 B.非线性变换 C.循环移位 D.移位 著名的Kerckhoff原则是指&#xff08;&#xff09;。 A.系统的保密性不但依赖于对加密体制或算法的保密&#xff0c;而且依赖于密钥 B.系统…

即插即用篇 | YOLOv8 引入 Strip Pooling | 重新思考场景解析的空间池化

本改进已集成到 YOLOv8-Magic 框架。 空间池化已被证明在捕获像素级预测任务的长距离上下文信息方面非常有效,如场景解析。在本文中,我们超越了通常具有N N规则形状的常规空间池化,重新思考空间池化的构成,引入了一种新的池化策略,称为条带池化,它考虑了一个长而窄的核,…

C++ 中的 lambda 表达式

1.概念 lambda表达式实际上是一个匿名类的成员函数&#xff0c;该类由编译器为lambda创建&#xff0c;该函数被隐式地定义为内联。因此&#xff0c;调用lambda表达式相当于直接调用匿名类的operator()函数&#xff0c;这个函数可以被编译器内联优化&#xff08;建议&#xff0…

C++的数据结构(二)

一、链表的基本概念 链表&#xff08;Linked List&#xff09;是一种物理存储单元上非连续的、非顺序的线性数据结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点&#xff08;链表中每一个元素称为节点&#xff09;组成&#xff0c;节点…

py黑帽子学习笔记_网络编程工具

tcp客户端 socket.AF_INET表示使用标准IPV4地址和主机名 SOCK_STREAM表示这是一个TCP客户端 udp客户端 udp无需连接&#xff0c;因此不需要client.connect这种代码 socket.SOCK_DGRAM是udp的 tcp服务端 server.listen(5)表示设置最大连接数为5 发现kill server后端口仍占用…

牛客NC404 最接近的K个元素【中等 二分查找+双指针 Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/b4d7edc45759453e9bc8ab71f0888e0f 知识点 二分查找&#xff1b;找到第一个大于等于x的数的位置idx;然后从idx开始往两边扩展Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、…

Shell编程规范与变量

Shell 什么是Shell&#xff1f; 就是与内核沟通的界面、应用程序等等。比如你要播放音乐&#xff0c;你的计算机通过你在Shell输入的打开音乐的命令&#xff0c;Shell在告诉操作系统的内核用户希望打开音乐&#xff0c;内核在通过cpu调度、内存管理、磁盘输入输出等工作&#…

JAVA课程设计

一&#xff1a;Java连接mysql数据库 1.1点击进入mysql jar包下载官网 MySQL :: MySQL Community Downloads 将下载好的压缩包进行解压 解压之后下图就是连接数据库所用到的jar包&#xff1a; 将jar包复制到IDEA所用的项目下&#xff0c;放置jar包的目录为lib&#xff0c;需要…

NSS刷题

[SWPUCTF 2021 新生赛]jicao 类型&#xff1a;PHP、代码审计、RCE 主要知识点&#xff1a;json_decode()函数 json_decode()&#xff1a;对JSON字符串解码&#xff0c;转换为php变量 用法&#xff1a; <?php $json {"ctf":"web","question"…

安装Nox夜神模拟器关闭了HyperV后Docker运行不了怎么办?

1.背景 为了模拟真机&#xff0c;尝试安装了Nox夜神模拟器&#xff0c; 安装过程要求关闭Hyper-V。当时只是在程序安装卸载中关闭了系统服务。以为到时勾选上就好了。操作路径&#xff1a;控制面板\所有控制面板项\程序和功能\启用或关闭Windows功能\Hyper-V。 后来卸载掉了夜神…

FreeRTOS的列表和列表项 list.c文件详解

列表、列表项的定义以及初始化 列表相当于链表&#xff0c;列表项相当于节点&#xff0c;FreeRTOS中的列表相当于一个双向环形链表。 列表使用指针指向列表项。一个列表&#xff08;list&#xff09;下面可能有很多个列表项&#xff08;list item&#xff09;&#xff0c;每个…

vivado仿真readmemb函数相对路径

目前常用的vivado工程的结构如下所示 prj-name|-xxx|-prj.sim|-sim_1|-behav|-modelsim|-tb_prj.do|-xsim|-prj.srcs|-sim_1|-new|-tb_prj.v|-tb_prj_mem.txt一般来说我们创建的testbench文件和新建的txt文件都会放在srcs->sim_1->new这个路径下面&#xff0c;但是我们在…

【PHP【实战版】系统性学习】——登录注册页面的教程,让编写PHP注册变成一个简单的事情

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

最美博客POETIZE个人博客系统源码

源码说明&#xff1a; POETIZE个人博客系统源码 | 最美博客 这是一个基于SpringBoot、Vue2和Vue3的开源项目&#xff0c;支持移动端自适应&#xff0c;并具备完善的前台和后台管理功能。 网站分为两个模块&#xff1a; 1. 博客系统&#xff1a;包括文章、表白墙、图片墙、收…

SpringBoot实现图片验证码

引入依赖 <dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version> </dependency>代码实现 package com.qiangesoft.captcha.controller;import com.wf.captcha.*…

【Linux】基础命令:进程、网络

systemctl命令 控制内置服务 systemctl start | stop | status | enable | disable 服务名 start | stop开启关闭&#xff0c;status状态&#xff0c;enable | disable开启关闭开机自启 date命令 查看系统时间 date [-d] [格式化字符串] date -d “1 day” %Y-%m-%d 修改时区…

Stable Diffusion:AI绘画的新纪元

摘要&#xff1a; Stable Diffusion&#xff08;SD&#xff09;作为AI绘画领域的新星&#xff0c;以其开源免费、强大的生成能力和高度的自定义性&#xff0c;正在引领一场艺术与技术的革命。本文旨在为读者提供Stable Diffusion的全面介绍&#xff0c;包括其原理、核心组件、安…

链表的经典面试题(数据结构详解)+顺序表和链表之间区别+计算机存储体系

前言 首先这里已经正式步入数据结构的知识&#xff0c;之前我们已经讲解了链表的使用&#xff0c;接下来我们需要的就是大量的练习&#xff0c;熟练掌握数据结构。下面的题型我们选择的都是链表的经典题型&#xff0c;面试题型&#xff0c;包含快慢指针&#xff0c;数形结合&am…

【qt】设计器实现界面

设计器实现界面 一.总体思路二.具体操作1.创建项目2.粗略拖放3.水平布局4.垂直布局5.修改名字6.转到槽7.实现槽函数 一.总体思路 创建项目粗略拖放水平布局垂直布局修改名称转到槽实现槽函数 二.具体操作 1.创建项目 这次咱们一定要勾选Generate form哦。 因为我们要使用设…