QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

news2024/12/26 3:43:24

QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

  • [1] QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样
    • 一、本自制虚拟键盘特点
    • 二、windows打开系统自带软键盘
    • 三、让键盘界面保持在最上方、不改变底层界面焦点
    • 四、长按按键重复输入键盘内容
    • 五、模拟键盘点击事件完成虚拟键盘输入
    • 六、键盘符号输入
    • 七、界面
    • 八、头文件代码
    • 九、源文件代码


[1] QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

原文链接:https://blog.csdn.net/qq_41632571/article/details/125808787

一、本自制虚拟键盘特点

1.键盘界面保持在所有界面最上方。

2.点击键盘按钮不会改变底层文本输入框焦点。

3.通过模拟键盘点击事件完成键盘输入文本信息。

4.包含各种键盘自带符号输入。

5.长按按键可以持续重复输入键盘内容。

6.支持win7、win10、Linux等各个系统。

7.界面好看。

总之跟真的虚拟键盘一样,不会有不爽的地方

二、windows打开系统自带软键盘

QDesktopServices::openUrl(QUrl("osk.exe", QUrl::TolerantMode));

传统打开系统自带虚拟键盘的方法如上,一行代码即可,但是系统自带的虚拟键盘不一定好用,有的按键太小,有的电脑上可能没有自带的软键盘,干脆直接写一个。

三、让键盘界面保持在最上方、不改变底层界面焦点

很多自制键盘时不知道怎么使键盘保持在最顶层,发现点击键盘界面后系统焦点在键盘界面上了,光标不在底层的行输入框里,就通过输入完成后点击确定的方式将键盘内容传到底层界面,显得不nice,其实这两个问题都很简单能够解决,代码如下

this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);

Qt::WindowStaysOnTopHint 设置窗口置顶
Qt::WindowDoesNotAcceptFocus 设置无焦点窗口

四、长按按键重复输入键盘内容

特别是我们点击退格删除键时,文本比较多是我们使用真实键盘就会长按退格键把十多个文本挨个删除,而使用虚拟键盘时要按十多次退格键,显得不nice。那么我们使用QPushButton的setAutoRepeat为true,就可以实现按键长按功能了,设置重复操作延时为500ms差不多了,按下的时长超过500ms后马上再次执行按键槽函数。

pbtn->setAutoRepeat(true);    //允许自动重复
pbtn->setAutoRepeatDelay(500);//设置重复操作的时延

五、模拟键盘点击事件完成虚拟键盘输入

一些自制虚拟键盘完成键盘输入的方式是同传递文本到输入框的方式,话不多说,就是不nice。点击虚拟按键直接发送对应的按键点击事件就很nice,这样其实就不会太死,甚至中文输入也可以,我们写的是键盘,不是写中文输入法,那些下载网上含有中文输入法的库的大可不必,输入法你系统用的什么就是什么。如果你想中文输入,系统下载的有搜狗输入法,你的键盘只需按下ctrl+shift切换输入法即可,而不是在键盘里实现中文输入法的功能。那样不nice,模拟发送按键点击事件代码如下。

	QPushButton* pbtn = (QPushButton*)sender();
	if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {
		QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());
		QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}

通过QApplication::sendEvent发送一个按键按下和按键松开的事件就相当于模拟一个按键按下事件

QKeyEvent说明:

QKeyEvent::QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text = QString(), bool autorep = false, ushort count = 1)

类型参数必须为QEvent::KeyPress、QEvent::KeyRelease或QEvent::ShortcutOverride。

Int key是事件循环应该监听的Qt:: key的代码。 如果key为0,则事件不是已知键的结果; 例如,它可能是组合序列或键盘宏的结果。 修饰符包含键盘修饰符,给定的文本是键生成的Unicode文本。 如果autorep为真,isAutoRepeat()将为真。 Count是事件中涉及的键的数量。

QKeyEvent在我们这里用4个参数就行了,第二个参数Qt:: key对应的按键,第四个参数是需要发送的文本,没有这个参数是无法输入任何内容的。

QApplication::sendEvent的第一个参数非常重要,是接收键盘输入的控件,比如是底层界面的lineEdit。

