Python如何用TKinter搭建图形界面窗口,并通过多进程的方式调用功能函数

2023-05-16

用Python开发图形界面和程序时,经常会对图形界面的搭建感到失望,或许是由于对图形界面不熟悉的原因吧,总之一想到图形界面,就感觉会很费时、费力,编程的积极性大幅下降。最近,尝试用Tkinter创建了一个简便的图形界面,这个过程果然和原先想的不差多少,搭建窗口界面,调整位置布局,确实很费时费力,与其它可视化编程工具的差距实在太过悬殊。但是既然已经开始了,就尝试把这个界面做成一个简单的模板吧,以后如果遇到有类似的窗口应用需要开发,也好直接拿来就用,减少启动阻力。如果你也正好有这样的困惑,参考本文中的程序代码或许可以让你省点心力。

空谈无益,上图 show 代码:
TKinter图形界面简易窗口TKinter图形界面简易窗口

上面的图片是启动后的初始窗口界面,用于显示LOGO或者文字内容(序号1),这个窗口适合处理一些简单的功能,本案例中的功能设定是,往输入框(序号3)中输入一段文字,点击[开始](序号4),或按回车后,功能函数会根据 ', '对输入的文字内容进行分割并保存到列表框中,之后可以在展开的窗口界面中点击[处理选中内容],或者[处理全部内容]按钮,就可以调用多进程执行字数统计的函数。当然这里只是一个最简单的示例演示,你也完全可以用于处理更多的场景,比如说,你可以在输入框输入需要搜索的文字,或者需要下载的网址等内容。
输入框右侧的开始按钮(序号4)绑定了相应函数的调用,表示对这个内容进行处理; 如果这一个简单的窗口不能满足你的需求,还有更多的内容需要操作,可以点击旁边的红色小按钮(序号5),就可以展开这个窗口,展开后的内容如下图所示:
TKinter图形界面展开窗口TKinter图形界面展开窗口

输入框的下方,添加了一排功能按钮(序号6),可以设定调用不同的函数,以实现程序的相应功能,你可以通过复制源代码,重新设定变量名,等一些简单的操作,达到增加或者减少按钮的效果,也可以调整按钮的间距和字体等显示效果,使用起来会比重头开始搭建要方便不少。
功能按钮下方是一个显示详细内容的列表框(序号7),这个列表框也已经绑定了滚动条(序号8),这里可以用于显示正在处理的内容,比如说可以作为播放列表,显示即将播放的歌曲和状态,或者也可以作为下载列表,用于显示目前各内容的下载以及完成情况等,本文的末尾附有一个根据这个模板进行完善的Youtube视频下载程序,列表框中,各行内容的显示效果可以在程序中通过调整文字内容,以及设定不同的颜色加以完善。
接下来,在列表框的下方,也有一排操作按键(序号9)专门用于对列表框中的内容进行操作,比如说,选中,反向选择,删除等,本案例中已经设定了与相关列表框操作函数的调用,你可以通过简单的调整,就可以完成相应功能的设定。
最后,是状态栏(序号10),用于显示各个功能执行过程中的状态,完全可以通过非常容易的变量替换,再结合你的实际需要进行调整。
除此之外,本案例中还添加了键盘事件与功能函数的绑定,当焦点落在输入框的时候,按下control键会自动清空内容,可以更方便的让你在按下control+v 粘贴快捷键之前,不需要对输入框的内容进行删除操作 , 另外回车键也已经和开始按钮的功能联动,当你输入内容,并按下回车键的时候,会自动执行开始任务。

完整的代码如下:

"""
Title : TKinter Template with Thread and Multiprocessing
Author: Le Miaokai
Date  : 2022-10-21
Email : LeMiaokai@Gmail.com
"""

# 导入基本模块
import os, sys

# 调用tkinter模块
from tkinter import *
from tkinter import messagebox, filedialog 

# 调用多线程模块
from threading import Thread

# 调用多进程模块
from multiprocessing import Pool, freeze_support

# 调用ctypes模块,以便在运行时隐藏控制窗口,但是在启动的时候,会有控制框闪过。
# 如果用auto_py_to_exe  可完全解决起动时控制框闪过的问题。
import ctypes
# 运行程序的时候,隐藏控制窗口
whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 0)
    ctypes.windll.kernel32.CloseHandle(whnd)


