Pyqt5高级技巧:多线程任务、窗体交互、常用控件介绍(含基础Demo)

news2024/11/16 10:48:25

一、多线程任务和多窗体交互

【main】

import MainForm
#import CRUD
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = MainForm.Ui_MainWindow()#也可能是Ui_Form/Ui_widget这里填写的是生成的类名
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【MainForm.py】

# -*- coding: utf-8 -*-
import time

# Form implementation generated from reading ui file 'MainForm.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal


class Ui_MainWindow(object):
    def __init__(self):
        super().__init__()


    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("ril.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(300, 150, 181, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.open_new_window)
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(30, 440, 741, 51))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(290, 260, 201, 28))
        self.pushButton_2.setObjectName("pushButton_2")

        MainWindow.setCentralWidget(self.centralwidget)

        self.worker = WorkerThread()  # 创建WorkerThread实例
        self.worker.progress.connect(self.update_progress)  # 多线程连接进度条
        self.pushButton_2.clicked.connect(self.worker.start) # 开始按钮连接多线程


        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "点击我打开另一个窗体"))
        self.pushButton_2.setText(_translate("MainWindow", "点击我,执行多线程任务"))

    def open_new_window(self):
        import Form2
        # 创建新的子窗口
        self.new_window = Form2.Ui_Form()  # 使用 Form2 类
        self.new_window.setWindowTitle("一个新的窗体")
        # Form2信号 关联 主窗口获取方法getdata
        self.new_window.signal.connect(self.MainGetData)
        # 发送消息到Form2
        self.new_window.SubGetData("hello")
        self.new_window.show()  # 显示新窗体

    def update_progress(self, value):#设置进度条的值
        self.progressBar.setValue(value)

    def MainGetData(self,msg):#接收Form2的信息
        print(f"我是主窗体,我收到了: {msg}")

class WorkerThread(QThread):  #多线程任务
    progress = pyqtSignal(int)  # 自定义信号用于发送进度

    def run(self):
        for i in range(1, 6):
            time.sleep(i)  # 模拟耗时操作
            self.progress.emit(i * 20)  # 发送当前进度
            print(f"任务{i}完成了")
        self.progress.emit(100)  # 任务全部完成

【Form2】

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Form2.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSignal


class Ui_Form(QtWidgets.QWidget):#【改】1.改为继承QtWidgets.QWidget

    signal = pyqtSignal(str)#信号,沟通主窗体的getdata方法

    def __init__(self):# 【加】2.初始化界面方法
        super().__init__()
        self.setupUi(self)

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(571, 345)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(190, 30, 281, 161))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(36)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(220, 160, 151, 31))
        self.lineEdit.setObjectName("lineEdit")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(240, 210, 111, 28))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.SubSendData)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "子窗体"))
        self.pushButton.setText(_translate("Form", "发送给主窗体"))

    def SubGetData(self,msg):#接收主窗体的信息
        print(f"我是Form2,我收到了: {msg}")

    def SubSendData(self):#发送信息给主窗体
        outputdata = self.lineEdit.text()
        self.signal.emit(outputdata)
        self.close()

【效果图】

运行main.py函数,点击打开窗体即打开Form2,点击多线程任务即可实现多线程任务。

二、增删改查Demo

【main.py】

#import MainForm
import CRUD
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = CRUD.Ui_Form()#也可能是Ui_Form/Ui_widget这里填写的是生成的类名
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【CRUD.py】 

