Python——桌面摄像头软件(附源码+打包)

目录

一、前言

二、桌面摄像头软件

2.1、下载项目

2.2、功能介绍

三、打包工具(nuitka)

 四、项目文件复制(我全部合到一个文件里面了)

五、结语


一、前言

看见b站的向军大叔用electron制作了一个桌面摄像头软件

但是,我不怎么熟悉前端,自己就用pyside6简单制作一个

二、桌面摄像头软件

2.1、下载项目

软件下载地址:(下载后,双击即可运行——60MB左右)

https://wwm.lanzout.com/ibIEL1q0xt8d
密码:eg34

工程文件下载地址:

camera-python.zip - 蓝奏云

启动项目:

# 下载包
pip install -r requirements.txt# 运行项目
python main.py

2.2、功能介绍

启动后,会自动打开默认摄像头

基础操作

左键长按:拖拽移动

滚轮上下滑动:放大和缩小摄像头画面

右键设置操作

选择边框颜色(rgb格式)

选择摄像头(自由切换)

窗口变形(正方形窗口和圆形窗口的切换)

隐藏

退出

系统托盘(可右键选择隐藏或出现,以及退出)

三、打包工具(nuitka)

 Python——Windows使用Nuitka2.0打包(保姆级教程)-CSDN博客

我的打包命令:

 

nuitka --mingw64 --show-progress --standalone --disable-console --enable-plugin=pyside6 --plugin-enable=numpy --onefile --remove-output --windows-icon-from-ico=logo.ico camera.py

 四、项目文件复制(我全部合到一个文件里面了)