#  通过多线程添加内容到列表框中
def put_item_to_list(event=''):
	# 启用多线程,将内容添加到列表中
    t_1 = Thread(target=append_to_list)
    t_1.start()
	
	# 只要调用了添加到列表中的功能,就将窗口放大。
    root.geometry('900x550')
    more_BT["text"]=' ^ '

# 添加内容到列表中
def append_to_list():
	text = input_text.get()
	if len(text) == 0:
		messagebox.showinfo("提示:", "请检查输入框中的内容,多个信息请以 ,分隔!")
	else:
		# 将输入的内容,去除空格后,以 , 进行分割,并存入到列表中。
		text = text.strip().replace(',', ',').split(',')

	# 循环添加内容到列表框
	for item_id, item in enumerate(text):
		add_link_to_listbox(item_id, item)
	
	# 添加内容完成后恢复窗口中的按钮状态
	button_state(state = "normal")		

# 添加单个项目到listbox中
def add_link_to_listbox(item_id, item):
	global g_ytlink_dict

	# 本案例中item_id对应列表框中的序号,作为索引
	item_id = list_box.size()

	# 如果索引内容已经添加,则在状态栏显示,当前item的状态参数,
	if item_id in g_info_dict and g_info_dict[item_id]!=[]:
		status_info["text"] = f"| {g_info_dict[item_id][3]}"
	else:
		# item_id, 作为内容的索引号, 每个索引号对应的内容为 [列表框中的显示位置序号,项目内容,是否已经完成,以及当前状态] 等
		g_info_dict[item_id] = [list_box.size(), item, False, '']

		# 将当前信息,添加到列表框中, 输出的序号,需要 list_box.size() + 1, 未尾添加可以直接用END
		list_box.insert(END, f"{str(list_box.size()+1).zfill(3)} . {item}")


# 回调函数,返回结果, 在用多进程任务完成后,自动调用本函数
def collectMyResult(result):
	global g_info_dict, g_count
	item_id = result[1]
	# 显示多进程中已经完成任务所返回的结果信息
	if result[0] == True:
		# 处理成功后,更新状态:
		g_info_dict[item_id][2] = True
		g_info_dict[item_id][3] = '处理完成,总字数为{}个。'.format(result[2])
		# 处理完成后,变更列表框中的状态
		tasks_status(item_id)

	else:
		g_info_dict[item_id][3] = "处理失败!"
		tasks_status(item_id)

	# 在状态样栏中显示目前已经处理完成的计数
	g_count += 1
	status_info["text"] = f"|总计完成数量 : {g_count}"

# 处理全部列表框中的内容
def threading_all_tasks():
	# 先全部选中
	select_all()
	# 调用处理选中内容的函数
	threading_tasks()

# 设定并启用进程池处理需要执行的任务
def threading_tasks():
	# 调用处理列表中选中内容的函数,需要创建一个多线程,否则窗口会无响应
	v_l = Thread(target=multiprocess_pool)
	v_l.start()

# 设定函数,通过多进程池,分配添加多进程任务
def multiprocess_pool():
	global g_info_dict

	list_selected = list_box.curselection()
	# 如果没有内容被选中,则显示提示框
	if len(list_selected)==0:
		messagebox.showinfo("提示:", "请选择需要处理的任务 !")
	else:
		# 定义多进程池,默认为CPU的核数, 也可以在括号中输入指定的数量,比如同时启用6个进程
		pool = Pool()  #Pool(6)
		# 设定循环范围为列表框中已经选择的内容
		for curr_id in list_selected:
			# 如果信息字典中的处理标志为True,则提示该内容已经处理完成
			if g_info_dict.get(curr_id)[2]:
				# 在状态栏显示当前状态
				status_info["text"] = f"| {g_info_dict[curr_id][3]}"   
			else:
				item = g_info_dict[curr_id][1]
				g_info_dict[curr_id][3] = "正在处理......"
				# 设定列表中的显示状态, status将由g_info_dict中的状态信息替代
				tasks_status(curr_id)
				# 添加多进程的参数,多个参数用 ,分隔
				save_args = [curr_id, item]
				pool.apply_async(multiprocess_task, args=save_args, callback=collectMyResult)

		# 关闭进程池,并等待进程执行完成
		pool.close()
		pool.join()

	# 处理完成后恢复窗口中的按钮状态
	button_state(state = "normal")
	# messagebox.showinfo("提示", "已经成功处理!")