import SQLiterConnect


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1074, 759)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(410, 0, 281, 91))
        #icon = QtGui.QIcon()
        #icon.addPixmap(QtGui.QPixmap("ril.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        #Form.setWindowIcon(icon)#设置icon图标
        font = QtGui.QFont()
        font.setFamily("黑体")
        font.setPointSize(26)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(80, 110, 111, 31))
        self.lineEdit.setObjectName("lineEdit")
        self.comboBox = QtWidgets.QComboBox(Form)
        self.comboBox.setGeometry(QtCore.QRect(520, 110, 141, 31))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.checkBox = QtWidgets.QCheckBox(Form)
        self.checkBox.setGeometry(QtCore.QRect(700, 110, 111, 21))
        self.checkBox.setObjectName("checkBox")
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setGeometry(QtCore.QRect(300, 110, 131, 31))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(840, 110, 93, 28))
        self.pushButton.setObjectName("pushButton")
        self.tableWidget = QtWidgets.QTableWidget(Form)
        self.tableWidget.setGeometry(QtCore.QRect(30, 170, 1021, 571))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(30, 120, 72, 15))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(Form)
        self.label_3.setGeometry(QtCore.QRect(250, 120, 72, 15))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(Form)
        self.label_4.setGeometry(QtCore.QRect(470, 120, 72, 15))
        self.label_4.setObjectName("label_4")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(940, 110, 93, 28))
        self.pushButton_2.setObjectName("pushButton_2")
        #绑定事件
        self.pushButton.clicked.connect(self.query)
        self.pushButton_2.clicked.connect(self.add)
        self.lineEdit.textChanged.connect(self.query)
        self.lineEdit_2.textChanged.connect(self.query)
        self.checkBox.stateChanged.connect(self.query)
        self.comboBox.currentIndexChanged.connect(self.query)
        #初始化
        self.tableWidget.setColumnCount(8)#设置8列
        self.tableWidget.setHorizontalHeaderLabels(["ID", "姓名", "年龄", "班级", "性别", "是否是领导", "编辑", "删除"])
        self.query()
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "增删改查演示"))
        self.label.setText(_translate("Form", "增删改查Demo"))
        self.comboBox.setItemText(0, _translate("Form", "全部"))
        self.comboBox.setItemText(1, _translate("Form", "男"))
        self.comboBox.setItemText(2, _translate("Form", "女"))
        self.checkBox.setText(_translate("Form", "是否是领导"))
        self.pushButton.setText(_translate("Form", "查询"))
        self.label_2.setText(_translate("Form", "姓名:"))
        self.label_3.setText(_translate("Form", "班级:"))
        self.label_4.setText(_translate("Form", "性别:"))
        self.pushButton_2.setText(_translate("Form", "新增"))

    def query(self):
        try:
            # 清空表格
            self.tableWidget.setRowCount(0)

            # 获取输入数据
            name = self.lineEdit.text()
            classes = self.lineEdit_2.text()
            sex = self.comboBox.currentText()
            is_leader = 1 if self.checkBox.isChecked() else 0

            #拼接SQL
            sql = "SELECT * FROM Student WHERE 1=1"
            if name:
                sql += f" AND Name LIKE '%{name}%'"
            if classes:
                sql += f" AND Classes LIKE '%{classes}%'"
            if sex and sex!="全部":
                sql+= f" AND Sex = '{sex}'"
            if is_leader:
                sql += f" AND IsLeader = {is_leader}"

            rows = SQLiterConnect.sqlquery(sql)


            # 填充表格
            for row in rows:
                rowPosition = self.tableWidget.rowCount()
                self.tableWidget.insertRow(rowPosition)
                for col, item in enumerate(row):
                    table_item = QtWidgets.QTableWidgetItem(str(item))
                    # 设置内容居中对齐
                    table_item.setTextAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter)
                    self.tableWidget.setItem(rowPosition, col, table_item)

                editButton = QtWidgets.QPushButton("编辑")
                editButton.clicked.connect(lambda checked, row=row: self.edit(row))
                self.tableWidget.setCellWidget(rowPosition, 6, editButton)

                deleteButton = QtWidgets.QPushButton("删除")
                deleteButton.clicked.connect(lambda checked, row=rowPosition: self.delete(row))
                self.tableWidget.setCellWidget(rowPosition, 7, deleteButton)
        except Exception as e:
            print(f"查询出错{e}")

    def add(self):
        try:
            dialog = EditDialog((None, '', '', '', '', 0))  # 创建空记录的对话框
            if dialog.exec_():
                data = dialog.get_data()
                #编写SQL:
                sql = f"INSERT INTO Student (Name, Age, Classes, Sex, IsLeader) VALUES ('{data['name']}', {data['age']}, '{data['classes']}', '{data['sex']}', {data['is_leader']})"
                SQLiterConnect.sqlexecute(sql)
                self.query()
        except Exception as e:
            print(f"新增出错{e}")

    def edit(self, row):
        try:
            dialog = EditDialog(row)
            if dialog.exec_():
                data = dialog.get_data()
                item_id = row[0]

                #编写并执行SQL
                sql=f"""
                UPDATE Student 
                SET Name = '{data['name']}', Age = '{data['age']}', Classes = '{data['classes']}', 
                Sex = '{data['sex']}', IsLeader = '{data['is_leader']}' 
                WHERE ID = {item_id}"""
                SQLiterConnect.sqlexecute(sql)
                self.query()
        except Exception as e:
            print(f"编辑出错{e}")

    def delete(self, row):
        try:
            item_id = self.tableWidget.item(row, 0).text()
            reply = QtWidgets.QMessageBox.question(None, '删除', '确定删除吗?',
                                                   QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                                   QtWidgets.QMessageBox.No)
            if reply == QtWidgets.QMessageBox.Yes:
                sql = f"DELETE FROM Student WHERE ID = {item_id}"
                SQLiterConnect.sqlexecute(sql)
                self.query()
        except Exception as e:
            print(f"删除出错{e}")