# -*- coding: utf-8 -*-
# @Author : pan
import time
import cv2
import numpy as npfrom PySide6.QtCore import (Qt, QTimer, QPropertyAnimation, QEasingCurve,QParallelAnimationGroup, QThread, QMutex,Signal, Slot, QCoreApplication, QDate, QDateTime,QLocale, QMetaObject, QObject, QPoint, QRect,QSize, QTime, QUrl, QAbstractAnimation, QEvent)
from PySide6.QtGui import (QPixmap, QPainter, QColor, QFontMetrics, QPen,QWheelEvent, QCursor, QAction, QImage, QPainterPath,QBrush, QConicalGradient, QFont, QFontDatabase,QGradient, QIcon, QKeySequence, QLinearGradient,QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QWidget, QLabel, QMenu, QDialog,QVBoxLayout, QLineEdit, QPushButton, QMessageBox,QInputDialog, QFrame, QHBoxLayout, QLayout,QSizePolicy, QSpacerItem, QSystemTrayIcon)# 提示组件
class Toast(QWidget):def __init__(self,text: str,duration: int = 3000,parent: QWidget = None,):super().__init__(parent)self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)self.setAttribute(Qt.WA_TranslucentBackground, True)self.duration = durationlabel = QLabel(self)label.setText(text)label.setStyleSheet("""background-color: rgba(60, 179, 113, 0.8);color: white;font-size: 16px;padding: 12px;border-radius: 4px;""")label.setAlignment(Qt.AlignCenter)fm = QFontMetrics(label.font())width = fm.boundingRect(text).width() + 80# 高度与宽度label.setFixedWidth(width)label.setFixedHeight(40)self.setGeometry(*self.calculatePosition(label.sizeHint()))self.fadeIn()self.animationTimer = QTimer()self.animationTimer.timeout.connect(self.fadeOut)self.animationTimer.start(self.duration)def calculatePosition(self, sizeHint):if self.parent() is not None:# 如果存在父窗口,计算使Toast窗口相对于父窗口居中的位置x = self.parent().width() / 2 - sizeHint.width()/2y = 10else:# 如果没有父窗口,计算使Toast窗口相对于屏幕居中的位置desktopRect = QApplication.primaryScreen().availableGeometry()x = (desktopRect.width() - sizeHint.width()) // 2y = (desktopRect.height() - sizeHint.height()) // 2return x, y, sizeHint.width(), sizeHint.height()def fadeIn(self):# 创建并设置淡入动画fadeInAnimation = QPropertyAnimation(self, b"windowOpacity", self)fadeInAnimation.setStartValue(0)fadeInAnimation.setEndValue(1)fadeInAnimation.setDuration(500)fadeInAnimation.finished.connect(lambda: print('加载成功'))# 启动淡入动画fadeInAnimation.start()print('in')# 淡出动画def fadeOut(self):print('out')# 停止计时器self.animationTimer.stop()# 断开计时器的超时信号与当前方法的连接self.animationTimer.timeout.disconnect(self.fadeOut)# 创建并设置并行动画组self.parallelAnimation = QParallelAnimationGroup()# 创建并设置不透明度动画self.opacityAnimation = QPropertyAnimation(self, b"windowOpacity")self.opacityAnimation.setStartValue(1.0)self.opacityAnimation.setEndValue(0.0)self.opacityAnimation.setDuration(500)# 创建并设置位置动画self.yAnimation = QPropertyAnimation(self, b"geometry")targetY = self.y() - 10self.yAnimation.setStartValue(self.geometry())self.yAnimation.setEndValue(self.geometry().translated(0, targetY))self.yAnimation.setDuration(500)self.yAnimation.setEasingCurve(QEasingCurve.OutCubic)# 将动画添加到并行动画组中self.parallelAnimation.addAnimation(self.opacityAnimation)self.parallelAnimation.addAnimation(self.yAnimation)# 连接并行动画组的完成信号与关闭窗口的槽self.parallelAnimation.finished.connect(self.close)# 启动动画组self.parallelAnimation.start(QAbstractAnimation.DeleteWhenStopped)def paintEvent(self, event):painter = QPainter(self)painter.fillRect(self.rect(), QColor(0, 0, 0, 0))def mousePressEvent(self, event):pass# 弹窗 输入框
class Ui_InputColor(QWidget):textEntered = Signal(str)  # 定义一个带有字符串参数的信号def __init__(self):super().__init__()self.drag_position = Nonedef setupUi(self, Form):Form.setObjectName("Form")  # 直接设置对象名称Form.resize(200, 70)# 设置背景颜色和透明度Form.setWindowFlags(Qt.FramelessWindowHint)  # 设置无边框窗口Form.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口透明self.bg_gray = QFrame(Form)self.bg_gray.setObjectName(u"bg_gray")self.bg_gray.setGeometry(QRect(0, 0, 200, 65))self.bg_gray.setStyleSheet(u".QFrame{\n"
"	background-color: rgb(234,236,243);\n"
"	border-radius:5px;\n"
"}")self.bg_gray.setFrameShape(QFrame.StyledPanel)self.bg_gray.setFrameShadow(QFrame.Raised)self.verticalLayout_3 = QVBoxLayout(self.bg_gray)self.verticalLayout_3.setSpacing(0)self.verticalLayout_3.setObjectName(u"verticalLayout_3")self.verticalLayout_3.setContentsMargins(10, 11, 4, 11)self.verticalLayout_2 = QVBoxLayout()# 设置右侧边距为5pxself.verticalLayout_2.setContentsMargins(0, 0, 7, 0)self.verticalLayout_2.setObjectName(u"verticalLayout_2")self.window_top = QHBoxLayout()self.window_top.setSpacing(10)self.window_top.setObjectName(u"window_top")self.window_top.setSizeConstraint(QLayout.SetFixedSize)self.window_top.setContentsMargins(0, 0, 0, 0)self.text_title = QLabel(self.bg_gray)self.text_title.setObjectName(u"text_title")self.text_title.setStyleSheet(u"    font-size: 9pt;\n"
"    font-family: \"\u5fae\u8f6f\u96c5\u9ed1\";\n"
"    color: #333;\n"
"font-weight: bold;")self.window_top.addWidget(self.text_title)self.h_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)self.window_top.addItem(self.h_spacer)self.btn_min = QPushButton(self.bg_gray)self.btn_min.setObjectName(u"btn_min")sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(0)sizePolicy.setVerticalStretch(0)sizePolicy.setHeightForWidth(self.btn_min.sizePolicy().hasHeightForWidth())self.btn_min.setSizePolicy(sizePolicy)self.btn_min.setMaximumSize(QSize(10, 10))self.btn_min.setStyleSheet(u"QPushButton {\n"
"    background-color: #07BB2C;\n"
"    border: 2px solid #07BB2C;\n"
"    color: #3498db;\n"
"    padding: 1px;\n"
"    border-radius: 5px;\n"
"}\n"
" \n"
"QPushButton:hover {\n"
"    background-color: #09ED3A;\n"
"    color: #ffffff;\n"
"}")self.window_top.addWidget(self.btn_min)self.btn_max = QPushButton(self.bg_gray)self.btn_max.setObjectName(u"btn_max")self.btn_max.setMaximumSize(QSize(10, 10))self.btn_max.setStyleSheet(u"QPushButton {\n"
"    background-color: #FFB206;\n"
"    border: 2px solid #FFB206;\n"
"    color: #3498db;\n"
"    padding: 1px;\n"
"    border-radius: 5px;\n"
"}\n"
" \n"
"QPushButton:hover {\n"
"    background-color: #FFC033;\n"
"    color: #ffffff;\n"
"}")self.window_top.addWidget(self.btn_max)self.btn_stop = QPushButton(self.bg_gray)self.btn_stop.setObjectName(u"btn_stop")self.btn_stop.clicked.connect(self.hide)  # 关联关闭窗口事件self.btn_stop.setMaximumSize(QSize(10, 10))self.btn_stop.setStyleSheet(u"\n"
"\n"
"QPushButton {\n"
"    background-color: #EE514A;\n"
"    border: 2px solid #EE514A;\n"
"    color: #3498db;\n"
"    padding: 1px;\n"
"    border-radius: 5;\n"
"}\n"
" \n"
"QPushButton:hover {\n"
"    background-color: #F1756F;\n"
"    color: #ffffff;\n"
"}")self.window_top.addWidget(self.btn_stop)self.verticalLayout_2.addLayout(self.window_top)self.horizontalLayout = QHBoxLayout()self.horizontalLayout.setObjectName(u"horizontalLayout")self.lineEdit = QLineEdit(self.bg_gray)self.lineEdit.setObjectName(u"lineEdit")self.horizontalLayout.addWidget(self.lineEdit)self.b_submit = QPushButton(self.bg_gray)self.b_submit.clicked.connect(self.emitSignal)  # 点击按钮时连接到发射信号的方法self.b_submit.setObjectName(u"b_submit")self.b_submit.setMinimumSize(QSize(0, 0))self.b_submit.setStyleSheet(u"            QPushButton {\n"
"                border-style: solid;\n"
"                border-width: 2px;\n"
"                border-radius: 15px;\n"
"                border-color: rgb(88, 180, 107);\n"
"                font-size: 7pt;\n"
"                font-weight: bold;\n"
"                padding: 2px;\n"
"                background-color: rgb(88, 180, 107);\n"
"                color: rgb(255, 255, 255);\n"
"            }\n"
"            QPushButton:hover {\n"
"                border-color: rgb(100, 100, 100);\n"
"                background-color: rgb(183, 255, 189);\n"
"				color: rgb(88, 180, 107);\n"
"            }\n"
"            QPushButton:pressed {\n"
"                border-color: rgb(42, 42, 42);\n"
"                background-color: rgb(160, 255, 163);\n"
"				color: rgb(88, 180, 107);\n"
"            }")self.horizontalLayout.addWidget(self.b_submit)self.verticalLayout_2.addLayout(self.horizontalLayout)self.verticalLayout_3.addLayout(self.verticalLayout_2)self.retranslateUi(Form)QMetaObject.connectSlotsByName(Form)# setupUi@Slot()def emitSignal(self):text = self.lineEdit.text()self.textEntered.emit(text)  # 发射信号,并传递lineEdit中的文本def retranslateUi(self, Form):Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))self.text_title.setText(QCoreApplication.translate("Form", u"\u8bf7\u8f93\u5165\u8272\u53f7", None))self.btn_min.setText("")self.btn_max.setText("")self.btn_stop.setText("")self.lineEdit.setPlaceholderText(QCoreApplication.translate("Form", u"255,255,255", None))self.b_submit.setText(QCoreApplication.translate("Form", u"\u786e\u8ba4", None))# retranslateUidef mousePressEvent(self, event):if event.button() == Qt.LeftButton:self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()event.accept()def mouseMoveEvent(self, event):if event.buttons() == Qt.LeftButton and self.drag_position:self.move(event.globalPosition().toPoint() - self.drag_position)event.accept()def mouseReleaseEvent(self, event):if event.button() == Qt.LeftButton:self.drag_position = Noneevent.accept()# 摄像头检测类
class Camera:def __init__(self, cam_preset_num=5):self.cam_preset_num = cam_preset_numdef get_cam_num(self):cnt = 0devices = []for device in range(0, self.cam_preset_num):stream = cv2.VideoCapture(device, cv2.CAP_DSHOW)grabbed = stream.grab()stream.release()if not grabbed:continueelse:cnt = cnt + 1devices.append(device)return cnt, devices# 摄像头线程
class CameraThread(QThread):change_pixmap_signal = Signal(np.ndarray)def __init__(self, device_id=0):super().__init__()self.device_id = device_idself.is_paused = Falseself.mutex = QMutex()self.exiting = Falseself.cap = Nonedef run(self):self.cap = cv2.VideoCapture(self.device_id)while not self.exiting:self.mutex.lock()if not self.is_paused:ret, frame = self.cap.read()if ret:self.change_pixmap_signal.emit(frame)else:breakself.mutex.unlock()self.cap.release()self.cap = Nonedef set_device_id(self, device_id):self.device_id = device_iddef pause(self):self.mutex.lock()self.is_paused = Trueself.mutex.unlock()def resume(self):self.mutex.lock()self.is_paused = Falseself.mutex.unlock()def stop(self):self.exiting = Trueself.wait()def set_device_id(self, device_id):self.device_id = device_iddef stop(self):self.exiting = True# 主窗口
class MyWindow(QWidget):def __init__(self,text: str,parent: QWidget = None,):super().__init__(parent)# 设置窗口属性self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)self.setAttribute(Qt.WA_TranslucentBackground, True)# 窗口大小self.size = 200self.color = "255,255,255"self.window_shape = 0  # 0是圆# 子线程self.camera_thread = CameraThread()self.camera_thread.change_pixmap_signal.connect(self.image_data_slot)self.camera_thread.start()self.select_camera = Falseself.input_color_window = None# 创建标签并设置样式self.label = QLabel(self)self.label.setText(text)self.reset_style()  # 样式刷新self.label.setAlignment(Qt.AlignCenter)# 设置标签尺寸self.label.setAlignment(Qt.AlignCenter)self.label.setFixedSize(self.size, self.size)  # 设置标签的宽度和高度# 设置窗口位置self.setGeometry(*self.calculatePosition(self.label.sizeHint()))self.fadeIn()def fadeIn(self):# 创建并设置淡入动画fadeInAnimation = QPropertyAnimation(self, b"windowOpacity", self)fadeInAnimation.setStartValue(0)fadeInAnimation.setEndValue(1)fadeInAnimation.setDuration(500)fadeInAnimation.finished.connect(lambda: print('窗口 加载成功'))# 启动淡入动画fadeInAnimation.start()# 出现在屏幕居中的位置def calculatePosition(self, sizeHint):desktopRect = QApplication.primaryScreen().availableGeometry()x = (desktopRect.width() - sizeHint.width()) // 2y = (desktopRect.height() - sizeHint.height()) // 2return x, y, sizeHint.width(), sizeHint.height()def paintEvent(self, event):painter = QPainter(self)painter.fillRect(self.rect(), QColor(0, 0, 0, 0))def image_data_slot(self, image_data):if self.select_camera is True:self.label.clear()self.label.setText('请重新选择摄像头')returnself.image = cv2.cvtColor(image_data, cv2.COLOR_BGR2RGB)height, width, channel = self.image.shapebytesPerLine = 3 * widthimage = QImage(self.image.data, width, height, bytesPerLine, QImage.Format_RGB888)# 将图片先裁剪为正方形width = image.width()height = image.height()size = min(width, height)square_image = image.copy((width - size) // 2, (height - size) // 2, size, size)# 计算缩放比例new_size = self.size - 10label_size = self.label.sizeHint()scaled_image = square_image.scaled(new_size, new_size, Qt.KeepAspectRatio)# 将 QImage 转换为 QPixmappixmap = QPixmap.fromImage(scaled_image)# 创建一个圆形路径path = QPainterPath()path.addEllipse(0, 0, new_size, new_size)# 创建一个与 scaled_image 大小相同的的 QPixmapresult_pixmap = QPixmap(new_size, new_size)result_pixmap.fill(Qt.transparent)# 在 result_pixmap 上绘制圆形图像painter = QPainter(result_pixmap)if self.window_shape == 0:painter.setClipPath(path)  # 设置裁剪路径painter.setRenderHint(QPainter.Antialiasing)  # 设置抗锯齿painter.drawPixmap(0, 0, pixmap)  # 绘制原始图像painter.end()# 在 label 上显示圆形图像self.label.setPixmap(result_pixmap)def reset_style(self, flag=1):try:if flag == 0:r = 0else:r = self.size / 2self.label.setStyleSheet(f"""font-family: Arial, sans-serif; /* 设置字体 */font-size: 12pt; /* 设置字体大小 */background-color: rgb({self.color}); /* 设置背景颜色为红色 */padding: 0px; border-radius: {r}; /* 设置圆角大小为宽度的一半 */""")except Exception as e:print(e)def mousePressEvent(self, event):if event.button() == Qt.LeftButton:self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()event.accept()# 右键 打开菜单if event.button() == Qt.RightButton:menu = QMenu(self)set_color_action = menu.addAction("设置边框色")set_camera_action = menu.addAction("选择摄像头")set_camera_shape = menu.addAction('圆形窗口') if self.window_shape == 1 else menu.addAction('正方形窗口')set_hide_action = menu.addAction("隐藏")set_quit_action = menu.addAction("退出")# 修改 exec_ 弃用警告action = menu.exec(self.mapToGlobal(event.position().toPoint()))if action == set_color_action:# 打开窗口 Ui_InputColorself.open_input_color_window()# 获取目前所有摄像头的设备号,然后把设备号弄成一个菜单,让用户选择if action == set_camera_action:self.select_camera = True# 如果有摄像头在运行if self.camera_thread.cap is not None:# 这里给我绘制一个标签,等待2s再消失self.toast = Toast("正在关闭摄像头中", 1000, self)self.toast.show()time.sleep(1)self.camera_thread.stop()  # 停止摄像头播放return# 检测摄像头可用设备,把设备号弄成一个菜单,让用户选择# 获取本地摄像头数量_, cams = Camera().get_cam_num()popMenu = QMenu()popMenu.setFixedWidth(110)popMenu.setStyleSheet('''QMenu {font-size: 9px;font-family: "Microsoft YaHei UI";font-weight: light;color:white;padding-left: 5px;padding-right: 5px;padding-top: 4px;padding-bottom: 4px;border-style: solid;border-width: 0px;border-color: rgba(255, 212, 255, 255);border-radius: 3px;background-color: rgba(16,155,226,50);}''')for cam in cams:action = QAction(f'{cam} 号摄像头')popMenu.addAction(action)pos = QCursor.pos()action = popMenu.exec(pos)# 设置摄像头来源if action:str_temp = ''selected_stream_source = str_temp.join(filter(str.isdigit, action.text()))  # 获取摄像头号,去除非数字字符self.toast = Toast(f"摄像头设备是:{selected_stream_source}", 1000, self)self.toast.show()self.select_camera = Falseself.camera_thread = CameraThread()self.camera_thread.device_id = int(selected_stream_source)self.camera_thread.change_pixmap_signal.connect(self.image_data_slot)self.camera_thread.start()# 切换窗口if action == set_camera_shape:#if self.window_shape == 1:self.window_shape = 0 # 切换为圆形self.reset_style()  # 切换为圆形else:self.window_shape = 1self.reset_style(flag=0)  # 背景 变成正方形# 隐藏if action == set_hide_action:self.hide()# 退出if action == set_quit_action:self.close()# 颜色设置def colorEntered(self, text):print(1)# TODO 数据处理self.color = textself.reset_style()self.input_color_window.hide()#  打开窗口 Ui_InputColordef open_input_color_window(self):if self.input_color_window is None:  # 只有当窗口对象尚未创建时才创建它self.input_color_window = Ui_InputColor()self.input_color_window.setupUi(self.input_color_window)self.input_color_window.setWindowFlag(Qt.FramelessWindowHint)  # 设置窗口标志:隐藏窗口边框self.input_color_window.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)  # 设置窗口标志位self.input_color_window.textEntered.connect(self.colorEntered)  # 连接子窗口的信号和父窗口的槽# 窗口显示在父窗口的中心self.input_color_window.move(self.x() + (self.width() - self.input_color_window.width()) / 2,self.y() + (self.height() - self.input_color_window.height()) / 2)self.input_color_window.show()def mouseMoveEvent(self, event):# 左键 移动创建if event.buttons() == Qt.LeftButton:self.move(event.globalPosition().toPoint() - self.drag_position)event.accept()def mouseReleaseEvent(self, event):self.drag_position = None# 窗口大小变换def row_event(self, up=0, down=0):self.size = self.size + upself.size = self.size - downif self.window_shape == 1:self.reset_style(flag=0)  # 背景 变成正方形else:self.reset_style()  # 切换为圆形self.label.setFixedSize(self.size, self.size)  # 设置标签的宽度和高度self.setFixedSize(self.size, self.size)def event(self, event):if event.type() == QWheelEvent.Wheel:# 阻止默认的滚动行为event.ignore()# 获取滚动方向和距离delta = event.angleDelta().y() / 120# 根据滚动方向和距离执行相应操作if delta < 0:# 向下滚动(触发两次 因为背景上有bugself.row_event(down=1)self.row_event(down=1)else:# 向上滚动(触发两次 因为背景上有bugself.row_event(up=1)self.row_event(up=1)return Truereturn super().event(event)if __name__ == "__main__":app = QApplication([])# 创建系统托盘图标tray_icon = QSystemTrayIcon(QIcon("logo.jpg"), parent=app)tray_icon.setToolTip("Camera By Pan")# 创建并设置托盘图标的右键菜单menu = QMenu()show_action = menu.addAction("出现")     # 让window窗口出现hide_action = menu.addAction("隐藏")     # 让window窗口隐藏exit_action = menu.addAction("退出")tray_icon.setContextMenu(menu)# 显示托盘图标tray_icon.show()window = MyWindow("Camera Software By Pan")# 使窗口不在任务栏出现window.setWindowFlags(window.windowFlags() | Qt.Tool)  # 或者使用 Qt.SubWindow,根据你的需求和测试结果选择# 注意:# 使用Qt.Tool标志会使得窗口不在任务栏显示,这对于某些辅助工具或临时窗口是有用的。# 然而,这种改变也可能影响窗口的关闭行为和资源管理,尤其是在与系统托盘图标交互的上下文中。# 这导致我在关闭子窗口的时候,会导致程序崩溃!!!# 这导致我在关闭子窗口的时候,会导致程序崩溃!!!# 这导致我在关闭子窗口的时候,会导致程序崩溃!!!window.show()# 连接信号到槽函数exit_action.triggered.connect(app.quit)show_action.triggered.connect(window.show)hide_action.triggered.connect(window.hide)app.exec()


