Python文件管理器:一个基于wxPython的桌面应用

server/2024/10/19 3:29:28/

在当今的软件开发世界中,管理大量的源代码文件变得越来越重要。无论是个人项目还是大型团队协作,有一个强大而灵活的文件管理工具都可以大大提高工作效率。今天,我们要介绍一个基于Python和wxPython构建的文件管理器,它专门用于管理.py文件。
C:\pythoncode\new\managefiles.py

全部代码

python">import wx
import wx.lib.mixins.listctrl as listmix
import sqlite3
import os
import subprocess
from datetime import datetime
import openpyxlclass EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin):def __init__(self, parent, style):wx.ListCtrl.__init__(self, parent, style=style)listmix.TextEditMixin.__init__(self)class MyFrame(wx.Frame):def __init__(self):super().__init__(parent=None, title="Manage .py Files", size=(1000, 600))panel = wx.Panel(self)vbox = wx.BoxSizer(wx.VERTICAL)# Folder selection and scan buttonhbox1 = wx.BoxSizer(wx.HORIZONTAL)self.folder_picker = wx.DirPickerCtrl(panel)scan_btn = wx.Button(panel, label="Scan")scan_btn.Bind(wx.EVT_BUTTON, self.on_scan)hbox1.Add(self.folder_picker, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)hbox1.Add(scan_btn, flag=wx.ALL, border=5)# ListView1 for displaying .py filesself.listview1 = wx.ListCtrl(panel, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)self.listview1.InsertColumn(0, "File Name", width=200)self.listview1.InsertColumn(1, "Full Path", width=400)self.listview1.InsertColumn(2, "Date Modified", width=200)self.listview1.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_listview1_double_click)# Search box for ListView1hbox2 = wx.BoxSizer(wx.HORIZONTAL)self.search1 = wx.TextCtrl(panel)search1_btn = wx.Button(panel, label="Search ListView1")search1_btn.Bind(wx.EVT_BUTTON, self.on_search1)hbox2.Add(self.search1, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)hbox2.Add(search1_btn, flag=wx.ALL, border=5)# ListView2 for selected files with editable remarks and valid checkboxself.listview2 = wx.ListCtrl(panel, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)self.listview2.InsertColumn(0, "File Name", width=200)self.listview2.InsertColumn(1, "Full Path", width=400)self.listview2.InsertColumn(2, "Date Modified", width=200)self.listview2.InsertColumn(3, "Remarks", width=150)self.listview2.InsertColumn(4, "Valid", width=50)self.listview2.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_listview2_double_click)# Search box for ListView2hbox3 = wx.BoxSizer(wx.HORIZONTAL)self.search2 = wx.TextCtrl(panel)search2_btn = wx.Button(panel, label="Search ListView2")search2_btn.Bind(wx.EVT_BUTTON, self.on_search2)hbox3.Add(self.search2, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)hbox3.Add(search2_btn, flag=wx.ALL, border=5)# Buttons for opening, saving, and deletinghbox4 = wx.BoxSizer(wx.HORIZONTAL)open_btn = wx.Button(panel, label="Open in VSCode")open_btn.Bind(wx.EVT_BUTTON, self.on_open)save_btn = wx.Button(panel, label="Save to Database")save_btn.Bind(wx.EVT_BUTTON, self.save_to_database)delete_btn = wx.Button(panel, label="Delete Selected")delete_btn.Bind(wx.EVT_BUTTON, self.on_delete)hbox4.Add(open_btn, flag=wx.ALL, border=5)hbox4.Add(save_btn, flag=wx.ALL, border=5)hbox4.Add(delete_btn, flag=wx.ALL, border=5)# ListView3 for displaying database recordsself.listview3 = wx.ListCtrl(panel, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)self.listview3.InsertColumn(0, "File Name", width=200)self.listview3.InsertColumn(1, "Full Path", width=400)self.listview3.InsertColumn(2, "Date Modified", width=200)self.listview3.InsertColumn(3, "Remarks", width=150)self.listview3.InsertColumn(4, "Valid", width=50)# Buttons for refreshing and deleting database records, opening in VSCode, and exporting to Excelhbox5 = wx.BoxSizer(wx.HORIZONTAL)refresh_btn = wx.Button(panel, label="Refresh Database Records")refresh_btn.Bind(wx.EVT_BUTTON, self.on_refresh)delete_db_btn = wx.Button(panel, label="Delete Database Record")delete_db_btn.Bind(wx.EVT_BUTTON, self.on_delete_db)open_vscode_btn = wx.Button(panel, label="Open in VSCode")open_vscode_btn.Bind(wx.EVT_BUTTON, self.on_open_vscode)export_excel_btn = wx.Button(panel, label="Export to Excel")export_excel_btn.Bind(wx.EVT_BUTTON, self.on_export_excel)hbox5.Add(refresh_btn, flag=wx.ALL, border=5)hbox5.Add(delete_db_btn, flag=wx.ALL, border=5)hbox5.Add(open_vscode_btn, flag=wx.ALL, border=5)hbox5.Add(export_excel_btn, flag=wx.ALL, border=5)# Adding all to the main vertical boxvbox.Add(hbox1, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(self.listview1, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(hbox2, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(self.listview2, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(hbox3, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(hbox4, flag=wx.ALIGN_CENTER | wx.ALL, border=5)vbox.Add(self.listview3, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)vbox.Add(hbox5, flag=wx.ALIGN_CENTER | wx.ALL, border=5)panel.SetSizer(vbox)self.db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files1.db")def on_scan(self, event):folder_path = self.folder_picker.GetPath()if not folder_path:wx.MessageBox("Please select a folder.", "Error", wx.OK | wx.ICON_ERROR)returnself.listview1.DeleteAllItems()py_files = []for root, dirs, files in os.walk(folder_path):for file in files:if file.endswith(".py"):full_path = os.path.join(root, file)date_modified = os.path.getmtime(full_path)date_str = wx.DateTime.FromTimeT(int(date_modified)).FormatISOCombined()py_files.append((file, full_path, date_str, date_modified))# Sort files by date modified (most recent first)py_files.sort(key=lambda x: x[3], reverse=True)for file, full_path, date_str, _ in py_files:index = self.listview1.InsertItem(self.listview1.GetItemCount(), file)self.listview1.SetItem(index, 1, full_path)self.listview1.SetItem(index, 2, date_str)def on_listview1_double_click(self, event):selected = self.listview1.GetFirstSelected()if selected == -1:returnfile_name = self.listview1.GetItemText(selected)full_path = self.listview1.GetItem(selected, 1).GetText()date_modified = self.listview1.GetItem(selected, 2).GetText()new_index = self.listview2.InsertItem(self.listview2.GetItemCount(), file_name)self.listview2.SetItem(new_index, 1, full_path)self.listview2.SetItem(new_index, 2, date_modified)self.listview2.SetItem(new_index, 3, "")self.listview2.SetItem(new_index, 4, "No")def on_listview2_double_click(self, event):selected = self.listview2.GetFirstSelected()if selected == -1:returnremarks = self.listview2.GetItem(selected, 3).GetText()valid = self.listview2.GetItem(selected, 4).GetText()dlg = EditDialog(self, remarks, valid == "Yes")if dlg.ShowModal() == wx.ID_OK:new_remarks, new_valid = dlg.get_values()self.listview2.SetItem(selected, 3, new_remarks)self.listview2.SetItem(selected, 4, new_valid)dlg.Destroy()def on_search1(self, event):search_term = self.search1.GetValue().lower()self.search_in_listview(self.listview1, search_term)def on_search2(self, event):search_term = self.search2.GetValue().lower()self.search_in_listview(self.listview2, search_term)# def search_in_listview(self, listview, search_term):#     listview.DeleteAllItems()#     for index in range(listview.GetItemCount()):#         item_text = listview.GetItemText(index).lower()#         full_path = listview.GetItem(index, 1).GetText().lower()#         if search_term in item_text or search_term in full_path:#             new_index = listview.InsertItem(listview.GetItemCount(), listview.GetItemText(index))#             for col in range(1, listview.GetColumnCount()):#                 listview.SetItem(new_index, col, listview.GetItem(index, col).GetText())def search_in_listview(self, listview, search_term):for i in range(listview.GetItemCount()):item = listview.GetItem(i)if search_term in item.GetText().lower() or search_term in listview.GetItem(i, 1).GetText().lower():item.SetBackgroundColour(wx.YELLOW)listview.SetItem(item)listview.EnsureVisible(i)else:item.SetBackgroundColour(wx.WHITE)listview.SetItem(item)if not search_term:for i in range(listview.GetItemCount()):item = listview.GetItem(i)item.SetBackgroundColour(wx.WHITE)listview.SetItem(item)def on_open(self, event):self.open_in_vscode(self.listview2)def on_open_vscode(self, event):self.open_in_vscode(self.listview3)def open_in_vscode(self, listview):selected = listview.GetFirstSelected()if selected == -1:wx.MessageBox("Please select a file to open", "Error", wx.OK | wx.ICON_ERROR)returnfull_path = listview.GetItem(selected, 1).GetText()subprocess.Popen(["C:\\Users\\86182\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe", full_path])# def save_to_database(self, event):#     try:#         conn = sqlite3.connect(self.db_path)#         cursor = conn.cursor()#         # Ensure table exists#         cursor.execute('''CREATE TABLE IF NOT EXISTS files (#                             id INTEGER PRIMARY KEY AUTOINCREMENT,#                             file_name TEXT,#                             full_path TEXT,#                             date_modified TEXT,#                             remarks TEXT,#                             valid INTEGER)''')#         cursor.execute('DELETE FROM files')  # Clear old records#         for index in range(self.listview2.GetItemCount()):#             file_name = self.listview2.GetItemText(index)#             full_path = self.listview2.GetItem(index, 1).GetText()#             date_modified = self.listview2.GetItem(index, 2).GetText()#             remarks = self.listview2.GetItem(index, 3).GetText()#             valid = self.listview2.GetItem(index, 4).GetText()#             valid = 1 if valid == "Yes" else 0#             cursor.execute('INSERT INTO files (file_name, full_path, date_modified, remarks, valid) VALUES (?, ?, ?, ?, ?)',#                         (file_name, full_path, date_modified, remarks, valid))#         conn.commit()  # Save changes#     except sqlite3.Error as e:#         wx.MessageBox(f"Database error: {e}", "Error", wx.OK | wx.ICON_ERROR)#     finally:#         conn.close()  # Ensure connection is closed#     wx.MessageBox("Data saved to the database.", "Info", wx.OK | wx.ICON_INFORMATION)def save_to_database(self, event):try:conn = sqlite3.connect(self.db_path)cursor = conn.cursor()# Ensure table existscursor.execute('''CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT,file_name TEXT,full_path TEXT,date_modified TEXT,remarks TEXT,valid INTEGER)''')# Append new records instead of deleting old onesfor index in range(self.listview2.GetItemCount()):file_name = self.listview2.GetItemText(index)full_path = self.listview2.GetItem(index, 1).GetText()date_modified = self.listview2.GetItem(index, 2).GetText()remarks = self.listview2.GetItem(index, 3).GetText()valid = self.listview2.GetItem(index, 4).GetText()valid = 1 if valid == "Yes" else 0# Check if the record already existscursor.execute('SELECT * FROM files WHERE full_path = ?', (full_path,))if cursor.fetchone() is None:# If it doesn't exist, insert a new recordcursor.execute('INSERT INTO files (file_name, full_path, date_modified, remarks, valid) VALUES (?, ?, ?, ?, ?)',(file_name, full_path, date_modified, remarks, valid))else:# If it exists, update the existing recordcursor.execute('UPDATE files SET file_name = ?, date_modified = ?, remarks = ?, valid = ? WHERE full_path = ?',(file_name, date_modified, remarks, valid, full_path))conn.commit()  # Save changesexcept sqlite3.Error as e:wx.MessageBox(f"Database error: {e}", "Error", wx.OK | wx.ICON_ERROR)finally:conn.close()  # Ensure connection is closedwx.MessageBox("Data saved to the database.", "Info", wx.OK | wx.ICON_INFORMATION)def on_delete(self, event):selected = self.listview2.GetFirstSelected()if selected == -1:wx.MessageBox("Please select a file to delete", "Error", wx.OK | wx.ICON_ERROR)returnself.listview2.DeleteItem(selected)def on_refresh(self, event):self.listview3.DeleteAllItems()conn = sqlite3.connect(self.db_path)cursor = conn.cursor()cursor.execute('SELECT file_name, full_path, date_modified, remarks, valid FROM files')for row in cursor.fetchall():file_name, full_path, date_modified, remarks, valid = rowvalid_text = "Yes" if valid == 1 else "No"index = self.listview3.InsertItem(self.listview3.GetItemCount(), file_name)self.listview3.SetItem(index, 1, full_path)self.listview3.SetItem(index, 2, date_modified)self.listview3.SetItem(index, 3, remarks)self.listview3.SetItem(index, 4, valid_text)conn.close()def on_delete_db(self, event):selected = self.listview3.GetFirstSelected()if selected == -1:wx.MessageBox("Please select a database record to delete", "Error", wx.OK | wx.ICON_ERROR)returnfull_path = self.listview3.GetItem(selected, 1).GetText()conn = sqlite3.connect(self.db_path)cursor = conn.cursor()# cursor.execute('DELETE FROMcursor.execute('DELETE FROM files WHERE full_path = ?', (full_path,))conn.commit()conn.close()self.listview3.DeleteItem(selected)wx.MessageBox("Record deleted from the database.", "Info", wx.OK | wx.ICON_INFORMATION)def on_export_excel(self, event):if self.listview3.GetItemCount() == 0:wx.MessageBox("No data to export.", "Error", wx.OK | wx.ICON_ERROR)returnwith wx.FileDialog(self, "Save Excel file", wildcard="Excel files (*.xlsx)|*.xlsx",style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnpathname = fileDialog.GetPath()try:workbook = openpyxl.Workbook()sheet = workbook.activesheet.title = "Python Files"# Write headersheaders = ["File Name", "Full Path", "Date Modified", "Remarks", "Valid"]for col, header in enumerate(headers, start=1):sheet.cell(row=1, column=col, value=header)# Write datafor row in range(self.listview3.GetItemCount()):for col in range(self.listview3.GetColumnCount()):value = self.listview3.GetItem(row, col).GetText()sheet.cell(row=row+2, column=col+1, value=value)workbook.save(pathname)wx.MessageBox(f"Data exported to {pathname}", "Info", wx.OK | wx.ICON_INFORMATION)except Exception as e:wx.MessageBox(f"Failed to export data: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)class EditDialog(wx.Dialog):def __init__(self, parent, remarks, valid):super().__init__(parent, title="Edit Record", size=(350, 200))vbox = wx.BoxSizer(wx.VERTICAL)hbox1 = wx.BoxSizer(wx.HORIZONTAL)lbl1 = wx.StaticText(self, label="Remarks:")self.remarks_ctrl = wx.TextCtrl(self, value=remarks, style=wx.TE_MULTILINE)hbox1.Add(lbl1, flag=wx.ALL, border=5)hbox1.Add(self.remarks_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)hbox2 = wx.BoxSizer(wx.HORIZONTAL)lbl2 = wx.StaticText(self, label="Valid:")self.valid_checkbox = wx.CheckBox(self)self.valid_checkbox.SetValue(valid)hbox2.Add(lbl2, flag=wx.ALL, border=5)hbox2.Add(self.valid_checkbox, flag=wx.ALL, border=5)hbox3 = wx.BoxSizer(wx.HORIZONTAL)ok_btn = wx.Button(self, label="OK")ok_btn.Bind(wx.EVT_BUTTON, self.on_ok)cancel_btn = wx.Button(self, label="Cancel")cancel_btn.Bind(wx.EVT_BUTTON, self.on_cancel)hbox3.Add(ok_btn, flag=wx.ALL, border=5)hbox3.Add(cancel_btn, flag=wx.ALL, border=5)vbox.Add(hbox1, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)vbox.Add(hbox2, flag=wx.ALIGN_CENTER | wx.ALL, border=10)vbox.Add(hbox3, flag=wx.ALIGN_CENTER | wx.ALL, border=10)self.SetSizer(vbox)def on_ok(self, event):self.EndModal(wx.ID_OK)def on_cancel(self, event):self.EndModal(wx.ID_CANCEL)def get_values(self):remarks = self.remarks_ctrl.GetValue()valid = "Yes" if self.valid_checkbox.GetValue() else "No"return remarks, validclass MyApp(wx.App):def OnInit(self):frame = MyFrame()frame.Show()return Trueif __name__ == "__main__":app = MyApp(False)app.MainLoop()                       