六、键盘符号输入

m_mapSymbolKeys.insert("~", Qt::Key_AsciiTilde);
	m_mapSymbolKeys.insert("`", Qt::Key_nobreakspace); 
	m_mapSymbolKeys.insert("-", Qt::Key_Minus);
	m_mapSymbolKeys.insert("_", Qt::Key_Underscore);
	m_mapSymbolKeys.insert("+", Qt::Key_Plus);
	m_mapSymbolKeys.insert("=", Qt::Key_Equal);
	m_mapSymbolKeys.insert(",", Qt::Key_Comma);
	m_mapSymbolKeys.insert(".", Qt::Key_Period);
	m_mapSymbolKeys.insert("/", Qt::Key_Slash);
	m_mapSymbolKeys.insert("<", Qt::Key_Less);
	m_mapSymbolKeys.insert(">", Qt::Key_Greater);
	m_mapSymbolKeys.insert("?", Qt::Key_Question);
	m_mapSymbolKeys.insert("[", Qt::Key_BracketLeft);
	m_mapSymbolKeys.insert("]", Qt::Key_BracketRight);
	m_mapSymbolKeys.insert("{", Qt::Key_BraceLeft);
	m_mapSymbolKeys.insert("}", Qt::Key_BraceRight); 
	m_mapSymbolKeys.insert("|", Qt::Key_Bar);
	m_mapSymbolKeys.insert("\\", Qt::Key_Backslash);
	m_mapSymbolKeys.insert(":", Qt::Key_Colon);
	m_mapSymbolKeys.insert(";", Qt::Key_Semicolon);
	m_mapSymbolKeys.insert("\"", Qt::Key_QuoteLeft);
	m_mapSymbolKeys.insert("'", Qt::Key_Apostrophe);
 
    QKeyEvent keyPress(QEvent::KeyPress, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);
	QKeyEvent keyRelease(QEvent::KeyRelease, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);
	QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
	QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);

键盘输入特定的符号重要是找到QKeyEvent第二个参数对应的按键值即可。按键中的值被都在qnamespace.h的头文件中的enum Key枚举类型内。

七、界面

在这里插入图片描述

八、头文件代码

#pragma once
#pragma execution_character_set("utf-8")
#include <QDialog>
#include "ui_frmKeyBoard.h"
#include "moveWidget.h"
#include <QPushButton>
#include <QKeyEvent>
#include <QDebug>
#include <QStyle>
 
class frmKeyBoard : public QDialog
{
	Q_OBJECT
 
public:
	frmKeyBoard(QWidget *parent = nullptr);
	~frmKeyBoard();
 
	void initFocusWidget(QWidget*);
 
private slots:
	void slotKeyButtonClicked();
	void slotKeyLetterButtonClicked();
	void slotKeyNumberButtonClicked();
 
private:
	Ui::frmKeyBoardClass ui;
	void initFrm();
	void initStyleSheet();
 
	QWidget* m_focusWidget;	//键盘输入主窗口
 
	QVector<QPushButton*> m_letterKeys;
	QVector<QPushButton*> m_NumberKeys;
 
	QMap<QString, Qt::Key> m_mapSymbolKeys;
 
};

九、源文件代码

#include "frmKeyBoard.h"
 
frmKeyBoard::frmKeyBoard(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);
 
	this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
	this->setWindowTitle("屏幕键盘");
	this->setWindowModality(Qt::WindowModal); 
	this->setAttribute(Qt::WA_DeleteOnClose);
 
	MoveWidget* moveWidget = new MoveWidget();
	moveWidget->setWidget(this);
 
	this->initFrm();
	this->initStyleSheet();
}
 
frmKeyBoard::~frmKeyBoard()
{
}
 
void frmKeyBoard::initFocusWidget(QWidget* widget)
{
	m_focusWidget = widget;
}
 