class EditDialog(QtWidgets.QDialog):#编辑对话框
    def __init__(self, row, parent=None):
        super(EditDialog, self).__init__(parent)

        self.row = row
        self.setWindowTitle("编辑框")
        self.setGeometry(100, 100, 300, 200)

        # self.setWindowIcon(QtGui.QIcon("ril.ico"))#设置icon图标

        self.name_edit = QtWidgets.QLineEdit(self)
        self.name_edit.setText(row[1])

        self.age_edit = QtWidgets.QLineEdit(self)
        self.age_edit.setText(str(row[2]))

        self.classes_edit = QtWidgets.QLineEdit(self)
        self.classes_edit.setText(row[3])

        self.sex_combo = QtWidgets.QComboBox(self)
        self.sex_combo.addItems(["全部","男", "女"])
        self.sex_combo.setCurrentText(row[4])

        self.is_leader_check = QtWidgets.QCheckBox("Is Leader", self)
        self.is_leader_check.setChecked(row[5])

        self.save_button = QtWidgets.QPushButton("保存", self)
        self.save_button.clicked.connect(self.save)

        layout = QtWidgets.QFormLayout(self)
        layout.addRow("Name:", self.name_edit)
        layout.addRow("Age:", self.age_edit)
        layout.addRow("Classes:", self.classes_edit)
        layout.addRow("Sex:", self.sex_combo)
        layout.addRow("Is Leader:", self.is_leader_check)
        layout.addWidget(self.save_button)

        # 计算并设置对话框位置为屏幕中心
        screen_rect = QtWidgets.QDesktopWidget().screenGeometry()
        dialog_rect = self.geometry()
        x = (screen_rect.width() - dialog_rect.width()) // 2
        y = (screen_rect.height() - dialog_rect.height()) // 2
        self.move(x, y)

    def save(self):
        self.accept()

    def get_data(self):
        try:
            return {
                'name': self.name_edit.text(),
                'age': int(self.age_edit.text()),
                'classes': self.classes_edit.text(),
                'sex': self.sex_combo.currentText(),
                'is_leader': 1 if self.is_leader_check.isChecked() else 0
            }
        except Exception as e:
            print(f"编辑框转化数据出错{e}")

【SQLiterConnect】(sqlite数据库)

from datetime import datetime
import sqlite3

conn = sqlite3.connect('database.db')
cursor = conn.cursor()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

def sqlquery(sql):
    try:
        rows = cursor.execute(sql).fetchall()
        print(f"查询成功,数据:{len(rows)}条,时间:{now}")
        return rows
    except Exception as e:
        print(f"查询出现错误: {e},时间:{now},出错SQL:\n{sql}")