# 设定多进程任务,也就是通过进程池调用的任务
def multiprocess_task(item_id, item):
	result = 0
	try:
		# 假设任务为统计当前内容的字数,
		result = len(item)

		return [True,  item_id, result]
	except:
		return [False, item_id, result]


# 通过status 来设置并显示,当前的程序进展状态
def tasks_status(item_id):
	global g_info_dict
	if item_id=='':
		status_info["text"] = f"| 请检查当前内容 ! "
	else:
		# 根据item_id获取当前列表框中的序号id
		curr_id = g_info_dict[item_id][0]
		# 根据item_id获取当前文件的标题
		title   = g_info_dict[item_id][1]	
		# 根据item_id获取当前的处理状态
		status  = g_info_dict[item_id][3]

		# 更新状态,先删除当前行,再添加更新后的内容
		list_box.delete(curr_id)
		# 如果状态为空,则不显示状态情况,否则显示当前状态
		if status =='':
			list_box.insert(curr_id, f"{str(curr_id+1).zfill(3)} . {title}")
		else:
			list_box.insert(curr_id, f"{str(curr_id+1).zfill(3)} . {title} | {status}")

		# 根据序号和状态信息,更新列表框中的显示内容,设定当前行的颜色
		list_box_color_set(curr_id, status)

		# 在状态栏显示,当前的状态信息
		status_info["text"] = f"|{status}"


# 点击“开始”按钮或者回车确认后,将内容添加到列表框中。
def d_threading(event=''):
	# 开始之后,先将内容添加到列表框中。
	put_item_to_list()


# 弹出目录选择框
def choose_savepath():
    global download_Path
    download_Directory = filedialog.askdirectory(initialdir=download_Path.get(), title="Select Save Folder")
	# 设置选中的目录位置,如果没有选择,则保持原样
    if download_Directory =='':
        pass
    else:
        download_Path.set(download_Directory)


# 删除列表中的全部内容
def clean_listbox():
	global g_info_dict, g_count
	list_box.delete(0, 'end')
	# 清空链接字典
	g_info_dict  ={}

	# 在状态样栏中显示目前已经完成的数量
	status_info["text"] = f"|Downloaded Count : {g_count}"

	download_video_BT.config(state=DISABLED)
	download_audio_BT.config(state=DISABLED)


# 选中列表中的全部
def select_all():
	# 选中全部列表中的内容
	list_box.select_set(0,END)


# 清空所有选中的项目
def select_none():
	# 清空选中的列表中的内容
	list_box.selection_clear(0,END)


# 对列表中的内容进行反向选择
def list_box_inverse():
	# 先将当前选中的内容保存
	selected_list  = list_box.curselection()
	# 选择全部列表
	select_all()
	# 将之前选中过的内容清空
	for i in selected_list:
		list_box.selection_clear(i,i)

# 删除选中的项目
def delete_selected():
	global g_info_dict
	select_list = list(list_box.curselection())
	# 为了避免删除后序号的重复,这里需要反向删除,也就是从后往前删除
	select_list.sort(reverse=True)
	for curr_id in select_list:
		# 删除列表框中的信息
		list_box.delete(curr_id)
		# 删除字典中的链接信息。
		if curr_id in g_info_dict:
			del g_info_dict[curr_id]

	# 删除后,对列表中的内容重新排序号		
	list_box_sort()

	# 在状态样栏中显示目前已经完成的数量
	status_info["text"] = f"|Downloaded Count : {g_count}"	


# 删除已经完成的项目
def delete_finished():
	global g_info_dict
	# 获取列表框中的所有内容的总数
	list_size = list_box.size()

	# 对每一行的内容按反向顺序进行排列,并更新序号, 从总数量开始,每次-1, 到0为止, 所以需要设定为-1.
	for curr_id in range(list_size-1, -1,-1):
		item_id = get_listbox_id(curr_id)
		# 如果是已经完成的内容,则删除
		if g_info_dict.get(item_id)[2]:
			# 删除列表中的相应内容
			list_box.delete(item_id)
			del g_info_dict[item_id]
		else:
			pass

	# 删除后,对列表中的内容重新排序, 同时删除字典中已经清空的内容
	list_box_sort()
	# 在状态样栏中显示目前已经完成的数量
	status_info["text"] = f"|总完成数 : {g_count}"	


# 设置列表框中第i行信息内容的显示颜色
def list_box_color_set(i,status):
	if "完成" in status:
		list_box.itemconfigure(i, background="yellowgreen", fg="white")
	elif "正在处理" in status:
		list_box.itemconfigure(i, background="greenyellow")
	elif "失败" in status:
		list_box.itemconfigure(i, background="red", fg="white")