五、结语

  • 如果你有任何问题,欢迎在评论区留言,我会尽快回复。
  • 很久没有碰pyside6,而且学的很浅显,写了屎山代码
  • 目前只能保证功能实现,里面还有一些小bug
  • 但是不影响正常使用,就这样吧~

PS:其实我只是想自己拿来用用

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

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

相关文章

LabVIEW起重机工作参数远程监测系统

LabVIEW起重机工作参数远程监测系统 随着起重机技术的持续发展&#xff0c;对其工作参数的实时监控需求日益增加。设计了一个基于LabVIEW和TBox的起重机工作参数远程监测系统&#xff0c;能够实现起重机工作参数的实时采集、传输、解析和显示&#xff0c;有效提升起重机的性能…

自动化测试介绍、selenium用法(自动化测试框架+爬虫可用)

文章目录 一、自动化测试1、什么是自动化测试&#xff1f;2、手工测试 vs 自动化测试3、自动化测试常见误区4、自动化测试的优劣5、自动化测试分层6、什么项目适合自动化测试 二、Selenuim1、小例子2、用法3、页面操作获取输入内容模拟点击清空文本元素拖拽frame切换窗口切换/标…

【计算机网络】HTTPS 协议原理

https 一、HTTPS 是什么二、加密1. 加密概念2. 加密的原因3. 常见的加密方式&#xff08;1&#xff09;对称加密&#xff08;2&#xff09;非对称加密 三、数据摘要(数据指纹)四、HTTPS 的工作原理探究1. 只使用对称加密2. 只使用非对称加密3. 双方都使用非对称加密4. 非对称加…

