修改frame快捷方法,不必再繁琐的计算

本文介绍了一种通过创建类别来简化视图控件frame操作的方法,包括属性定义、setter和getter实现,以及如何在代码中使用这个类别来快速调整控件的位置、尺寸。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平时计算控件frame时我们是这样计算的:

//首先设置frame
view.frame = CGRectMake(0, 0, 320, 150);
//如果想改变其中的宽或者高或者位置,则需要重新设置frame大小,这个时候需要重新写一遍以前设置的frame
view.frame = CGRectMake(view.frame.origin.x, 100, view.frame.size.width, view.frame.size.height);


这样写是不是很麻烦,如果遇到很多控件都需要改变的时候,再写这么多设置frame的代码是不是很麻烦呢?那么我们不如就直接创建一个category

一、创建一个类别:

二、写代码

.h 文件定义了 x, y, width, height 等方便读写的属性,代码如下:

#import <UIKit/UIKit.h>

@interface UIView (Layout)

@property (assign, nonatomic) CGFloat    top;
@property (assign, nonatomic) CGFloat    bottom;
@property (assign, nonatomic) CGFloat    left;
@property (assign, nonatomic) CGFloat    right;

@property (assign, nonatomic) CGFloat    x;
@property (assign, nonatomic) CGFloat    y;
@property (assign, nonatomic) CGPoint    origin;

@property (assign, nonatomic) CGFloat    centerX;
@property (assign, nonatomic) CGFloat    centerY;

@property (assign, nonatomic) CGFloat    width;
@property (assign, nonatomic) CGFloat    height;
@property (assign, nonatomic) CGSize    size;

@end
.m 文件实现各个属性的setter和getter方法,代码如下:
#import "UIView+Layout.h"

@implementation UIView (Layout)

@dynamic top;
@dynamic bottom;
@dynamic left;
@dynamic right;

@dynamic width;
@dynamic height;

@dynamic size;

@dynamic x;
@dynamic y;

- (CGFloat)top
{
    return self.frame.origin.y;
}

- (void)setTop:(CGFloat)top
{
    CGRect frame = self.frame;
    frame.origin.y = top;
    self.frame = frame;
}

- (CGFloat)left
{
    return self.frame.origin.x;
}

- (void)setLeft:(CGFloat)left
{
    CGRect frame = self.frame;
    frame.origin.x = left;
    self.frame = frame;
}

- (CGFloat)bottom
{
    return self.frame.size.height + self.frame.origin.y;
}

- (void)setBottom:(CGFloat)bottom
{
    CGRect frame = self.frame;
    frame.origin.y = bottom - frame.size.height;
    self.frame = frame;
}

- (CGFloat)right
{
    return self.frame.size.width + self.frame.origin.x;
}

- (void)setRight:(CGFloat)right
{
    CGRect frame = self.frame;
    frame.origin.x = right - frame.size.width;
    self.frame = frame;
}

- (CGFloat)x
{
    return self.frame.origin.x;
}

- (void)setX:(CGFloat)value
{
    CGRect frame = self.frame;
    frame.origin.x = value;
    self.frame = frame;
}

- (CGFloat)y
{
    return self.frame.origin.y;
}

- (void)setY:(CGFloat)value
{
    CGRect frame = self.frame;
    frame.origin.y = value;
    self.frame = frame;
}

- (CGPoint)origin
{
    return self.frame.origin;
}

- (void)setOrigin:(CGPoint)origin
{
    CGRect frame = self.frame;
    frame.origin = origin;
    self.frame = frame;
}

- (CGFloat)centerX
{
    return self.center.x;
}

- (void)setCenterX:(CGFloat)centerX
{
    CGPoint center = self.center;
    center.x = centerX;
    self.center = center;
}

- (CGFloat)centerY
{
    return self.center.y;
}

- (void)setCenterY:(CGFloat)centerY
{
    CGPoint center = self.center;
    center.y = centerY;
    self.center = center;
}

- (CGFloat)width
{
    return self.frame.size.width;
}

- (void)setWidth:(CGFloat)width
{
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}