# 根据id序号,获取列表框中,当前id号项目的文字内容
def get_listbox_title(curr_id):
	title = list_box.get(curr_id)
	if '|' in title:
		# 获取标题内容的时候,要注意|的前面有个空格,否则会出现字典关键字无法读取的问题。
		title = title[title.find('.')+2:title.rfind(' |')]
	else:
		title = title[title.find('.')+2:]
	return title


# 根据序号,获取列表框中,当前行因列表内容删减而改变了位置,通过文字获取原来的id号
def get_listbox_id(curr_id):
	title = list_box.get(curr_id)
	item_id = int(title[:title.find(' .')]) - 1
	return item_id


# 对列表中的序号进行重新排序号
def list_box_sort():
	global g_info_dict

	# 获取列表框中的所有内容的总数
	list_size = list_box.size()

	# 对每一行的内容按顺序进行排列,并更新序号
	for curr_id in range(list_size):
		item_id = get_listbox_id(curr_id)
		# 更新状态, 如果当前序号与字典中的序号一致,则变更序号,否则重新生成新的字典内容,并删除当前字典中的内容
		if curr_id == item_id:
			g_info_dict[curr_id][0]=curr_id
		else:
			g_info_dict[curr_id] = g_info_dict[item_id]
			g_info_dict[curr_id][0]=curr_id
			del g_info_dict[item_id]
		
		tasks_status(curr_id)
		# 根据状态值,设置列表框中第 i 行的信息内容显示颜色
		list_box_color_set(curr_id, g_info_dict[curr_id][3])


# 设置按钮状态
def button_state(state = "disabled"):
	download_video_BT.config(state=state)
	download_audio_BT.config(state=state)
	get_videos_BT.config(state=state)
	clean_list_BT.config(state=state)


# 设置窗口尺寸
def root_size():
	if root.winfo_height() >230 :
		root.geometry('900x230')
		more_BT["text"]='...'
	else:
		root.geometry('900x550')
		more_BT["text"]=' ^ '


# 创建窗口
root = Tk()

# 设置窗口尺寸,标题以及颜色等相关信息
root.geometry('900x230')
root.title(" TKinter Template ")
bg_color='snow'#'lemon chiffon' #"white"  #"whitesmoke"  # "floralwhite"
fg_color="red"
root.configure(background=bg_color)

# 全局变量设定:
# 获取当前程序所在的目录,
g_curr_path = os.path.dirname(os.path.realpath(sys.argv[0]))

# download_path 用于存储保存路径,
download_Path = StringVar() 
download_Path.set(g_curr_path)


# 全局变量,链接字典,保存具体链接对应的内容,对应内容是字典格式,包括列表框中的序号,标题,是否已经处理,以及状态等
g_info_dict = {}

# 初始化任务完成数量统计变量
g_count = 0

# 根据 auto-py-to-exe 对添加图片文件的说明, 设定图片文件的目录, 引用自,以下URL:
# https://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile/7675014#7675014
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
		# 会在程序运行的时候建立一个临时目录,用于存放内容
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

# LOGO处的图片文件,相对路径
logo_path = resource_path("logo.png")  

if os.path.exists(logo_path):
	# 如果LOGO图片存在,则显示图片,
	photo=PhotoImage(file=logo_path)
	Label(root, image=photo, bg=bg_color).pack(padx=0, pady=10)
else:
	# 否则就显示文字
	Label(root, text="TKinter Template", font="Calibri 45 bold", bg=bg_color, fg="red").pack(padx=0, pady=38)

# 添加窗口中组件:

# 添加输入框
inputframe = Frame(root, bg=bg_color)
inputframe.pack(pady=0)

# 添加提示标签
Label(inputframe, text="请输入内容 :", font="Calibri 13 bold", bg=bg_color, fg=fg_color).pack(side = LEFT)

url_entry = StringVar() 
url_entry.set(r"如有多个内容请以','进行分隔,按回车键或者开始按钮,将启动每行内容的字数统计演示!")

# 清空输入框中的内容
def clean_url_entry(event=''):
	url_entry.set('')


# 添加输入框
input_text = Entry(inputframe, textvariable = url_entry, width=88, font="Calibri 11", bg="greenyellow")
input_text.bind("<Return>", d_threading)
input_text.bind("<Control_L>", clean_url_entry)
input_text.pack(side = LEFT, padx=3, pady=8)