应用概述

这个应用程序提供了一个图形用户界面,允许用户浏览文件系统,查看和管理Python源代码文件。它的主要功能包括:

  1. 扫描指定文件夹中的所有.py文件
  2. 在列表视图中显示文件信息
  3. 搜索文件
  4. 编辑文件备注和有效性标志
  5. 将文件信息保存到SQLite数据库
  6. 数据库中检索和显示文件信息
  7. 在Visual Studio Code中打开选定的文件
  8. 将文件信息导出到Excel

让我们深入了解这个应用的一些关键特性和它们的实现方式。

核心功能解析

1. 文件扫描和显示

应用程序使用Python的os模块来遍历指定文件夹及其子文件夹,查找所有的.py文件。文件信息(包括文件名、完整路径和修改日期)被收集并按最近修改日期排序,然后显示在一个wx.ListCtrl控件中。

python">def on_scan(self, event):folder_path = self.folder_picker.GetPath()if not folder_path:wx.MessageBox("Please select a folder.", "Error", wx.OK | wx.ICON_ERROR)returnself.listview1.DeleteAllItems()py_files = []for root, dirs, files in os.walk(folder_path):for file in files:if file.endswith(".py"):full_path = os.path.join(root, file)date_modified = os.path.getmtime(full_path)date_str = wx.DateTime.FromTimeT(int(date_modified)).FormatISOCombined()py_files.append((file, full_path, date_str, date_modified))# Sort files by date modified (most recent first)py_files.sort(key=lambda x: x[3], reverse=True)for file, full_path, date_str, _ in py_files:index = self.listview1.InsertItem(self.listview1.GetItemCount(), file)self.listview1.SetItem(index, 1, full_path)self.listview1.SetItem(index, 2, date_str)