void frmKeyBoard::initFrm()
{
    ui.pushButton_closeKeyboard->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
	m_letterKeys.clear();
	m_NumberKeys.clear();
	QList<QPushButton*> pbtns = this->findChildren<QPushButton*>();
	foreach(QPushButton * pbtn, pbtns) {
		pbtn->setAutoRepeat(true);    //允许自动重复
		pbtn->setAutoRepeatDelay(500);//设置重复操作的时延
 
		if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {
			connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyLetterButtonClicked);
			m_letterKeys.push_back(pbtn);
		}
		else if (pbtn->text().toInt() > 0 && pbtn->text().toInt() <= 9 || pbtn->text() == "0") {
			connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyNumberButtonClicked);
			m_NumberKeys.push_back(pbtn);
		}
		else{
			connect(pbtn, &QPushButton::clicked, this, &frmKeyBoard::slotKeyButtonClicked);
		}
	}
 
	m_mapSymbolKeys.insert("~", Qt::Key_AsciiTilde);
	m_mapSymbolKeys.insert("`", Qt::Key_nobreakspace); 
	m_mapSymbolKeys.insert("-", Qt::Key_Minus);
	m_mapSymbolKeys.insert("_", Qt::Key_Underscore);
	m_mapSymbolKeys.insert("+", Qt::Key_Plus);
	m_mapSymbolKeys.insert("=", Qt::Key_Equal);
	m_mapSymbolKeys.insert(",", Qt::Key_Comma);
	m_mapSymbolKeys.insert(".", Qt::Key_Period);
	m_mapSymbolKeys.insert("/", Qt::Key_Slash);
	m_mapSymbolKeys.insert("<", Qt::Key_Less);
	m_mapSymbolKeys.insert(">", Qt::Key_Greater);
	m_mapSymbolKeys.insert("?", Qt::Key_Question);
	m_mapSymbolKeys.insert("[", Qt::Key_BracketLeft);
	m_mapSymbolKeys.insert("]", Qt::Key_BracketRight);
	m_mapSymbolKeys.insert("{", Qt::Key_BraceLeft);
	m_mapSymbolKeys.insert("}", Qt::Key_BraceRight); 
	m_mapSymbolKeys.insert("|", Qt::Key_Bar);
	m_mapSymbolKeys.insert("\\", Qt::Key_Backslash);
	m_mapSymbolKeys.insert(":", Qt::Key_Colon);
	m_mapSymbolKeys.insert(";", Qt::Key_Semicolon);
	m_mapSymbolKeys.insert("\"", Qt::Key_QuoteLeft);
	m_mapSymbolKeys.insert("'", Qt::Key_Apostrophe);
}
 
void frmKeyBoard::initStyleSheet()
{
	QString qss;
	qss += "QWidget{ background-color:rgb(26,26,26)}";
    qss += "QPushButton{ color:white; background-color:rgb(51,51,51); height:60px; font-size:bold 15pt; border:1px solid rgb(26,26,26); border-radius: 0px; min-width:50px;}";
	qss += "QPushButton:hover{background-color:rgb(229,229,229); color:black;}";
	qss += "QPushButton:pressed,QPushButton:checked{background-color:rgb(0,118,215);}";
	qss += "#pushButton_closeKeyboard{background-color:rgba(0,0,0,0); border:0px}";
	qss += "#pushButton_closeKeyboard:hover{background-color:#b30220;}";
	qss += "#pushButton_space{min-width:500px;}";
	qss += "#pushButton_backspace,#pushButton_shift{min-width:100px;}";
	qss += "#pushButton_enter{min-width:120px;}";
	qss += "#pushButton_tab,#pushButton_ctrl{min-width:70px;}";
	qss += "#pushButton_capsLock{min-width:80px;}";
	qss += "#pushButton_up{min-width:150px;}";
	this->setStyleSheet(qss);
}
 