def sqlexecute(sql):
    try:
        cursor.execute(sql)
        cursor.connection.commit()
        print(f"增删改成功,时间:{now}")
    except Exception as e:
        print(f"增删改出现错误: {e},时间:{now},出错SQL:\n{sql}")#不要出现GO等脚本关键字
        cursor.connection.rollback()

if __name__ == '__main__':
    pass
    # data = sqlquery("SELECT * FROM BuyTable WHERE ID='1'")
    # ins = 100
    # data = sqlquery(f"SELECT * FROM BuyTable WHERE ID={ins}")

 

 

 

不断更新中..... 

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

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

相关文章

算法设计与分析:实验三 回溯法——地图填色问题

实验内容与要求: 问题描述: 我们可以将地图转换为平面图,每个地区变成一个节点,相邻地区用边连接,我们要为这个图形的顶点着色,并且两个顶点通过边连接时必须具有不同的颜色。附件是给出的地图数据&#…

如何在 MySQL 中使用 Socket 身份验证 ?

在 MySQL 和 MariaDB 中,可以使用 socket 身份验证,而不是传统的用户名和密码组合。这种方法既安全又方便,因为它使用的是操作系统的用户凭证。 什么是 Socket 身份验证? Socket 身份验证允许使用 Unix 或 Linux 用户凭证连接到数据库&…

NS4892B 蓝牙耳机充电仓-线性锂电池充放电管理 IC

1 特性 充电部分  (0V) 涓流 / 恒流 / 恒压三段式充电  内部设定 300mA 充电电流  线性工作模式充电  内置自动复充功能  内部预设 4.2V 充电浮充电压  内置过温保护 放电部分  同步升压输出 5.1V  放电开关频率 1MHz  放电效率最…

【网络】NAT、代理服务、内网穿透

NAT技术与代理服务 文章目录 1.NAT技术1.1NAT技术背景1.2NAT IP转换过程1.3NAPT1.4NAT技术的缺陷 2.代理服务器3.NAT和代理服务器的区别4.内网穿透 1.NAT技术 NAT(Network Address Translation,网络地址转换)技术,是解决IP地址不…

高效处理高并发手机号查询请求:系统设计与优化策略

高效处理高并发手机号查询请求:系统设计与优化策略 一、系统架构设计原理1. 路由网关层2. Web服务层3. 消息队列层4. 实时查询微服务层5. 缓存预热服务 二、总结与优化 💖The Begin💖点点关注,收藏不迷路💖 在现代互联…

Java语言程序设计基础篇_编程练习题17.14 (加密文件)/17.15 (解密文件)

题目:17.14 (加密文件) 通过给文件中的每个字节加5来对文件编码。编写一个程序,提示用户输入一个输入文件名和一个输出文件名,然后将输入文件的加密版本存入输出文件。 代码示例:编程练习题17_14EncryptFiles.java package chapte…

VM Workstation虚拟机AlmaLinux 9.4操作系统安装(桌面版安装详细教程)(宝塔面板的安装),填补CentOS终止支持维护的空白

目录 AlmaLinux介绍 AlmaLinux操作系统的安装 1、下载镜像文件 2、新建虚拟机 (1)点击创建新的虚拟机 (2)打开虚拟机向导后,选择“自定义”安装,然后点击“下一步” (3)选择虚…

文本数据分析-(TF-IDF)(1)