2. 文件搜索

搜索功能允许用户在文件名或完整路径中查找匹配项。匹配的项目会被高亮显示,使用户能够快速定位所需的文件。

python">def search_in_listview(self, listview, search_term):for i in range(listview.GetItemCount()):item = listview.GetItem(i)if search_term in item.GetText().lower() or search_term in listview.GetItem(i, 1).GetText().lower():item.SetBackgroundColour(wx.YELLOW)listview.SetItem(item)listview.EnsureVisible(i)else:item.SetBackgroundColour(wx.WHITE)listview.SetItem(item)if not search_term:for i in range(listview.GetItemCount()):item = listview.GetItem(i)item.SetBackgroundColour(wx.WHITE)listview.SetItem(item)

3. 数据库集成

应用程序使用SQLite数据库来持久化文件信息。用户可以将文件信息保存到数据库,也可以从数据库中检索信息。这个功能特别有用,因为它允许用户在不同的会话中保留他们的文件管理状态。

python">def save_to_database(self, event):try:conn = sqlite3.connect(self.db_path)cursor = conn.cursor()# Ensure table existscursor.execute('''CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT,file_name TEXT,full_path TEXT,date_modified TEXT,remarks TEXT,valid INTEGER)''')# Append new records or update existing onesfor index in range(self.listview2.GetItemCount()):file_name = self.listview2.GetItemText(index)full_path = self.listview2.GetItem(index, 1).GetText()date_modified = self.listview2.GetItem(index, 2).GetText()remarks = self.listview2.GetItem(index, 3).GetText()valid = self.listview2.GetItem(index, 4).GetText()valid = 1 if valid == "Yes" else 0# Check if the record already existscursor.execute('SELECT * FROM files WHERE full_path = ?', (full_path,))if cursor.fetchone() is None:# If it doesn't exist, insert a new recordcursor.execute('INSERT INTO files (file_name, full_path, date_modified, remarks, valid) VALUES (?, ?, ?, ?, ?)',(file_name, full_path, date_modified, remarks, valid))else:# If it exists, update the existing recordcursor.execute('UPDATE files SET file_name = ?, date_modified = ?, remarks = ?, valid = ? WHERE full_path = ?',(file_name, date_modified, remarks, valid, full_path))conn.commit()except sqlite3.Error as e:wx.MessageBox(f"Database error: {e}", "Error", wx.OK | wx.ICON_ERROR)finally:conn.close()wx.MessageBox("Data saved to the database.", "Info", wx.OK | wx.ICON_INFORMATION)