信息系统项目管理师--项目立项管理

项⽬⽴项管理是对拟规划和实施的项⽬技术上的先进性、适⽤性&#xff0c;经济上的合理性、效益性&#xff0c;实施上的可能性、⻛险性以及社会价值的有效性、可持续性等进⾏全⾯科学的综合分析&#xff0c; 为项⽬决策提供客观依据的⼀种技术经济研究活动 项⽬建议与⽴项申请、…

代码随想录第46天|● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

文章目录 ● 121. 买卖股票的最佳时机思路一&#xff1a;贪心&#xff08;效率最快&#xff09;代码&#xff1a; 思路二&#xff1a;动态规划-dp数组代码&#xff1a; 思路三&#xff1a;动态规划 常数储存代码&#xff1a; ● 122.买卖股票的最佳时机II思路一&#xff1a;动态…

微信小程序(四十九)拦截器处理登入失败情况

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.拦截器判断处理失败与成功的情况 2.使用拦截器拒绝失败的情况&#xff0c;使网络请求后面的逻辑步骤不会执行 源码&#xff1a; index.wxml <button type"primary" bind:tap"onSubmit"…

Java面试题总结200道(二)

26、简述Spring中Bean的生命周期&#xff1f; 在原生的java环境中&#xff0c;一个新的对象的产生是我们用new()的方式产生出来的。在Spring的IOC容器中&#xff0c;将这一部分的工作帮我们完成了(Bean对象的管理)。既然是对象&#xff0c;就存在生命周期&#xff0c;也就是作用…