# 设定程序起动后的焦点为输入框
input_text.focus_set()

# 添加开始按钮,并指定调用的功能函数
download_BT = Button(inputframe, text="开始", font="Calibri 11 bold", command=d_threading, bg=bg_color, fg=fg_color)
download_BT.pack(side = LEFT, padx=3, pady=8)

more_BT = Button(inputframe, text="...", font="Calibri 11 bold", command=root_size, bg="red")
more_BT.pack(side = LEFT, padx=5, pady=8)

# 添加按钮框
buttonframe = Frame(root,bg=bg_color)
buttonframe.pack(pady=8)

# 添加内容到列表框中
get_videos_BT = Button(buttonframe, text="添加到列表框", command=put_item_to_list, bg="greenyellow", font="Arial 10 bold")
get_videos_BT.pack(side = LEFT, padx=15, pady=8)


# 处理选中内容
download_video_BT = Button(buttonframe, text="处理选中内容", command=threading_tasks, state=DISABLED, bg="greenyellow", font="Arial 10 bold")
download_video_BT.pack(side = LEFT, padx=15, pady=8)

# 处理全部内容
download_audio_BT = Button(buttonframe, text="处理全部内容", command=threading_all_tasks, state=DISABLED, bg="greenyellow", font="Arial 10 bold")
download_audio_BT.pack(side = LEFT, padx=12, pady=8)


# 选择目录
save_path_BT = Button(buttonframe, text="选择目录", command=choose_savepath, bg="greenyellow", font="Arial 10 bold")
save_path_BT.pack(side = LEFT, padx=15, pady=8)

# 状态栏设定
statusframe = Frame(root, bd =1 ,relief = SUNKEN,bg=bg_color)
statusframe.pack(side = BOTTOM, fill = X)

status_label = Label(statusframe, text='保存位置 >>>', anchor =W, bg=bg_color, font="Calibri 11 bold")
status_label.pack(side = LEFT)

status_savepath = Label(statusframe, textvariable = download_Path, anchor =W, bg=bg_color, font="Calibri 11 bold")
status_savepath.pack(side = LEFT, fill = X)
status_info = Label(statusframe, text='|Author Email: LeMiaokai@gmail.com', anchor =W, bg=bg_color, font="Calibri 11 bold")
status_info.pack(side = RIGHT)

# 滚动条和列表框设定
listboxframe = Frame(root, bg=bg_color,bd =1)
listboxframe.pack(expand=YES, fill=BOTH, padx=2, pady=2)

scrollbar = Scrollbar(listboxframe, bg=bg_color)
scrollbar.pack(side=RIGHT, fill=BOTH)
list_box = Listbox(listboxframe, selectmode="multiple", font="Arial 11", bg=bg_color)
list_box.pack(expand=YES, fill="both")
list_box.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=list_box.yview)


# 删除列表中的内容
clean_list_BT = Button(listboxframe, text="删除全部", 	command=clean_listbox,  	background="red", fg="white", font="Arial 10 bold")
clean_list_BT.pack(side = RIGHT, padx=5, pady=8)

# 删除已经完成的内容
select_all_BT = Button(listboxframe, text="删除已完成", command=delete_finished,  	background="red", fg="white", font="Arial 10 bold")
select_all_BT.pack(side = RIGHT, padx=5, pady=8)

# 删除选中的内容
select_all_BT = Button(listboxframe, text="删除已选中", command=delete_selected,  	background="red", fg="white", font="Arial 10 bold")
select_all_BT.pack(side = RIGHT, padx=5, pady=8)

# 反向选择
sort_list_BT = Button(listboxframe, text="反向选择",command=list_box_inverse,  	background="red", fg="white", font="Arial 10 bold")
sort_list_BT.pack(side = RIGHT, padx=5, pady=8)

# 全部不选
select_all_BT = Button(listboxframe, text="全部不选",	command=select_none,  		background="red", fg="white", font="Arial 10 bold")
select_all_BT.pack(side = RIGHT, padx=5, pady=8)

# 全部选中
select_all_BT = Button(listboxframe, text="全部选中", 	command=select_all,  		background="red", fg="white", font="Arial 10 bold")
select_all_BT.pack(side = RIGHT, padx=5, pady=8)


	
def main():
	# 打开TK窗口显示
	root.mainloop()

if __name__ == '__main__':
	# 多进程运行需要此函数支持。
    freeze_support()
    main()