void frmKeyBoard::slotKeyButtonClicked()
{
	QPushButton* pbtn = (QPushButton*)sender();
	QString objectName = pbtn->objectName();
	if (objectName == "pushButton_closeKeyboard") {
		this->close();
		return;
	}
	if (pbtn->text().contains("Backspace")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Caps")) {	
		if (pbtn->isChecked()) {
			for (auto pbtnKey : m_letterKeys) {
				pbtnKey->setText(pbtnKey->text().toUpper());
			}
		}
		else {
			for (auto pbtnKey : m_letterKeys) {
				pbtnKey->setText(pbtnKey->text().toLower());
			}
		}
	}
	else if(pbtn->text() == "Space") {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier, " ");
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Space, Qt::NoModifier, " ");
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Tab")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Tab, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Enter")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Shift")) {
		if (pbtn->isChecked()) {
			for (auto pbtnKey : m_letterKeys) {
				pbtnKey->setText(pbtnKey->text().toUpper());
			}
		}
		else {
			for (auto pbtnKey : m_letterKeys) {
				pbtnKey->setText(pbtnKey->text().toLower());
			}
		}
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Ctrl")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Control, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Win")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Menu, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Menu, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("Alt")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("↑")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("↓")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("←")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text().contains("→")) {
		QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);
		QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Right, Qt::NoModifier);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else {
		QString symbol;
		if (ui.pushButton_shift->isChecked())
			symbol = pbtn->text().split("\n").at(0);
		else
			symbol = pbtn->text().split("\n").at(1);
 
		QKeyEvent keyPress(QEvent::KeyPress, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);
		QKeyEvent keyRelease(QEvent::KeyRelease, m_mapSymbolKeys.value(symbol), Qt::NoModifier, symbol);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	//取消组合键按下
	if (!pbtn->text().contains("Shift") && !pbtn->text().contains("Ctrl") && !pbtn->text().contains("Win") && !pbtn->text().contains("Alt")) {
		if (ui.pushButton_shift->isChecked()) {
			ui.pushButton_shift->setChecked(false);
			for (auto pbtnKey : m_letterKeys) {
				pbtnKey->setText(pbtnKey->text().toLower());
			}
		}
		if (ui.pushButton_ctrl->isChecked())
			ui.pushButton_ctrl->setChecked(false);
		if (ui.pushButton_win->isChecked())
			ui.pushButton_win->setChecked(false);
		if (ui.pushButton_alt->isChecked())
			ui.pushButton_alt->setChecked(false);
	}
}
 
 
void frmKeyBoard::slotKeyLetterButtonClicked()
{
	QPushButton* pbtn = (QPushButton*)sender();
	if (pbtn->text() >= 'a' && pbtn->text() <= 'z') {
		QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());
		QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()) - 32, Qt::NoModifier, pbtn->text());
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	else if (pbtn->text() >= 'A' && pbtn->text() <= 'Z') {
		QKeyEvent keyPress(QEvent::KeyPress, int(pbtn->text().at(0).toLatin1()), Qt::NoModifier, pbtn->text());
		QKeyEvent keyRelease(QEvent::KeyRelease, int(pbtn->text().at(0).toLatin1()), Qt::NoModifier, pbtn->text());
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
		QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	}
	//取消组合键按下
	if (ui.pushButton_shift->isChecked()) {
		ui.pushButton_shift->setChecked(false);
		for (auto pbtnKey : m_letterKeys) {
			pbtnKey->setText(pbtnKey->text().toLower());
		}
	}
	if (ui.pushButton_ctrl->isChecked())
		ui.pushButton_ctrl->setChecked(false);
	if (ui.pushButton_win->isChecked())
		ui.pushButton_win->setChecked(false);
	if (ui.pushButton_alt->isChecked())
		ui.pushButton_alt->setChecked(false);
}
 
void frmKeyBoard::slotKeyNumberButtonClicked()
{
	QPushButton* pbtn = (QPushButton*)sender();
	QKeyEvent keyPress(QEvent::KeyPress, pbtn->text().toInt() + 48, Qt::NoModifier, pbtn->text());
	QKeyEvent keyRelease(QEvent::KeyRelease, pbtn->text().toInt() + 48, Qt::NoModifier, pbtn->text());
	QApplication::sendEvent(m_focusWidget->focusWidget(), &keyPress);
	QApplication::sendEvent(m_focusWidget->focusWidget(), &keyRelease);
	//取消组合键按下
	if (ui.pushButton_shift->isChecked()) {
		ui.pushButton_shift->setChecked(false);
		for (auto pbtnKey : m_letterKeys) {
			pbtnKey->setText(pbtnKey->text().toLower());
		}
	}
	if (ui.pushButton_ctrl->isChecked())
		ui.pushButton_ctrl->setChecked(false);
	if (ui.pushButton_win->isChecked())
		ui.pushButton_win->setChecked(false);
	if (ui.pushButton_alt->isChecked())
		ui.pushButton_alt->setChecked(false);
}
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虹科方案|使用 HK-TRUENAS支持媒体和娱乐工作流程-2