4. 与Visual Studio Code集成

为了提高开发效率,应用程序允许用户直接在Visual Studio Code中打开选定的Python文件。这是通过使用Python的subprocess模块来启动VS Code实现的。

python">def open_in_vscode(self, listview):selected = listview.GetFirstSelected()if selected == -1:wx.MessageBox("Please select a file to open", "Error", wx.OK | wx.ICON_ERROR)returnfull_path = listview.GetItem(selected, 1).GetText()subprocess.Popen(["C:\\Users\\86182\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe", full_path])

5. 导出到Excel

为了方便数据共享和报告生成,应用程序提供了将文件信息导出到Excel的功能。这是使用openpyxl库实现的。

python">def on_export_excel(self, event):if self.listview3.GetItemCount() == 0:wx.MessageBox("No data to export.", "Error", wx.OK | wx.ICON_ERROR)returnwith wx.FileDialog(self, "Save Excel file", wildcard="Excel files (*.xlsx)|*.xlsx",style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnpathname = fileDialog.GetPath()try:workbook = openpyxl.Workbook()sheet = workbook.activesheet.title = "Python Files"# Write headersheaders = ["File Name", "Full Path", "Date Modified", "Remarks", "Valid"]for col, header in enumerate(headers, start=1):sheet.cell(row=1, column=col, value=header)# Write datafor row in range(self.listview3.GetItemCount()):for col in range(self.listview3.GetColumnCount()):value = self.listview3.GetItem(row, col).GetText()sheet.cell(row=row+2, column=col+1, value=value)workbook.save(pathname)wx.MessageBox(f"Data exported to {pathname}", "Info", wx.OK | wx.ICON_INFORMATION)except Exception as e:wx.MessageBox(f"Failed to export data: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)