"""
Reference:
# 更多关于TKinter的内容,详见以下参考内容
TKinter:https://www.runoob.com/python/python-gui-tkinter.html
"""

以上代码中也包含了程序启动后,关于如何隐藏控制窗口的说明,如果你还需要了解如何更方便的将python打包成Exe文件,可以参考我之前写过的文章 用 auto-py-to-exe 将 python 代码打包为exe可执行文件过程中的遇到的问题及解决方案。如果有兴趣更进一步的了解这个窗口界面的实际案例, 可以下载下图所展示的应用程序,这个程序是在上述这个窗口界面的基础上进一步完善功能后,编译而成的一款多进程YouTube视频下载工具,仅供参考学习之用:
YouTube Downloader 视频下载工具
以上就是关于Python如何用TKinter搭建图形界面窗口,并通过多进程的方式调用功能函数的全部内容,希望对你有所启发,如有不足之处请指出,大家共同学习,谢谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python如何用TKinter搭建图形界面窗口,并通过多进程的方式调用功能函数 的相关文章

  • HTML复选框--checkbox

    在公司实际开发中 xff0c 会经常遇到复选框全选 多选 统计选中个数的情况 xff0c 所以总结研究了一些大神的帖子 xff0c 汇总学习一下 xff01 1 统计被选中复选框的个数 2 点击复选框 xff0c 执行对应函数 3 获取复选
  • 在Ubuntu14.04不能添加PPA源到apt源的问题解决方法

    在Ubuntu14 04使用apt get 更新Git 时 xff0c 需要更新apt源 xff0c 添加一个带有最新Git的源 xff0c 如下命令 xff1a sudo add apt repository ppa git core p
  • android 12 framework开发第53节-Activity的reLaunch及onConfigurationChanged android源码分析

    hi xff0c 同学们大家好 xff01 1 Configuration应用开发背景 今天要给大家分享内容就是我们应用开发时候经常会遇到问题 xff0c 那就是如果系统一些属性变化了 xff0c 比如语言 xff0c 横竖屏幕 xff0c
  • QT 线程,实现生产者-消费者模式

    一 两种启动线程方式 xff1a 1 QThread 2 QObject moveToThread 函数 可以让 调用者的 槽中的代码 xff0c 在单独的线程执行 注 xff1a 如果该对象有 父对象 xff0c 那么它无法被移动 二 线
  • 【easyui学习笔记】3.easyui布局之边框布局

    学习参考 xff1a EasyUI 为网页创建边框布局 建设稍微实用点的界面都离不开布局 xff08 layout xff09 xff0c 我们先来了解最简单的一种布局 xff1a 边框布局 xff08 border layout xff0
  • Android的四种启动模式以及onNewIntent方法

    前言 想起来写这个是因为之前在开发过程中遇到在onStart 方法中使用getIntent 方法无法获取到启动activity时传入的数据 xff0c 也是纳闷了很久 xff0c 然后就决定好好看一下这个地方 xff0c 本文章会结合简单的
  • selenium webdriver 页面css和xpath定位

    对于html来说 xff0c 不管用什么浏览器打开 xff0c 他的架构是不变的 xff0c 所以对于编写自动化测试程序来说 xff0c 基于什么浏览器开发 xff0c 差异不大 xff0c 所以这里推荐使用chrome 65或以后版本浏览
  • Ubuntu 18.04 +Nvidia gtx 1650 显卡驱动安装

    1 Adding this PPA to your system You can update your system with unsupported packages from this untrusted PPA by adding
  • 详解https请求Nginx转发tomcat变成http问题

    概述 分享一个最近处理的nginx转发问题 xff0c 简单记录下 一 问题现象 简单架构为nginx做负载均衡 xff0c 后端用tomcat做容器 浏览器和 Nginx 之间走的 HTTPS 通讯 xff0c 而 Nginx 到 Tom
  • Zookeeper启动出现闪退问题解决

    1 检查环境变量是否配置了JAVA HOME xff0c 若是没有配置 xff0c 需配置才可以 xff08 由于zkEnv cmd文件中使用了JAVA HOME xff09 2 打开zkEnv cmd文件 xff0c 加上pause xf
  • WIN10下全新的部署和映像处理工具DISM

    DISM xff08 Deployment Image Servicing and Management xff09 就是部署映像服务和管理 DISM exe 用于安装 卸载 配置和更新脱机 Windows R 映像和脱机 Windows
  • 富文本显示不全自动省略

    使用富文本时 xff0c 文字一行 xff08 n行 xff09 显示不全 xff0c 末尾文字省略 简介 CGSize maxSize 61 CGSizeMake MAX MAXFLOAT 调整行间距 NSMutableParagraph
  • 普通用户安装管理Keepalived

    普通用户安装管理Keepalived 介绍安装授权给普通用户修改配置文件keepalived 配置检测脚本配置普通用户启动keepalived 介绍 负载均衡 Load Balance xff0c 简称LB 是一种服务或基于硬件设备等实现的
  • Arch Linux 安装小记

    Arch Linux 安装小记 这只是一篇随笔 xff0c 用来记录从全新安装 Arch Linux 开始 xff0c 到在使用过程中各种软件配置的过程 其实对于 Arch Linux 这样滚动更新的 Linux xff0c 很少需要重新安
  • Java Collections的min和max方法

    方法一 public static lt T extends Object amp Comparable lt super T gt gt T min Collection lt extends T gt coll 此方法需要传入一个实现了
  • 【高效工作】Sublime Text 3 美化

    参考 xff1a 炫酷的sublime text3主题 准备一个良好的工作环境会让人更加乐于工作 xff0c 现代的程序猿都有一颗geek的心 xff0c 谁能忍受整天在一个丑陋的UI下coding xff1f xff01 所以今天就简单介
  • oom killer &lmkd killer

    目录 oom killer amp reaper task 进程内存回收 杀进程内存回收 lmkd killer psi vmpressure 事件通知 内核psi 实现 内核vmpressure oom killer amp reaper
  • O 上新增 TaskSnapshot

    任务快照 https source android google cn devices tech perf task snapshots examples and source android P https developer andro
  • 2021.08.29_Android_设备配置改变和Activity处理

    Android设备那些配置会改变 xff1f 34 mcc 34 IMSI 移动国家 地区代码 MCC 发生了变化 检测到了 SIM 并更新了 MCC 34 mnc 34 IMSI 移动网络代码 MNC 发生了变化 检测到了 SIM 并更新
  • arcolinux使用i3wm窗口管理器

    arcolinux使用i3wm窗口管理器 i3wm手册 安装i3 一条命令 sudo pacman S i3 然后在arcolinux里面自己选择窗口管理器 arcolinux的文件管理器默认是 dolphin Dolphin使用就是直接