一、支持 M&E 工作流程的HK-TRUENAS 屡获殊荣的 TrueNAS 存储解决方案支持单独的工作空间来存放可在现场或制作室访问的媒体资产。 TrueNAS 提供企业功能&#xff0c;支持多个物理和虚拟应用程序&#xff0c;并具有同步块和文件存储访问。 这些功能允许备份和重新利用视频、…

路由递归配置

路由递归原理 路由必须有直连的下一跳才能够指导转发,但是路由生成时下一跳可能不是直连的,因此需要计算出一个直连的下一跳和对应的出接口,这个过程就叫做路由递归 。 路由递归也被称为路由 迭代。 实验配置 路由器R1配置 interface GigabitEthernet0/0/0ip address 192.…

《编程思维与实践》1049.GPS数据处理

《编程思维与实践》1049.GPS数据处理 题目 思路 注记: UTC为世界标准时间(0时区),东区加,西区减. 分两步实现: 1.判断是否为有效的语句: 有效需要满足三个条件: ①语句含$GPRMC,可以通过strstr搜索来判断; ②状态已定位,可以用sscanf来读取判断; ③异或结果与校验值相同,校验值…

【Vue学习笔记6】好用的 Vueuse 工具包

1. 安装Vueuse VueUse 的官方&#xff08;https://vueuse.org/&#xff09;的介绍说这是一个 Composition API 的工具集合&#xff0c;适用于 Vue 2.x 或者 Vue 3.x&#xff0c;用起来和 React Hooks 还挺像的。 VueUse 插件的安装 npm install vueuse/core2. 实现全屏功能 …

【三十天精通Vue 3】第二十七天 Vue 3的实战案例-接口进度条

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、安装进度条插件1.1 安装NProgress插件1.2 在Vue3中引入NProgress插件二、在路由中使用进度条2.1 在全局路由中使用进度…

ubuntu20.04安装搜狗输入法

搜狗输入法下载网址&#xff1a; https://shurufa.sogou.com/linux 选择x86_64版本 打开 系统设置——区域和语言——管理已安装的语言——在“语言”tab下——点击“添加或删除语言” 弹出“已安装语言”窗口&#xff0c;勾选中文&#xff08;简体&#xff09;&#xff0c;点…

【RPC、WebSocket】

文章目录 有HTTP协议为什么还要RPCTCPHTTP 和 RPCHTTP 和 RPC 有什么区别 有HTTP协议为什么还要WebSocket使用HTTP不断轮询长轮询WebSocket怎么建立WebSocket连接 有HTTP协议为什么还要RPC TCP TCP三个特点&#xff1a;面向连接、可靠、基于字节流。 基于字节流 字节流可以理…

Disabled PicPipeline: ImagesPipeline requires installing Pillow 4.0.0 or later

目录 一、scrapy是什么 二、问题以及原因 三、解决办法 1、确保系统已经安装了 Pillow 库。 2、安装 Pillow 库。 3、在项目根目录中添加 Pillow 的 .pth 文件。 一、scrapy是什么 Scrapy是一个用于从网站和Web应用中抓取数据的强大的Python库。Scrapy支持异步I/O和 Scr…

销售数据分析怎么做?这篇文章说清楚了

如何分析销售数据&#xff1f;分析销售数据有哪些指标&#xff1f;销售数据分析有什么作用&#xff1f; 销售数据是不是得通过数据分析软件啊&#xff1f; 本文将为您解答疑惑—— 一、分析销售数据的指标 从两个层面上来讲&#xff0c;一个是对销售情况的整体把控&#xf…