效果如下

在这里插入图片描述

结论

这个Python文件管理器应用程序展示了如何使用Python和wxPython创建一个功能丰富的桌面应用。它不仅提供了基本的文件管理功能,还集成了数据库持久化、外部编辑器启动和数据导出等高级特性。


http://www.ppmy.cn/server/103637.html

相关文章

线程间通信的同步机制(ConcurrentQueue)

假设需要实现的功能: 创建两个线程,一个用来读取数据,一个用来更新数据。 使用 ConcurrentQueue 来存放读取到的数据,然后使用 TryTake 或者 TryDequeue 来判断队列是否有新数据,如果有则更新 UI。 private readonly…

数字图像处理【14】特征检测——Harris角点检测

在上一篇文章已经介绍了opencv特征检测中的一些必要的概念,介绍了什么是特征,什么是角点,这些角点特征可以做什么。今天来看看对于我们人来说很容易就识别到角点特征,对于计算机来说是如何识别的,具体的步嘴原理是怎样…

Linux 音媒体小项目练手

1.1 项目背景 该项目旨在开发一个基于 Mplayer 的视频播放器,支持加载指定路径下的音视频文件,并通过命令行界面进行播放控制。播放器支持顺序播放、随机播放、单曲循环等模式,用户可通过简单的按键操作进行视频播放的控制。 1.2 目标 支持…