随机推荐

  • 我的 archinstall 使用手册

    我的 archinstall 使用手册 1 使用放大字体 xff0c 保护你的眼睛 archlinux 里面 tty 默认的字体是非常小的 setfont usr share kbd consolefont LatGrkCyr 12x22
  • Spring配置详解

    Spring 配置详解 1 配置bean元素 基本属性 lt 配置bean元素 name xff1a 给对象起个名字 class 类的完整路径 id 唯一 里面不初选特殊字符 struts sadfAction gt lt bean nam
  • 企业微信公众账号自定义应用模块中撤回历史消息的方法

    企业微信 xff0c 公众账号自定义应用模块中撤回历史消息的方法 注意 xff1a 此方法适用于撤回超过24小时的历史消息 下载这个工具 xff1a postman xff1a http www downza cn soft 205171
  • windows的BAT或者linux的VI下批量更改替换文件名的脚本

    windows 的BAT 或者linux 的VI 下批量更改替换文件名的脚本 本来离开写脚本有些日子了 xff0c 倒是现在有些文件处理或者EXCEL 工作簿要处理的话 xff0c 还是会用简化流程来处理 脚本函数则帮我解决了很多麻烦事 昨
  • 室内定位技术及机场方案建议

    室内定位技术发展现状 在1996年左右 xff0c 美国联邦通信委员会 xff08 FCC xff09 要求移动运营商为移动电话用户提供E 911 xff08 紧急救援 xff09 服务 1999年 xff0c FCC又对定位精度做出新的要
  • 如何让ActiveXObject( "Microsoft.XmlDom ")对象在非IE浏览器下显示数据?firefox(火狐)

    在IE浏览器下 xff0c xmlDom对象一般这样被定义 xff1a var xmlDom 61 new ActiveXObject 34 Microsoft XMLDOM 34 为了兼容Firefox xff0c 需要修改为 xff1a
  • 【easyui学习笔记】4.动态添加标签页

    参考 xff1a EasyUI 动态添加标签页 xff08 Tabs xff09 1 静态添加标签页 xff08 tabs xff09 静态添加标签页十分简单 xff0c 使用class属性为easyui tabs的div即可 xff0c
  • BIM+GIS建设与运维管理工作建议

    背景 xff1a BIM 43 GIS项目的建设意见 xff0c 就弱电的建设和运维方向提出相关需求 xff1b 在BIM模型建设时期 xff0c 面向弱电专业的建设建议 参考行业规范 xff1a 在机场工程项目的建设阶段 xff0c 各参
  • 修改svn默认端口

    Subversion有两种不同的配置方式 xff0c 一种基于它自带的轻量级服务器svnserve xff0c 一种基于非常流行的Web服务器Apache 根据不同的配置方式 xff0c Subversion使用不同的端口对外提供服务 基于
  • 项目、系统开发中的需求分析说明书和需求规格说明书的区别

    项目组成员在针对要开发的系统做需求调研后 xff0c 就要编写对应的需求说明书 作为软件工程师 xff0c 你就得知道需求分析说明书和需求规格说明书的区别 xff0c 以期在正确的时候编写正确的需求文档 两者有何不同 xff1a xff08
  • C/C++内存管理详解[转载]

    我觉得这是一篇很不错的文章 xff0c 对C和C 43 43 的程序员来说 xff0c 很有实用价值 xff0c 故推荐给大家 作者 xff1a PingPong 文档来源 xff1a CSDN 伟大的Bill Gates 曾经失言 xff
  • 项目启动会应该注意的几点

    摘要 xff1a 开个好头 xff0c 万事不难 项目启动会作为项目建设生命周期的开始 xff0c 其意义和难度不言而喻 作为项目管理办公室的负责人 xff0c 需要特别重视项目启动会的召开 xff0c 杜绝走过场 xff0c 避免虽然知道
  • 飞机的航班代码/航班号码的编号规则

    以下内容来源于网络 xff0c 并整理而得 一 国内航班 中国国内航班号的编号规则 xff1a 航空公司的两字代码 43 4位数字 其中 xff0c 后面四位数字的第一位代表航空公司的基地所在地区 第二位代表航班基地外终点所在地区 xff0
  • 机场生产运行数据统计指标-第四篇-机场运行保障类

    机场运行保障类 1 民航航班正常统计 1 1 统计说明 xff08 1 xff09 统计范围的相关说明 xff1a 1 民航航班正常统计范围 xff1a 国内外运输航空公司执行的客货运航班 xff0c 包括正班 加班 包机 港澳台地区及国际
  • Python入门学习--环境配置

    工作将近两年了 xff0c 做过B S结构的项目 xff0c 也做过android xff0c 也做过C S结构的项目 xff0c 相信无论是那种项目都是基于Java 学习运用Java也已经好多年了 xff0c 虽然也接触过C C 43 4
  • Python入门学习-数据类型

    一 类型的概念 首先 xff0c 对于一个数据1011100 xff0c 改怎么解释呢 xff1f 同Java等变成语言类型 xff0c 首先我们要明确数据的类型 xff0c 程序设计语言不允许语法歧义 xff0c 因此需要明确数据的类型
  • 流年似水 启航2019

    凌晨1点无意间看到一个演讲视频 感谢你给我机会上场 xff0c 很久之前的一个演讲视频 xff0c 看完除了羡慕还是羡慕吧 xff0c 也许就是一句话吧 xff0c 开挂的人生不需要解释 30多年的生活他做了很多事 xff0c 也做成了很多
  • 使用Python代码下载网易音乐歌曲

    刚刚写了一堆 xff0c 最终放弃了 xff0c 后来百度查找到一个接口 xff0c http music 163 com song media outer url id 61 这里填歌曲id mp3 这个URL就可以下载了 xff0c 现
  • Spring是如何管理Bean

    常常听老师说容器 xff0c 容器是什么 xff1f spring中是如何体现的 xff1f 一直有疑惑 xff0c 这两天看了一下Spring管理bean的Demo xff0c 对于Spring中的容器有了简单的认识 我们知道 xff0c
  • Python如何用TKinter搭建图形界面窗口,并通过多进程的方式调用功能函数

    用Python开发图形界面和程序时 xff0c 经常会对图形界面的搭建感到失望 xff0c 或许是由于对图形界面不熟悉的原因吧 xff0c 总之一想到图形界面 xff0c 就感觉会很费时 费力 xff0c 编程的积极性大幅下降 最近 xff