C#,无监督的K-Medoid聚类算法(K-Medoid Algorithm)与源代码

1 K-Medoid算法 K-Medoid&#xff08;也称为围绕Medoid的划分&#xff09;算法是由Kaufman和Rousseeuw于1987年提出的。中间点可以定义为簇中的点&#xff0c;其与簇中所有其他点的相似度最小。 K-medoids聚类是一种无监督的聚类算法&#xff0c;它对未标记数据中的对象进行聚…

【DIY】超重低音耳机放大器的制作

这不是一款普通的耳机放大器&#xff0c;我在它前级加入低音提升电路后&#xff0c;可以让你使用耳机听到高保真的音响效果&#xff0c;特别是重低音效果&#xff0c;逼真感很强以至于用它听的时间长了会让人感到头晕&#xff0c;使用它必须得注意&#xff1a;你的耳机要能经得…

文心一言 VS 讯飞星火 VS chatgpt (207)-- 算法导论15.4 4题

四、说明如何只使用表 c 中 2*min(m&#xff0c;n) 个表项及O(1)的额外空间来计算LCS的长度。然后说明如何只用 min(m&#xff0c;n) 个表项及O(1)的额外空间完成相同的工作。要写代码的时候&#xff0c;请用go语言。 文心一言&#xff1a; 在只使用 2 * min(m, n) 个表项和 …

MySQL高可用性攻略:快速搭建MySQL主从复制集群 !

MySQL高可用性攻略&#xff1a;快速搭建MySQL主从复制集群 &#xff01; MySQL基础知识&#xff1a;介绍MySQL数据库的基本概念和常用命令&#xff0c;如何创建数据库、表、用户和权限管理等。 MySQL安装教程&#xff1a;Centos7 安装MySQL5.7.29详细安装手册 MySQL数据类型&…

页面布局与样式设计:从基础到进阶

✨✨祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一. 基础布局技巧 1.使用CSS Grid布局设计网页布局 1.1 创建网格容器 1.2. 定义…