- (CGFloat)height
{
    return self.frame.size.height;
}

- (void)setHeight:(CGFloat)height
{
    CGRect frame = self.frame;
    frame.size.height = height;
    self.frame = frame;
}

- (CGSize)size
{
    return self.frame.size;
}

- (void)setSize:(CGSize)size
{
    CGRect frame = self.frame;
    frame.size = size;
    self.frame = frame;
}
@end

三、使用的时候只需要导入#import "UIView+Layout.h"就可以了

view.y = 100;//改变y坐标
view.x = 100;//改变x坐标
view.width = 100;//改变宽度
view.height = 100;//改变高度



/* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : freertos.c * Description : Code for freertos applications ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usart.h" #include "gpio.h" #include "tim.h" #include <string.h> #include <stdio.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define MOTOR_PWM_MAX 19999 // PWM最大值 (Period - 1) #define MOTOR_PWM_MIN 0 // PWM最小值 /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ struct uart3_rx_t { int num,ok,en; uint8_t data[28]; int class; float score; int x1,y1,x2,y2; uint8_t datarx; }uart3_rx; struct uart2_rx_t { int num,ok,en; uint8_t data[3]; int shexiangtou_en; int manzaijianche_en; int dangban_en; int youhailaji_en; int chuyulaji_en; int kehuishou_en; int qitalaji_en; uint8_t datarx; }uart2_rx; struct pingmu_tx_t { int manzai,ok,en; int class; float score; int x1,y1,x2,y2; }pingmu_tx; osThreadId motorTaskHandle; osThreadId motor2TaskHandle; osThreadId manzaiTaskHandle; osThreadId txTaskHandle; osThreadId uart6MutexHandle; // 新增:电机控制和超声波测距任务句柄 osThreadId motorControlTaskHandle; // 电机控制任务句柄 osThreadId ultrasonicTaskHandle; // 超声波测距任务句柄 // 新增:超声波测距变量 float ultrasonic1_distance = 0.0f; // 超声波1测量距离 (cm) float ultrasonic2_distance = 0.0f; // 超声波2测量距离 (cm) // 新增:舵机状态跟踪变量 typedef enum { SERVO_IDLE = 0, // 舵机空闲状态(在原位) SERVO_WORKING = 1, // 舵机正在执行分类动作 SERVO_RETURNING = 2 // 舵机正在回到原位 } ServoState_t; volatile ServoState_t servoState = SERVO_IDLE; // 舵机状态 volatile uint32_t servoWorkStartTime = 0; // 舵机工作开始时间 // 新增:电机启动停止延时控制变量 volatile uint32_t motor1_startConditionStartTime = 0; // 电机1启动条件开始时间 volatile uint32_t motor2_startConditionStartTime = 0; // 电机2启动条件开始时间 volatile uint8_t motor1_startConditionActive = 0; // 电机1启动条件是否激活 volatile uint8_t motor2_startConditionActive = 0; // 电机2启动条件是否激活 volatile uint32_t motor1_stopConditionStartTime = 0; // 电机1停止条件开始时间 volatile uint32_t motor2_stopConditionStartTime = 0; // 电机2停止条件开始时间 volatile uint8_t motor1_stopConditionActive = 0; // 电机1停止条件是否激活 volatile uint8_t motor2_stopConditionActive = 0; // 电机2停止条件是否激活 // 电机当前状态 volatile uint8_t motor1_running = 0; // 电机1是否正在运行 volatile uint8_t motor2_running = 0; // 电机2是否正在运行 volatile uint8_t servo_class_to_act = 0; volatile uint8_t is_playing_manzai = 0; // 满载播报进行中标志 volatile uint32_t manzai_play_start = 0; // 满载播报开始时间 volatile uint32_t garbage_delay_start = 0; // 垃圾识别延迟开始时间 volatile uint8_t garbage_to_play = 0; // 待播放的垃圾类别 // ✅ 新增电机使能状态 typedef enum { MOTOR_ENABLED = 0, MOTOR_DISABLED = 1 } MotorState_t; volatile MotorState_t motorState = MOTOR_ENABLED; // 默认启用 /* USER CODE END Variables */ osThreadId defaultTaskHandle; osSemaphoreId motorHandle; osSemaphoreId motor2Handle; osSemaphoreId rxlubancatHandle; osSemaphoreId rxpingmuHandle; osSemaphoreId bujingdianjiHandle; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ int fun (int a,int b, int c); //_Noreturn void systemMonitorTask(void const * argument); _Noreturn void motor2Task(void const * argument); //_Noreturn void bujingdianjiTask(void const * argument); _Noreturn void manzaiTask(void const * argument); _Noreturn void txTask(void const * argument); // 新增:电机控制和超声波测距任务函数声明 _Noreturn void motorControlTask(void const * argument); // 核心电机控制任务 _Noreturn void ultrasonicTask(void const * argument); // 超声波测距任务 /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void const * argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* GetIdleTaskMemory prototype (linked to static allocation support) */ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } /* USER CODE END GET_IDLE_TASK_MEMORY */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ osMutexDef(uartMutex); osMutexId uartMutexHandle = osMutexCreate(osMutex(uartMutex)); osMutexDef(uart6Mutex); uart6MutexHandle = osMutexCreate(osMutex(uart6Mutex)); /* USER CODE END RTOS_MUTEX */ /* Create the semaphores(s) */ /* definition and creation of motor */ osSemaphoreDef(motor); motorHandle = osSemaphoreCreate(osSemaphore(motor), 1); /* definition and creation of motor2 */ osSemaphoreDef(motor2); motor2Handle = osSemaphoreCreate(osSemaphore(motor2), 1); /* definition and creation of rxlubancat */ osSemaphoreDef(rxlubancat); rxlubancatHandle = osSemaphoreCreate(osSemaphore(rxlubancat), 1); /* definition and creation of rxpingmu */ osSemaphoreDef(rxpingmu); rxpingmuHandle = osSemaphoreCreate(osSemaphore(rxpingmu), 1); /* definition and creation of bujingdianji */ osSemaphoreDef(bujingdianji); bujingdianjiHandle = osSemaphoreCreate(osSemaphore(bujingdianji), 1); /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ // osThreadDef(motorTask, motorTask, osPriorityNormal, 0, 128); // 添加舵机初始化 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); // 舵机1初始位置 //__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); // 舵机2初始位置 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); // 启动PWM输出 // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); // servoState = SERVO_IDLE; // 设置初始状态 // motorTaskHandle = osThreadCreate(osThread(motorTask), NULL); // 保留现有的舵机控制任务 osThreadDef(motor2Task, motor2Task, osPriorityNormal, 0, 128); motor2TaskHandle = osThreadCreate(osThread(motor2Task), NULL); // 保留现有的满载检测任务 osThreadDef(manzaiTask, manzaiTask, osPriorityNormal, 0, 128); manzaiTaskHandle = osThreadCreate(osThread(manzaiTask), NULL); // osThreadDef(systemMonitorTask, systemMonitorTask, osPriorityBelowNormal, 0, 128); // osThreadCreate(osThread(systemMonitorTask), NULL); // 保留现有的串口屏通讯任务 osThreadDef(txTask, txTask, osPriorityNormal, 2, 128); txTaskHandle = osThreadCreate(osThread(txTask), NULL); // 新增:电机控制任务 osThreadDef(motorControlTask, motorControlTask, osPriorityNormal, 0, 256); motorControlTaskHandle = osThreadCreate(osThread(motorControlTask), NULL); // 新增:超声波测距任务 osThreadDef(ultrasonicTask, ultrasonicTask, osPriorityHigh, 0, 256); ultrasonicTaskHandle = osThreadCreate(osThread(ultrasonicTask), NULL); /* USER CODE END RTOS_THREADS */ } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ uint32_t last_activity_time = HAL_GetTick(); uart2_rx.manzaijianche_en = 1; for(;;) { //xSemaphoreTake(rxpingmuHandle,portMAX_DELAY); if(xSemaphoreTake(rxpingmuHandle, 100) == pdTRUE) { switch (uart2_rx.data[1]) { case 1: uart2_rx.shexiangtou_en=0; break; case 0: uart2_rx.shexiangtou_en=1; break; case 3: uart2_rx.manzaijianche_en=0; break; case 2: uart2_rx.manzaijianche_en=1; break; case 4: uart2_rx.dangban_en=0; break; case 5: uart2_rx.dangban_en=1; break; case 6: uart2_rx.youhailaji_en=0; break; case 7: uart2_rx.youhailaji_en=1; break; case 8: uart2_rx.chuyulaji_en=0; break; case 9: uart2_rx.chuyulaji_en=1; break; case 10: uart2_rx.kehuishou_en=0; break; case 11: uart2_rx.kehuishou_en=1; break; case 12: uart2_rx.qitalaji_en=0; break; case 13: uart2_rx.qitalaji_en=1; break; default: break; } last_activity_time = HAL_GetTick(); } if(HAL_GetTick() - last_activity_time > 10000) { // 5秒无活动时软复位 NVIC_SystemReset(); } } /* USER CODE END StartDefaultTask */ } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ void PlayAudio(uint8_t audio_num) { char cmd[] = {0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30, 0xFF,0xFF,0xFF}; cmd[7] = '0' + audio_num; if(osMutexWait(uart6MutexHandle, 100) == osOK) { // 增加超时 HAL_UART_Transmit(&huart6, (uint8_t *)cmd, sizeof(cmd), 100); // 添加超时 osMutexRelease(uart6MutexHandle); // 关键!释放互斥量 } else { // 处理超时错误 Error_Handler(); } } void PlayGarbageAudio(uint8_t garbage_class) { uint8_t audio_num = 0; switch (garbage_class) { case 0: case 1: case 3: audio_num = 2; break; // 可回收 case 2: case 5: audio_num = 1; break; // 厨余 case 7: case 8: audio_num = 0; break; // 有害 default: audio_num = 3; break; // 其他 } PlayAudio(audio_num); } // 保留现有的舵机控制任务 - 增加状态跟踪 _Noreturn void motor2Task(void const * argument) { // 上电首次执行初始化动作 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 1300); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 2030); osDelay(500); // 确保舵机到位 servoState = SERVO_IDLE; for(;;) { xSemaphoreTake(motor2Handle, portMAX_DELAY); //uint8_t current_class = uart3_rx.class; if(is_playing_manzai) { osDelay(100); continue; // 跳过当前动作 } // 🎯 设置舵机工作状态 servoState = SERVO_WORKING; //servoWorkStartTime = HAL_GetTick(); uint8_t current_class = servo_class_to_act; switch (current_class) { //有害垃圾 case 0: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //可回收垃圾 case 1: case 8: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; //厨余垃圾 case 2: case 5: case 6: case 7: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(1000); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2430); break; //其它垃圾 case 3: case 4: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,2000); osDelay(500); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,1570); break; default: __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); break; } osDelay(1000); // 执行分类动作的延时 // 🎯 设置舵机回到原位状态 servoState = SERVO_RETURNING; __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1300); __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,2030); osDelay(1000); // 回到原位的延时 // 🎯 设置舵机空闲状态 servoState = SERVO_IDLE; } osSemaphoreGive(motor2Handle); osDelay(10); } // 保留现有的满载检测任务 _Noreturn void manzaiTask(void const * argument) { for(;;) { osDelay(100); if(HAL_GPIO_ReadPin(load1_GPIO_Port,load1_Pin)==0 || HAL_GPIO_ReadPin(load2_GPIO_Port,load2_Pin)==0 || HAL_GPIO_ReadPin(load3_GPIO_Port,load3_Pin)==0 || HAL_GPIO_ReadPin(load4_GPIO_Port,load4_Pin)==0) { pingmu_tx.manzai=1; xSemaphoreGive(rxlubancatHandle); } } } // 保留现有的串口屏通讯任务 _Noreturn void txTask(void const * argument) { int num=0; const char manzaidata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0xC0,0xAC,0xBB, 0xF8,0xC2,0xFA,0xD4,0xD8,0x22,0xff,0xff,0xff}; // const char kongdata[]={0x74,0x30,0x2E,0x74,0x78,0x74,0x3D,0x22,0x20,0x22,0xff,0xff,0xff}; char play[]={0x70,0x6C,0x61,0x79,0x20,0x30,0x2C,0x30,0x2C,0x30}; unsigned char aa[2]={0}; const char start[]={0x64,0x61,0x74,0x61,0x30,0x2E ,0x69 ,0x6E ,0x73 ,0x65 ,0x72 ,0x74 ,0x28 ,0x22 }; const char end[]={0x22,0x29,0xff,0xff,0xff}; const char end2[]={0xff,0xff,0xff}; //���� const char data1[]={0x5E,0xCD,0xC1,0xB6,0xB9,'\0'}; //���ܲ� const char data2[]={0x5E ,0xB0 ,0xD7 ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //���ܲ� const char data3[]={0x5E ,0xBA ,0xFA ,0xC2 ,0xDC ,0xB2 ,0xB7 ,'\0'}; //ֽ�� const char data4[]={0x5E ,0xD6 ,0xBD ,0xB1 ,0xAD ,'\0'}; //ʯͷ const char data5[]={0x5E ,0xCA ,0xAF ,0xCD ,0xB7 ,'\0'}; //��Ƭ const char data6[]={0x5E ,0xB4,0xC9 ,0xC6 ,0xAC ,'\0'}; //5�ŵ��????? const char data7[]={0x5E ,0x35 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //1�ŵ��????? const char data8[]={0x5E ,0x31 ,0xBA ,0xC5 ,0xB5 ,0xE7 ,0xB3 ,0xD8 ,'\0'}; //�к����� const char data10[]={0x70 ,0x6C ,0x61 ,0x79 ,0x20 ,0x30 ,0x2C ,0x31 ,0x2C ,0x30 ,0xFF ,0xFF ,0xFF }; //�������� const char data11[]={0x5E ,0xB3 ,0xF8 ,0xD3 ,0xE0 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�ɻ������� const char data12[]={0x5E ,0xBF ,0xC9 ,0xBB ,0xD8 ,0xCA ,0xD5 ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; //�������� const char data13[]={0x5E ,0xC6 ,0xE4 ,0xCB ,0xFB ,0xC0 ,0xAC ,0xBB ,0xF8 ,0x5E,'\0'}; const char* data[]={data8,data4,data7,data5,data6,data2,data3,data1,data1,data1,data1}; uart2_rx.manzaijianche_en=0; uart2_rx.shexiangtou_en=1; for(;;) { xSemaphoreTake(rxlubancatHandle,portMAX_DELAY); if(uart3_rx.ok==1 && uart2_rx.shexiangtou_en ==1 ){ uart3_rx.ok=0; HAL_GPIO_TogglePin(led0_GPIO_Port,led0_Pin); uart3_rx.class=uart3_rx.data[1]-0x30; if(uart3_rx.class<0 || uart3_rx.class>9) uart3_rx.class=11; aa[1]=num%10+0x30; aa[0]=num/10+0x30; HAL_UART_Transmit(&huart6, (uint8_t *) start,sizeof(start),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); switch (uart3_rx.class) { case 0: case 2: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data10, strlen(data10),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x30; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�к����� case 5: case 6: case 7: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data11, strlen(data11),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x31; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� case 1: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data12, strlen(data12),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x32; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�ɻ������� case 3: case 4: HAL_UART_Transmit(&huart6, (uint8_t *) data[uart3_rx.class], strlen(data[uart3_rx.class]),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) data13, strlen(data13),0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *)aa, 2,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end, sizeof(end),0xFFFF); play[7]=0x33; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); break;//�������� default: break; } servo_class_to_act = uart3_rx.class; xSemaphoreGive(motor2Handle); num++; if(num>99)num=0; osDelay(2000); } if(pingmu_tx.manzai==1 && uart2_rx.manzaijianche_en==1){ HAL_UART_Transmit(&huart6, (uint8_t *) manzaidata, 20,0xFFFF),pingmu_tx.manzai=0; play[7]=0x34; HAL_UART_Transmit(&huart6, (uint8_t *) play, 10,0xFFFF); HAL_UART_Transmit(&huart6, (uint8_t *) end2, sizeof(end2),0xFFFF); osDelay(2000); } } } // ========== 🎯 新增:电机控制任务 ========== // 功能:控制两个电机的PWM速度,与舵机控制分开 // 电机1:PA6 (TIM3_CH1) // 电机2:PA7 (TIM3_CH2) _Noreturn void motorControlTask(void const * argument) { uint32_t tickCounter = 0; // 延迟启动 osDelay(1000); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // PA6 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); // PA7 for(;;) { // 电机现在由超声波任务自动控制,这里只做周期性检查 if(tickCounter % 50 == 0) { // 可以在这里添加电机状态检查逻辑 } tickCounter++; osDelay(200); } } // 添加DWT周期计数器支持(在main.c初始化) void DWT_Init(void) { if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } } // 微秒级延时函数 void DWT_Delay_us(volatile uint32_t us) { uint32_t start = DWT->CYCCNT; us *= (SystemCoreClock / 1000000); while ((DWT->CYCCNT - start) < us); } // ========== 🎯 新增:超声波测距函数 ========== // 简化版本,避免任务阻塞,返回距离值(cm*10) // 重写超声波测距函数 int32_t measureDistance(GPIO_TypeDef* trig_port, uint16_t trig_pin, GPIO_TypeDef* echo_port, uint16_t echo_pin) { // 发送10us触发脉冲 HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_SET); DWT_Delay_us(10); HAL_GPIO_WritePin(trig_port, trig_pin, GPIO_PIN_RESET); uint32_t start_wait = DWT->CYCCNT; uint32_t timeout_ticks = 30 * (SystemCoreClock / 1000); //uint32_t timeout_cycles = DWT->CYCCNT + (25 * (SystemCoreClock / 1000)); // 25ms超时 while (HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_RESET) { if ((DWT->CYCCNT - start_wait) > timeout_ticks) return -1; // 正确超时判断 } uint32_t echo_start = DWT->CYCCNT; //uint32_t start_time = DWT->CYCCNT; //timeout_cycles = DWT->CYCCNT + (25 * (SystemCoreClock / 1000)); // 25ms超时 //start = HAL_GetTick(); while (HAL_GPIO_ReadPin(echo_port, echo_pin) == GPIO_PIN_SET) { if ((DWT->CYCCNT - echo_start) > timeout_ticks) return -2; } uint32_t echo_end = DWT->CYCCNT; //uint32_t end_time = DWT->CYCCNT; uint32_t pulse_cycles = (echo_end >= echo_start) ? (echo_end - echo_start) : (UINT32_MAX - echo_start + echo_end); // 精确计算脉冲时间(微秒) uint32_t pulse_us = (uint32_t)((uint64_t)pulse_cycles * 1000000 / SystemCoreClock); // 声速补偿(340m/s = 0.034cm/μs) // 距离 = (时间 × 声速) / 2 (往返距离) return (pulse_us * 34 + 5) / 20; // 返回0.1cm单位(+5用于四舍五入) } // ========== 🎯 新增:超声波测距任务 ========== // 真实测距版本,控制电机运行,与舵机同步,不使用USART1发送 _Noreturn void ultrasonicTask(void const * argument) { int32_t last_valid_dist1 = 5000; int32_t last_valid_dist2 = 5000; const int32_t STOP_DISTANCE = 1100; // 5cm停止 const int32_t MIN_DISTANCE = 20; // 2cm (传感器最小有效距离) for(;;) { int32_t dist1 = measureDistance(GPIOB, GPIO_PIN_2, GPIOD, GPIO_PIN_8); int32_t dist2 = measureDistance(GPIOB, GPIO_PIN_3, GPIOD, GPIO_PIN_9); if(dist1 > MIN_DISTANCE && dist1 < 50000) last_valid_dist1 = dist1; if(dist2 > MIN_DISTANCE && dist2 < 50000) last_valid_dist2 = dist2; if(servoState != SERVO_IDLE) { // 舵机运动时停止两个电机 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); } else{ static uint8_t motor1_stop_count = 0; if(last_valid_dist1 < STOP_DISTANCE) { if(++motor1_stop_count > 2) { // 连续3次检测到障碍才停止 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); osDelay(2000); } } else { motor1_stop_count = 0; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 5000); } static uint8_t motor2_stop_count = 0; if(last_valid_dist2 < STOP_DISTANCE) { if(++motor2_stop_count > 2) { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); osDelay(2000); } } else { motor2_stop_count = 0; // 距离比例控制 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 5000); } } osDelay(50); // 缩短延迟至50ms } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ // UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_UART_TxCpltCallback could be implemented in the user file */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* if(huart->Instance == USART6) { // 更健壮的帧检测 static uint8_t frame_buffer[32]; static uint8_t frame_index = 0; // 存储接收到的字节 frame_buffer[frame_index] = uart2_rx.datarx; frame_index = (frame_index + 1) % sizeof(frame_buffer); // 检测结束符 0xFF 0xFF 0xFF if(frame_index >= 3 && frame_buffer[frame_index-3] == 0xFF && frame_buffer[frame_index-2] == 0xFF && frame_buffer[frame_index-1] == 0xFF) { // 复制有效数据 memcpy(uart2_rx.data, frame_buffer, frame_index-3); uart2_rx.num = frame_index-3; uart2_rx.ok = 1; frame_index = 0; xSemaphoreGiveFromISR(rxpingmuHandle, &xHigherPriorityTaskWoken); } HAL_UART_Receive_IT(&huart6, (uint8_t*)&uart2_rx.datarx, 1); }*/ if(huart->Instance == USART6) { static uint8_t frame_buffer[64]; static uint8_t frame_index = 0; // 溢出保护 if(frame_index >= sizeof(frame_buffer)) { frame_index = 0; } frame_buffer[frame_index++] = uart2_rx.datarx; // 检测结束符 0xFF 0xFF 0xFF if(frame_index >= 3 && frame_buffer[frame_index-3] == 0xFF && frame_buffer[frame_index-2] == 0xFF && frame_buffer[frame_index-1] == 0xFF) { // 复制有效数据 uint8_t len = (frame_index-3 < sizeof(uart2_rx.data)) ? frame_index-3 : sizeof(uart2_rx.data); memcpy(uart2_rx.data, frame_buffer, len); uart2_rx.num = len; uart2_rx.ok = 1; frame_index = 0; xSemaphoreGiveFromISR(rxpingmuHandle, &xHigherPriorityTaskWoken); } HAL_UART_Receive_IT(&huart6, (uint8_t*)&uart2_rx.datarx, 1); } if(huart ->Instance == USART1){ HAL_GPIO_TogglePin(led1_GPIO_Port,led1_Pin); if(uart3_rx.datarx=='@') uart3_rx.num=0; uart3_rx.data[uart3_rx.num]=uart3_rx.datarx; uart3_rx.num++; if(uart3_rx.num>=28){ uart3_rx.num=0; if(uart3_rx.data[27]==']'){ uart3_rx.ok=1; xSemaphoreGiveFromISR(rxlubancatHandle, &xHigherPriorityTaskWoken); } uart3_rx.num = 0; // 重置缓冲区 } HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart3_rx.datarx, 1); } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /* USER CODE END Application */ 这个程序串口六为什么一直发送乱码,怎么解决
最新发布
08-01
<think>嗯,用户问的是如何在Java中修改框架(Frame)的属性,特别是从创建Frame方法外部进行修改。首先,我需要确认用户对Java GUI编程的基础了解程度。他们可能在使用AWT的Frame类或者Swing的JFrame类,但问题中没有明确说明。不过通常,Swing更为常见,所以可能需要提到两者的情况。 接下来,用户提到的是“createframe外面的方法”,这可能意味着他们有一个创建Frame方法,现在想在其他方法修改这个Frame的属性。这里的关键点是如何在方法外部访问Frame的实例。通常,如果Frame实例是在另一个方法中创建的,而没有将其作为返回值或存储在类的成员变量中,外部方法就无法访问它。因此,我需要考虑如何让Frame实例在需要修改的地方可见。 可能的解决方案包括:将Frame作为类的成员变量,这样其他方法可以直接访问;或者通过返回值传递Frame的引用。此外,使用事件监听器也是一种方式,比如在按钮点击时修改属性,这可能涉及内部类或lambda表达式。 另外,需要确保用户了解如何正确修改Frame的属性,比如设置标题、大小、可见性等。还要注意线程安全的问题,特别是在Swing中,更新GUI组件应该在事件分派线程中进行,使用SwingUtilities.invokeLater()。 可能用户在实际操作中遇到了无法访问Frame实例的问题,或者修改属性没有生效的情况。这时候需要检查变量的作用域和访问权限,以及是否正确调用了相关方法。例如,setTitle()只是更改标题,但可能需要调用repaint()或重新验证组件,不过通常set方法会自动触发更新。 总结回答的结构应该是先解释如何在不同作用域中访问Frame实例,然后给出具体的代码示例,说明如何通过成员变量、返回值或事件监听器来实现。同时提醒线程安全和Swing与AWT的区别,确保用户能够正确应用这些方法。</think>在Java中修改`JFrame`(或AWT的`Frame`)属性时,若需要从外部方法修改,需要确保你能访问到该`JFrame`实例的引用。以下是具体实现方法及示例: --- ### 1. **通过成员变量共享引用** 将`JFrame`声明为类的成员变量,其他方法均可访问: ```java import javax.swing.*; public class MyFrameDemo { // 声明为成员变量 private JFrame frame; public void createFrame() { frame = new JFrame("初始标题"); frame.setSize(400, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } // 外部方法修改属性 public void modifyFrame() { if (frame != null) { frame.setTitle("修改后的标题"); frame.setSize(600, 400); frame.setLocationRelativeTo(null); // 居中 } } public static void main(String[] args) { MyFrameDemo demo = new MyFrameDemo(); demo.createFrame(); // 稍后调用修改方法 demo.modifyFrame(); } } ``` --- ### 2. **通过返回值传递引用** 在创建方法中返回`JFrame`实例: ```java public class FrameFactory { public static JFrame createFrame() { JFrame frame = new JFrame("初始标题"); frame.setSize(400, 300); return frame; } public static void main(String[] args) { JFrame myFrame = createFrame(); myFrame.setVisible(true); // 外部修改 myFrame.setTitle("外部修改的标题"); } } ``` --- ### 3. **通过事件监听器间接修改** 在按钮点击等事件中动态修改属性: ```java import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class EventModifyDemo { private JFrame frame; public void createFrame() { frame = new JFrame("可修改的窗口"); JButton button = new JButton("点击修改大小"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 通过事件监听器修改 frame.setSize(800, 600); frame.setTitle("已修改"); } }); frame.add(button); frame.setSize(400, 300); frame.setVisible(true); } public static void main(String[] args) { new EventModifyDemo().createFrame(); } } ``` --- ### 关键点总结: 1. **作用域控制** - 确保`JFrame`实例在需要修改方法中可见(通过成员变量、参数传递等方式)。 2. **线程安全(Swing专属)** - 如果通过非事件线程(如主线程)修改GUI,需使用`SwingUtilities.invokeLater()`: ```java SwingUtilities.invokeLater(() -> { frame.setTitle("安全修改"); }); ``` 3. **常见属性方法** ```java frame.setTitle("新标题"); // 修改标题 frame.setSize(width, height); // 调整大小 frame.setLocation(x, y); // 设置位置 frame.setResizable(false); // 禁止调整大小 frame.setVisible(false); // 隐藏窗口 ``` 4. **AWT与Swing区别** - 若使用AWT的`Frame`,方法类似但需注意包名: ```java import java.awt.Frame; Frame frame = new Frame("AWT窗口"); ``` --- 通过上述方法,你可以灵活地在Java中跨方法修改`JFrame`或`Frame`的属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值