大学校友会管理APP系统开发 重温同学梦再叙校园情

互联网技术的深入发展&#xff0c;让各行各业对网络的依赖都逐渐加深&#xff0c;可以说网络在今天已经成为无数个你我他不可或缺的平台。学生时代是一生中最美好的时期&#xff0c;校友是社会高效重要的社会资本和无形资产&#xff0c;校友与校友之间信息交流也需要依靠互联网…

虚拟化转向容器的新方案,红帽正式推出虚拟化容器统一平台——openshift虚拟化

编辑 | 宋慧 出品 | CSDN 云计算 云原生、容器化&#xff0c;是近年 IT 界主要的话题之一。 数字化转型的浪潮下&#xff0c;技术在朝向更加有利于业务快速迭代的方向发展。据 CSDN 最新年度《中国开发者调查报告》数据显示&#xff0c;近一半的公司&#xff08;43%&#xff0…

爬虫|Python|ts格式的加密视频合并方法

前言&#xff1a; 爬虫的一些基本概念&#xff1a; 对于爬虫来说&#xff0c;没有道德&#xff08;比如&#xff0c;某些爬虫上w的并发&#xff0c;那么&#xff0c;一些小站可能就会崩溃&#xff0c;其实爬虫也是可以作为网络攻击的&#xff0c;假设有需要攻击的网站&#x…

Shell 脚本传递参数的两种方式:位置传参与指令式传参

Shell 脚本传递参数的两种方式 方式一&#xff1a;数字传参 直接传参 数字传递可以用$1 $2 $3 ......获取第一个第二个第三个参数&#xff0c;$0获取命令&#xff08;也就是你的文件名&#xff09;&#xff0c;$#可以查看总的参数个数 以下文件命名为param1&#xff08;shel…

rk3568平台调试typec口实现uvc输出,网络共享等功能

一、修改kernel相关配置 注意&#xff1a;一定要知道主控接线&#xff0c;那个物理口是otg的&#xff0c;然后要找准与之所连接的phy和控制器。然后处理CC1 CC2识别芯片&#xff0c;fusb302。默认sdk自带有驱动&#xff0c;需要配上中断脚和提供VBUS 5V的脚。用来判断角色是DF…

( “ 图 “ 之 拓扑排序 ) 210. 课程表 II ——【Leetcode每日一题】

❓210. 课程表 II 难度&#xff1a;中等 现在你总共有 numCourses 门课需要选&#xff0c;记为 0 到 numCourses - 1。给你一个数组 prerequisites &#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示在选修课程 ai 前 必须 先选修 bi 。 例如&#xff0c;想要学…

使用 docker 搭建 mysql 主从配置

真正的配置文件是docker中 /etc/my.cnf 拉取镜像 docker pull mysql:5.7启动主数据库和从数据库 docker run -p 3306:3306 --restartalways --name mysql_v1 -v /var/mysql/mysql_v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORDroot -d mysql:5.7 docker run -p 3307:3306 --res…

Neural Network笔记2

torch.nn: Containers: 神经网络骨架 Convolution Layers 卷积层 Pooling Layers 池化层 Normalization Layers 正则化层 Non-linear Activations (weighted sum, nonlinearity) 非线性激活 Convolution Layers Conv2d torch.nn.Conv2d(in_channels, out_channels, ke…

java版企业电子招投标系统源码 spring boot+mybatis+前后端分离

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

一体化管理系统如何使企业受益?

在当今世界&#xff0c;大多数企业使用管理系统来制定政策和程序&#xff0c;以帮助实现其业务目标。管理体系是用于确保企业能够管理实现其目标所需的所有任务的流程和程序的结构。 公司或企业会有支持客户、采购、项目、考勤、财务等管理系统&#xff0c;这些管理系统通常在…

OBCP部分考点总结

备份恢复&#xff1a; 恢复的最小力度&#xff1a;租户级 分布式事务&#xff1a; 参与者或者协调者宕机&#xff0c;全部参与者发送prepare ok&#xff0c;客户端会commit sql引擎&#xff1a; 不能使用常量的场景&#xff1a;between and 应该可以使用常量&#xff0c;被…