408专业135|王道和二轮强化课的经验分享

408 进入第二轮复习阶段,主要任务是大量练习大题。 此时,不建议完整地观看强化课程,因为在第一轮复习中,你已经做了大量选择题,积累了丰富的经验,并且熟悉了题目的出题方式。然而,这并不意味着…

【python与java的区别-04(文件流)】

一、文件和目录的操作 1、IO流(Stream) 通过“流”的形式允许计算机程序使用相同的方式来访问不同的流入/流出源。Stream是从起源(source)到接收(sink)的有序数据。我们把输入/输出源对比成“水桶”,那么流就是“管道…

迈入退休生活,全职开发ue独立游戏上架steam

决定退休了。算了算睡后收入,也可以达到每月一万一,正好可以养家糊口。 既然退休了,那就做些想做的事情,别人养花养草,而我打算开发独立游戏上架steam。 一,盘点下目前的技术体系。 1,图形学底…

ctfshow之web29~web51

目录 web29 题解: web30 web31 web32(32~36) web33 web34 web35 web36 web37 web38 web39 web40 web41 web42 (42~51) web43 web44 web45 web50 web51 web29 前瞻知识: isset() …

大数据量实现滚动分页-vue3+element-plus实现方式

1.背景:分页是处理大数据量的一种常见方式,一般有页码分页、滚动分页的实现方式,表格页面分页非常常见,下面是一个列表或者表格的滚动分页。 2.话不多说,上代码: (1)解题思路&#x…