qt实现一个安卓测试小工具

qt实现一个安卓测试小工具

  • 最终效果:
  • 目录结构
  • 源码
    • gui.py 主要是按钮,文本控制代码
    • main.py 主要是逻辑代码
    • gui.spec 是打包使用的
    • adb.ui
  • 打包为exe

最终效果:

在这里插入图片描述
在这里插入图片描述

目录结构

上面2个是打包的生成的不用管
在这里插入图片描述

源码

gui.py 主要是按钮,文本控制代码

from PySide2.QtCore import QTimer, QTime, QDateTime
from PySide2.QtWidgets import QApplication, QMessageBox
from PySide2.QtUiTools import QUiLoader
from main import PackNameOperate, Log, wifi_adb_connect, Devices, input_text,LogcatManager,capture_screenshot
import os, sys
import subprocessdev = Devices()
log=LogcatManager('D:/jb/logcat')def processPath(path):''':param path: 相对于根目录的路径:return: 拼接好的路径'''if getattr(sys, 'frozen', False):  # 判断是否存在属性frozen,以此判断是打包的程序还是源代码。false为默认值,即没有frozen属性时返回falsebase_path = sys._MEIPASS  # 该属性也是打包程序才会有,源代码尝试获取该属性会报错else:base_path = os.path.abspath(".")  # 当源代码运行时使用该路径return os.path.join(base_path, path)txt=r'''1、日志保存路径'D:\jb\logcat',截图保存路径'D:\jb\tu',路径不存在会自动创建
2、应用切换功能是输入2个包名,点一下按钮可以切换到其中一个,在点一下就是切到另一个,如此循环
3、开启wifi adb是新开一个tcpip端口进行wifiadb连接,开启成功后马上拔掉adb线,不然这个wifiadb会被干掉,当然也可以在点一次
4、如果按钮啥的不起作用,可以看看是不是设备离线了,把adb线拔了在插上就可以了,按钮被禁用是检查到没有设备连接而不是设备离线。 ゚゚・。・゚゚。       ゚。        。゚    ゚・。・゚    ︵                 ︵(        ╲        /       /╲          ╲/       /╲          ╲  /╭ ͡   ╲          ╲╭ ͡   ╲        ╲         ノ
╭ ͡   ╲        ╲         ╱╲
'''
class Stats:def __init__(self):self.kill_list = ['获取当前运行的包名','杀掉当前启动的app','清除当前app缓存信息', '清楚缓存并且杀掉app', '清楚缓存并且杀掉app并且重新启动']self.ui = QUiLoader().load(processPath('adb.ui'))# 下拉框添加内容self.ui.kill_apps.addItems(self.kill_list)# 按钮点击事件self.ui.qd_app.clicked.connect(self.qd)self.ui.zx.clicked.connect(self.kill)self.ui.get_log.clicked.connect(self.log)self.ui.disable.clicked.connect(self.wifi_disable)self.ui.enable.clicked.connect(self.wifi_enable)self.ui.bk.clicked.connect(self.bluetooth_enable)self.ui.bg.clicked.connect(self.bluetooth_disable)self.ui.huqie.clicked.connect(self.hq)self.ui.wifi_adb.clicked.connect(self.wifi_adb_)self.ui.write_in.clicked.connect(self.text_write_in)self.ui.get_device.clicked.connect(self.devices)self.ui.suoyou.clicked.connect(self.suoyou_log)self.ui.dell.clicked.connect(self.del_log)self.ui.time.clicked.connect(self.yl)self.ui.jt.clicked.connect(self.jietu)self.timer1 = QTimer()self.timer1.setInterval(5000)  # 设置定时器1的触发间隔为3秒self.timer1.timeout.connect(self.devices)self.timer1.start()self.devices()self.timer2 = QTimer()self.timer2.setInterval(1000)  # 设置定时器2的触发间隔为1秒self.timer2.timeout.connect(self.update_button_text)self.timer2.start()self.update_button_text()  # 初始self.ui.ttt.setPlainText(txt)def update_button_text(self):current_datetime = QDateTime.currentDateTime()time_text = current_datetime.toString('yyyy-MM-dd dddd hh:mm:ss')self.ui.time.setText(time_text)def check_adb_connection(self, d):'''控制按钮是否都可用'''buttons = [self.ui.qd_app,self.ui.zx,self.ui.get_log,self.ui.disable,self.ui.enable,self.ui.bk,self.ui.bg,self.ui.huqie,self.ui.wifi_adb,self.ui.write_in,self.ui.get_device,self.ui.suoyou,self.ui.dell,self.ui.time,self.ui.jt]for button in buttons:button.setEnabled(d)def qd(self):'''app根据包名启动'''pack_name = self.ui.pack_name.text()if PackNameOperate.pack_name_start(pack_name) == 1:QMessageBox.critical(self.ui, '包名错误', '请检查包名是否输入正确!')else:QMessageBox.information(self.ui, '操作成功', f'{pack_name}启动完成')# QMessageBox.close()def kill(self):'''app杀后台,清除缓存,启动等组合操作'''xz = self.ui.kill_apps.currentText()index = self.kill_list.index(xz)if PackNameOperate.kill_app(index) == 0:QMessageBox.information(self.ui, '操作成功', f'"{xz}"执行完成')elif '包名' in PackNameOperate.kill_app(index):QMessageBox.information(self.ui, '操作成功', PackNameOperate.kill_app(index))else:QMessageBox.critical(self.ui, '错误', '设备未连接或者未启动adb模式')def log(self):'''抓日志'''Log.test()def wifi_enable(self):subprocess.getoutput('adb shell svc wifi enable')QMessageBox.information(self.ui, '操作成功', f'wifi已打开')def wifi_disable(self):subprocess.getoutput('adb shell svc wifi disable')QMessageBox.information(self.ui, '操作成功', f'wifi已关闭')def bluetooth_enable(self):subprocess.getoutput('adb shell svc bluetooth enable')QMessageBox.information(self.ui, '操作成功', f'帅哥蓝牙已打开')def bluetooth_disable(self):subprocess.getoutput('adb shell svc bluetooth disable')QMessageBox.information(self.ui, '操作成功', f'蓝牙已关闭')def wifi_adb_(self):ml = wifi_adb_connect()if ml[0]==0:QMessageBox.information(self.ui, '操作成功', f'已经连接wifiadb成功,命令为:{ml[1]},请3s内拔掉adb线')else:QMessageBox.information(self.ui, '操作失败', f'开启失败,命令为:{ml[1]},未获取到ip信息,检查是否处于同一个wifi')def text_write_in(self):text = self.ui.text.text()input_text(text)# subprocess.run(['adb', 'shell', 'input', 'text', text])QMessageBox.information(self.ui, '操作成功', '写入完成')def jietu(self):capture_screenshot()QMessageBox.information(self.ui, '操作成功', '截图成功')def devices(self):d = dev.dev_id()'''获取当前连接的设备id'''if d[0] == 0:devices_info = d[1]self.check_adb_connection(True)elif d[0] == 00:devices_info = d[1]self.check_adb_connection(True)else:devices_info = d[1]self.check_adb_connection(False)self.ui.device.setText(str(devices_info))def suoyou_log(self):log.save_logcat()QMessageBox.information(self.ui, '操作成功', '日志导出完成')def del_log(self):log.clear_logcat()QMessageBox.information(self.ui, '操作成功', '日志清除完成')def yl(self):QMessageBox.information(self.ui, '嘿嘿', '要天天开心呀')def hq(self):'''2个应用互切'''pack_1 = self.ui.pack1.text()pack_2 = self.ui.pack2.text()print(pack_1, pack_2)if pack_1 == '':QMessageBox.information(self.ui, '操作失败', '包名1填下,谢谢')elif pack_2 == '':QMessageBox.information(self.ui, '操作失败', '包名2填下,谢谢')elif PackNameOperate.huqie(pack_1, pack_2) == 11:QMessageBox.information(self.ui, '操作失败', f'找不到{pack_1}这个包')elif PackNameOperate.huqie(pack_1, pack_2) == 12:QMessageBox.information(self.ui, '操作失败', f'找不到{pack_2}这个包')elif PackNameOperate.huqie(pack_1, pack_2) == 1:QMessageBox.information(self.ui, '操作失败', '当前运行的应用不是输入自定义的2个互切应用')elif pack_1 == pack_2:QMessageBox.information(self.ui, '操作成功', '一个包写2遍没太大必要啊')else:QMessageBox.information(self.ui, '操作成功', '切换完成')app = QApplication([])
stats = Stats()
stats.ui.show()
app.exec_()

main.py 主要是逻辑代码

import os
import re
import shutil
import subprocess
import time
from time import sleep
import datetimeclass PackNameOperate():@classmethoddef pack_name_start(cls, pack_name):'''根据包名启动app'''output = subprocess.getoutput(f'adb shell monkey -p {pack_name} --throttle 1 -s 2 -v -v -v 1')if 'No activities found to run, monkey aborted' in output:print('车机不存在该包名,请检查包名是否输入正确')return 1else:return 0@classmethoddef kill_app(cls, l):''':param l: 0不输入是获取当前运行的包名,1是杀掉当前启动的app,2是清除当前app缓存信息,3是清楚缓存并且杀掉app,4是根据上一个前三个操作的包名启动app:return:'''output = subprocess.getoutput('adb shell dumpsys window | findstr mCurrentFocus')if not output == '':try:pack_name = 'com.' + re.findall(r'com.(.*?)/com', output)[0]except:pack_name = 'com.' + re.findall(r'com.(.*?)/io', output)[0]if l == 0:print(f'当前运行的包名是{pack_name}')return f'当前运行的包名是{pack_name}'if l == 1:subprocess.getoutput(f'adb shell am force-stop {pack_name}')print(f'包名为{pack_name}的app已经杀掉')elif l == 2:subprocess.getoutput(f'adb shell pm clear {pack_name}')print(f'包名为{pack_name}的app缓存清楚成功')elif l == 3:subprocess.getoutput(f'adb shell pm clear {pack_name}')subprocess.getoutput(f'adb shell am force-stop {pack_name}')print(f'包名为{pack_name}的app清楚缓存并且杀掉成功')elif l == 4:subprocess.getoutput(f'adb shell pm clear {pack_name}')subprocess.getoutput(f'adb shell am force-stop {pack_name}')cls.pack_name_start(pack_name)print(f'包名为{pack_name}的app清楚缓存并且杀掉成功')print(f'{pack_name}重新启动完成')return 0print('设备未连接或者未启动adb模式')return 1@classmethoddef get_pack_name(cls):output = subprocess.getoutput('adb shell dumpsys window | findstr mCurrentFocus')try:pack_name = 'com.' + re.findall(r'com.(.*?)/com', output)[0]except:pack_name = 'com.' + re.findall(r'com.(.*?)/io', output)[0]# print(f'当前运行的包名是{pack_name}')return pack_name@classmethoddef huqie(cls, pack1, pack2):a = cls.get_pack_name()print(f'当前在运行的包名{a}')if a == pack1:if cls.pack_name_start(pack2) == 1:# 说明包名不对return 12elif a == pack2:if cls.pack_name_start(pack1) == 1:return 11else:print('当前运行的应用不输入自定义的2个互切应用')return 1class Log():@classmethoddef test(cls):for i in range(4):sleep(0.3)print(f'控制台打印{i}')# @classmethod# def move_file(cls, besave_dir=ys__log_path, fm='zip'):#     """#     将文件夹压缩成指定格式的压缩包#     :param besave_dir: 压缩文件夹的目录 如 ---r"D:\log_dir"#     :param format: 压缩的格式:"zip", "tar", "gztar","bztar", "xztar"#     :return:#     """#     if os.path.exists(besave_dir):#         zip_name = shutil.make_archive(besave_dir, f'{fm}', besave_dir)#         print(zip_name)  # 返回文件的最终路径## @classmethod# def del_dir(cls, dir_path=pc_log_path):#     '''删除目录下所有文件'''#     for filename in os.listdir(dir_path):#         file_path = os.path.join(dir_path, filename)#         if os.path.isfile(file_path) or os.path.islink(file_path):#             os.unlink(file_path)#         elif os.path.isdir(file_path):#             shutil.rmtree(file_path)## @classmethod# def log(cls):#     cls.del_dir()#     subprocess.getoutput(f'adb pull {cj_log_path} {pc_log_path}')#     cls.move_file()# Log.test()def wifi_adb_connect():def get_car_wifi_ip():process = subprocess.run(['adb', 'shell', 'ifconfig', 'wlan0'], capture_output=True, text=True)output = process.stdout.strip()ip_line = [line for line in output.split('\n') if 'inet addr' in line]if len(ip_line) > 0:ip = ip_line[0].split()[1].split(':')[1]subprocess.run(['adb', 'tcpip', '6666'])print(f'端口号6666')return ipelse:return None# 使用示例:获取车机的WiFi IPcar_wifi_ip = get_car_wifi_ip()print(car_wifi_ip)# ip = car_wifi_ipsubprocess.run(['adb', 'disconnect'])subprocess.run(['adb', 'connect', f'{car_wifi_ip}:6666'])# 获取连接状态输出result = subprocess.run(['adb', 'devices'], capture_output=True, text=True)output = result.stdout.strip().encode('utf-8').decode('gbk')print(output)if '不知道这样的主机' in output:return 1,outputelse:return 0, f'adb connect {car_wifi_ip}:6666'class Devices:def check_adb_connection(self):try:# 检查连接状态command = 'adb devices'output = subprocess.check_output(command.split()).decode().strip()# 检查输出结果中是否包含设备列表if 'List of devices attached' in output:# 提取设备列表devices = output.split('\n')[1:]# 检查设备列表是否为空if len(devices) > 0:# 提取所有设备的设备IDdevice_ids = [device.split('\t')[0] for device in devices]return device_idselse:return Noneelse:return Noneexcept subprocess.CalledProcessError:return Nonedef dev_id(self):device_ids = self.check_adb_connection()# if 'offline' in subprocess.getoutput(f'adb shell'):#     subprocess.run(['adb', 'kill-server'])#     time.sleep(1)#     subprocess.run(['adb', 'start-server'])#     print('检测到设备离线,重启adb服务解决中')if device_ids is not None:if len(device_ids) == 1:# print(f"设备ID: {device_ids[0]}")return 0, f"设备ID: {device_ids[0]}"elif len(device_ids) > 1 :# 清除所有连接subprocess.run(['adb', 'disconnect'])# print(f'干掉了{device_ids[1:]}等设备')return 00, f"设备ID: {device_ids[0]},干掉了{device_ids[1:]}等设备"else:return 1else:# print("ADB未成功连接到任何设备")return 1, "ADB未成功连接到任何设备,按钮全部禁用"def input_text(text):# 转义特殊字符text = text.replace('\\', '\\\\').replace('"', '\\"')# 执行 adb shell input text 命令subprocess.run(['adb', 'shell', 'input', 'text', f'"{text}"'])class LogcatManager:def __init__(self, save_directory):self.save_directory = save_directorydef _get_device_info(self):# 获取设备的Android版本android_version_cmd = ['adb', 'shell', 'getprop', 'ro.build.version.release']android_version_process = subprocess.Popen(android_version_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True)android_version_output, _ = android_version_process.communicate()android_version = android_version_output.strip()# 获取屏幕分辨率screen_resolution_cmd = ['adb', 'shell', 'wm', 'size']screen_resolution_process = subprocess.Popen(screen_resolution_cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE, universal_newlines=True)screen_resolution_output, _ = screen_resolution_process.communicate()screen_resolution = screen_resolution_output.strip().split()[2]# 获取系统版本信息system_info_cmd = ['adb', 'shell', 'getprop', 'ro.build.description']system_info_process = subprocess.Popen(system_info_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True)system_info_output, _ = system_info_process.communicate()system_info = system_info_output.strip()return android_version, screen_resolution, system_infodef _create_directory(self, directory):if not os.path.exists(directory):os.makedirs(directory)def _get_current_time(self):return datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')def _build_file_name(self, android_version, screen_resolution, system_info):current_time = self._get_current_time()file_name = f'{current_time}.Android{android_version}.{screen_resolution}.{system_info}.logcat.txt'return file_namedef _build_file_path(self, file_name):file_path = os.path.join(self.save_directory, file_name)return file_pathdef _export_logcat(self, file_path):# 执行 adb logcat -d 命令,导出日志到文件cmd = ['adb', 'logcat', '-d']process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)# 检查目录是否存在,如果不存在则创建目录self._create_directory(self.save_directory)try:with open(file_path, 'wb') as file:for line in process.stdout:file.write(line)print(f'Logcat已成功导出到文件:{file_path}')except Exception as e:print(f'保存Logcat文件时发生错误:{e}')def save_logcat(self):# 获取设备信息android_version, screen_resolution, system_info = self._get_device_info()# 构建文件名file_name = self._build_file_name(android_version, screen_resolution, system_info)# 构建完整的文件路径file_path = self._build_file_path(file_name)# 导出Logcat并保存到文件self._export_logcat(file_path)# return 'Logcat已成功导出成功'## def save_realtime_logcat(self):#     # 获取设备信息#     android_version, screen_resolution, system_info = self._get_device_info()##     # 构建文件名#     file_name = self._build_file_name(android_version, screen_resolution, system_info)##     # 构建完整的文件路径#     file_path = self._build_file_path(file_name)#     # 执行 adb logcat 命令,实时保存日志到文件#     cmd = ['adb', 'logcat']#     print(f'实时保存的Logcat已成功保存到文件:{file_path}')#     with open(file_path, 'w') as file:#         process = subprocess.Popen(cmd, stdout=file, stderr=subprocess.PIPE, universal_newlines=True)#         try:#             process.wait()#         except KeyboardInterrupt:#             process.terminate()def clear_logcat(self):# 执行 adb shell logcat -c 命令,清除Logcat日志cmd = ['adb', 'shell', 'logcat', '-c']subprocess.run(cmd)print('Logcat日志已清除')# return 'Logcat日志已清除'
def capture_screenshot():from datetime import datetime# 获取当前时间并格式化为字符串current_time = datetime.now().strftime("%Y-%m-%d-%H_%M_%S")# 创建目录directory = "D:/jb/tu/"os.makedirs(directory, exist_ok=True)# 执行ADB命令进行截图subprocess.run(["adb", "shell", "screencap", "-p", "/sdcard/screenshot.png"])# 将截图文件复制到本地目录local_path = os.path.join(directory, f"{current_time}.png")subprocess.run(["adb", "pull", "/sdcard/screenshot.png", local_path])return 0

gui.spec 是打包使用的

# -*- mode: python ; coding: utf-8 -*-block_cipher = Nonea = Analysis(['gui.py'],pathex=[],binaries=[],datas=[('adb.ui','.')],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='shy',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=True,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,icon=['i.ico'],
)

adb.ui

是qt设计师生成的ui界面,设置属性配合代码操作

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>adb_shell</class><widget class="QWidget" name="adb_shell"><property name="geometry"><rect><x>0</x><y>0</y><width>768</width><height>564</height></rect></property><property name="windowTitle"><string>安卓测试操作</string></property><layout class="QVBoxLayout" name="verticalLayout_4"><item><widget class="QPushButton" name="time"><property name="text"><string>时间</string></property></widget></item><item><widget class="QTabWidget" name="tabWidget"><property name="currentIndex"><number>0</number></property><widget class="QWidget" name="widget"><property name="minimumSize"><size><width>0</width><height>18</height></size></property><attribute name="title"><string>常用操作</string></attribute><layout class="QVBoxLayout" name="verticalLayout_2"><item><widget class="QGroupBox" name="groupBox"><property name="title"><string>根据包名操作</string></property><layout class="QVBoxLayout" name="verticalLayout"><item><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QLineEdit" name="pack_name"><property name="placeholderText"><string>请输入app包名</string></property></widget></item><item><widget class="QPushButton" name="qd_app"><property name="text"><string>启动app</string></property></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_2"><item><widget class="QComboBox" name="kill_apps"/></item><item><widget class="QPushButton" name="zx"><property name="text"><string>执行</string></property></widget></item></layout></item><item><layout class="QHBoxLayout" name="horizontalLayout_3"><item><widget class="QLineEdit" name="pack1"><property name="placeholderText"><string>包名1</string></property></widget></item><item><widget class="QLineEdit" name="pack2"><property name="placeholderText"><string>包名2</string></property></widget></item><item><widget class="QPushButton" name="huqie"><property name="text"><string>应用切换</string></property></widget></item></layout></item><item><widget class="QGroupBox" name="groupBox_3"><property name="title"><string>系统控制</string></property><layout class="QVBoxLayout" name="verticalLayout_3"><item><layout class="QHBoxLayout" name="horizontalLayout_4"><item><widget class="QPushButton" name="wifi_adb"><property name="text"><string>开启wifiadb</string></property></widget></item><item><widget class="QPushButton" name="enable"><property name="text"><string>wifi打开</string></property></widget></item><item><widget class="QPushButton" name="disable"><property name="text"><string>wifi关闭</string></property></widget></item><item><widget class="QPushButton" name="bk"><property name="text"><string>蓝牙打开</string></property></widget></item><item><widget class="QPushButton" name="bg"><property name="text"><string>蓝牙关闭</string></property></widget></item></layout></item></layout></widget></item><item><widget class="QLineEdit" name="text"/></item><item><widget class="QPushButton" name="write_in"><property name="text"><string>开始写入文本(不支持中文)</string></property></widget></item><item><widget class="QLineEdit" name="device"><property name="text"><string/></property></widget></item><item><widget class="QPushButton" name="get_device"><property name="text"><string>查询当前连接的设备(5s自动查询一次)</string></property></widget></item></layout></widget></item></layout></widget><widget class="QWidget" name="tab_6"><attribute name="title"><string>日志操作和使用说明</string></attribute><layout class="QVBoxLayout" name="verticalLayout_6"><item><layout class="QVBoxLayout" name="verticalLayout_5"><item><layout class="QHBoxLayout" name="horizontalLayout_5"><item><widget class="QPushButton" name="jt"><property name="text"><string>截图</string></property></widget></item><item><widget class="QPushButton" name="dell"><property name="text"><string>清除logcat</string></property></widget></item><item><widget class="QPushButton" name="suoyou"><property name="text"><string>抓取从现在到之前的所有logcat</string></property></widget></item><item><widget class="QPushButton" name="get_log"><property name="text"><string>控制台打印测试</string></property><property name="iconSize"><size><width>10</width><height>10</height></size></property></widget></item></layout></item><item><widget class="QPlainTextEdit" name="ttt"><property name="readOnly"><bool>true</bool></property></widget></item></layout></item></layout></widget></widget></item></layout></widget><resources/><connections/>
</ui>

打包为exe

https://blog.csdn.net/aaaaaaaaanjjj/article/details/134157127

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

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

相关文章

第二十章总结

一.线程简介 二.创建线程 1.继承Thread类 Thread类中常用的两个构造方法如下&#xff1a; public Thread():创建一个新的线程对象。 public Thread(String threadName):创建一个名称为threadName的线程对象。 继承Thread类创建一个新的线程的语法如下&#xff1a; p…

Blender动画导入Three.js

你是否在把 Blender 动画导入你的 ThreeJS 游戏(或项目)中工作时遇到问题? 您的 .glb (glTF) 文件是否正在加载,但没有显示任何内容? 你的骨骼没有正确克隆吗? 如果是这样,请阅读我如何使用 SkeletonUtils.js 解决此问题 1、前提条件 你正在使用 Blender 3.1+(此版本…

centos无法进入系统之原因解决办法集合

前言 可爱的小伙伴们&#xff0c;由于精力有限&#xff0c;暂时整理了两类。如果没有你遇到的问题也没有关系&#xff0c;欢迎底下留言评论或私信&#xff0c;小编看到后第一时间帮助解决 一. Centos 7 LVM xfs文件系统修复 情况1&#xff1a; [sda] Assuming drive cache:…

flask web开发学习之初识flask(一)

一、概念 flask是一个使用python编写的轻量级web框架&#xff0c;作者为Armin Ronacher&#xff08;中文名&#xff1a;阿尔敏罗纳彻&#xff09;&#xff0c;它广泛被应用于web开发和API。flask提供了简洁而灵活地方式来构建web应用&#xff0c;它不会强加太多约束&#xff0…

大数据平台/大数据技术与原理-实验报告--部署全分布模式HBase集群和实战HBase

实验名称 部署全分布模式HBase集群和实战HBase 实验性质 &#xff08;必修、选修&#xff09; 必修 实验类型&#xff08;验证、设计、创新、综合&#xff09; 综合 实验课时 2 实验日期 2023.11.07-2023.11.10 实验仪器设备以及实验软硬件要求 专业实验室&#xff…

如何在Ubuntu的Linux系统中安装MySQL5.7数据库

前往MySQL数据库官网链接地址下载5.7数据库。 MySQL :: Download MySQL Community Server (Archived Versions)使用ssh的可视化工具将下载的mysql-5.7.40-linux-glibc2.12-x86_64.tar.gz文件上传到Linux服务器&#xff0c;并解压文件 tar -zxvf mysql-5.7.40-linux-glibc2.12-x…

vue+SpringBoot的图片上传

前端VUE的代码实现 直接粘贴过来element-UI的组件实现 <el-uploadclass"avatar-uploader"action"/uploadAvatar" //这个action的值是服务端的路径&#xff0c;其他不用改:show-file-list"false":on-success"handleAvatarSuccess"…

共享充电宝被取代,共享WIFI项目将成市场趋势!

在创业领域如果有这样一个项目&#xff0c;你会选择哪一个&#xff1f;前者投资十万风险大&#xff0c;后者投资几千风险小。同样需要扫街地推&#xff0c;但产生的利润是相同的。相信100%的人会选择后者。实际上这两个项目前者就是共享电宝&#xff0c;后者就是共享WiFi项目。…

SpringBoot整合Redis,redis连接池和RedisTemplate序列化

SpringBoot整合Redis 1、SpringBoot整合redis1.1 pom.xml1.2 application.yml1.3 配置类RedisConfig&#xff0c;实现RedisTemplate序列化1.4 代码测试 2、SpringBoot整合redis几个疑问&#xff1f;2.1、Redis 连接池讲解2.2、RedisTemplate和StringRedisTemplate 3、RedisTemp…

python -opencv 中值滤波 ,均值滤波,高斯滤波实战

python -opencv 中值滤波 &#xff0c;均值滤波&#xff0c;高斯滤波实战 cv2.blur-均值滤波 cv2.medianBlur-中值滤波 cv2.GaussianBlur-高斯滤波 直接看代码吧&#xff0c;代码很简单&#xff1a; import copy import math import matplotlib.pyplot as plt import matp…

Linux系统---环境变量+内核进程调度队列(选学)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;如: 我们在编写CI/…

Java制作“简易王者荣耀”小游戏

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 GameFrame 运行类 package com.sxt;import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; im…

如何使用Cloudreve将个人电脑打造为私有云盘并实现远程访问

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 云存储概念兴起后&#xff0c;现在市面上也已经有了很多公有云盘。但一段时间后…

uniapp实现多时间段设置

功能说明&#xff1a; 1 点击新增时间&#xff0c;出现一个默认时间段模板&#xff0c;不能提交 2 点击“新增时间文本”&#xff0c;弹出弹窗&#xff0c;选择时间&#xff0c;不允许开始时间和结束时间同时为00:00&#xff0c; <view class"item_cont"> …

如何理解2023vivo开发者大会,使用Rust语言编写蓝河操作系统(BlueOS)?

在2023年vivo开发者大会上&#xff0c;vivo宣布使用Rust语言编写其蓝河操作系统&#xff08;BlueOS&#xff09;。 什么是Rust语言&#xff1f; Rust 是一种开放源代码系统编程语言&#xff0c;可用于开发高效、安全的软件。 使用 Rust 可管理内存并控制其低级详细信息。 但你…

Web框架与Django简介

Web框架与Django简介 一、Web应用的组成 我们为了开发一款Web软件首先要了解什么才是Web应用软件呢&#xff1f; 对于传统的应用软件来说&#xff0c;基本都是部署单机使用&#xff0c;而Web应用软件就不一样&#xff0c;Web应用软件是基于B/S架构的&#xff0c;B和S都在不同…

Spring Boot 3.2.0 Tomcat虚拟线程初体验 (部分装配解析)

写在前面 spring boot 3 已经提供了对虚拟线程的支持。 虚拟线程和平台线程主要区别在于&#xff0c;虚拟线程在运行周期内不依赖操作系统线程&#xff1a;它们与硬件脱钩&#xff0c;因此被称为 “虚拟”。这种解耦是由 JVM 提供的抽象层赋予的。 虚拟线程的运行成本远低于平…

记录:Unity脚本的编写8.0

目录 需求分析设计GUI包含账号和密码输入栏&#xff0c;包括登录和注册按键添加背景音乐编写脚本控制音乐 退出按钮编写脚本 背景图片完整代码 一个小demo&#xff0c;登录和注册的实现&#xff08;包括GUI和数据库操控&#xff09; 需求分析 自行设计GUI&#xff0c;要求 1.包…

智能优化算法应用:基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.花授粉算法4.实验参数设定5.算法结果6.参考文献7.…

java游戏制作-王者荣耀游戏

一.准备工作 首先创建一个新的Java项目命名为“王者荣耀”&#xff0c;并在src下创建两个包分别命名为“com.sxt"、”com.stx.beast",在相应的包中创建所需的类。 创建一个名为“img”的文件夹来储存所需的图片素材。 二.代码呈现 package com.sxt; import javax.…