文章目录 一、TF-IDF简介1.意义2.TF与IDF1).TF(Term Frequency)2).IDF(Inverse Document Frequency)3).TF-IDF 二、应用三、代码实现1.文件读取2.数据预处理3.排序和输出4.全部代码 一、TF-IDF简介 1.意义 TF-IDF(Te…

大数据查询优化之谓词下推 ?

谓词 谓词,可以理解为条件表达式,在SQL中,谓词就是返回Boolean值,即True或False的函数,或是隐式转换为Boolean的函数。SQL中的谓词主要有 LKIE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS其结果为布尔值&#xff0c…

NASA数据集:ASO L4雷达雪神数据集

目录 简介 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ASO L4 Lidar Snow Depth 50m UTM Grid V001 简介 该数据集包含根据机载光探测和测距仪(或称激光雷达)对地表高程的测量得出的 50 米网格雪深。 这些数据是 NASA/JPL 机载雪地观测…

如何构建基于Java SpringBoot的医疗器械管理系统?四步详解从需求分析到系统部署,集成Vue.js提升用户体验,内含MySQL数据库管理技巧。

🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…

采购管理流程:自动化如何使效率提升75% ?

与许多业务流程一样,采购到付款 (P2P) 流程也面临着潜在错误、可避免的成本支出以及可能导致的延误。目前,实现自动化的采购流程比例尚不足一半。 自动化在工作场所的应用具有深远的影响,其重要性不言而喻。对于某些企业而言,自动…

android openGL ES详解——面剔除

一、什么是面剔除? 1.面剔除 尝试在头脑中想象一下有一个3D立方体,你从任何一个方向去看它,最多可以同时看到多少个面。如果你的想象力不是过于丰富,你最终最多能数出来的面是3个。你可以从一个立方体的任意位置和方向上去看它&…

金融上云方案中,国产虚拟化产品选型的重点考虑因素、自动化运维建设步骤及如何进行保障数据中心安全需求的存储设计等问题及解决方法|金融行业数字化QA合集③

Q:金融机构应该从哪些方面考虑虚拟化产品选型? 我行是中小规模城商行,想实现虚拟化国产替换,针对国产虚拟化种类繁多的情况,我行应该从哪些方面考虑产品选型,确保所选择产品既能满足信创替换,又…

银河麒麟v10-sp3-x86系统安装k8s-1.30.4

X86-64和arm架构的区别 x86-64架构: 设计理念:x86-64架构起源于Intel的x86架构,并对其进行了64位扩展。这种架构的设计侧重于高性能和灵活性,适合处理复杂的计算任务。 性能特点:x86-64架构的处理器通常提供高性能的…

六个方面探讨企业为何迫切需要替换FTP

随着信息技术的迅猛发展和网络安全形势的日趋严峻,传统的FTP文件传输协议因其固有的局限性和安全隐患,逐渐难以满足现代企业的需求。因此,寻找并升级FTP替代方案成为众多企业需要解决的问题。本文将从六个方面探讨企业为何迫切需要替换FTP。 …

云轴科技ZStack产品升级,浙江分公司产品发布会成功举办

近日,以“智启未来,云端共赢”为主题的云轴科技ZStack浙江分公司针对浙江地区渠道合作伙伴的产品发布会在杭州顺利召开。ZStack总代理伟仕佳杰、神州数码、英迈等百余位合作伙伴代表出席会议,共同见证ZStack在云基础设施与AI软件基础设施领域…

易查分如何查询图片?

最近经常看到老师们各种分享和讨论一个问题,今天,我就和大家聊聊如何高效地在易查分平台上上传和管理图片,让查询结果更加直观。 首先准备你的图片,无论是获奖证书还是奖状,确保它们的格式正确,比如"2…

VMware虚拟机安装的Ubuntu,桥接方式静态ip,内网可以访问,ping外网不可用

1.环境说明 系统:Ubuntu 24.04 环境:VMware下桥接静态IP设置 2.问题:ping www.baidu.com报错 [~] ping www.baidu.com ping: www.baidu.com: Temporary failure in name resolutio…

十、前后端分离通用权限系统(10)

🌻🌻 目录 一、功能说明二、部门管理三、岗位管理四、日志管理4.1、登录日志4.1.1、功能实现- 接口4.1.2、编写 AsyncLoginLogMapper4.1.3、功能实现- 接口实现4.1.4、导入获取ip地址的工具类 IpUtil4.1.5、在 TokenLoginFilter 调用方法实现4.1.6、修改…