tkinter实现可视化的公主连结脚本
简介
该作品主要使用tkinter以及airtest实现。之后也可以使用pyinstaller进行打包
在输入框输入地址,后可以点击更改位置修改相应选项的位置。
按键盘q键可以控制血脉功能的开关状态(血脉是其他游戏的功能),切换到关于页面时停止。
其它的按钮都是一些功能函数。可以看这篇文章了解airtest为游戏脚本多增加点功能。文章地址
更改地址
按q时
1.function_test.py
import threading # 导入threading库,用于多线程操作
from tkinter import messagebox # 导入tkinter库的messagebox模块,用于显示消息框
import airtest # 导入airtest库,用于UI自动化测试
import os # 导入os库,用于操作操作系统功能
from airtest.core.api import connect_device, exists, touch, sleep, wait # 导入airtest库的API
import json # 导入json库,用于处理JSON数据
import asyncio # 导入asyncio库,用于异步操作
from airtest.core.cv import Template # 导入airtest库的Template模块,用于图像识别
import keyboard # 导入keyboard库,用于监听键盘输入
import pyautogui # 导入pyautogui库,用于模拟鼠标和键盘操作
class Open_And_Connect:
def __init__(self):
with open('Data/local_url.txt', mode='r', encoding='utf-8') as a:
text_local_url = a.read()
with open('Data/andorid_url.txt', mode='r', encoding='utf-8') as a:
text_local_andorid = a.read()
self.local_url = text_local_url
self.android_url = text_local_andorid
self.xuemaibool = True # 控制血脉的状态变量
self.control = True # 控制状态的变量
def star_Android(self):
os.startfile(self.local_url) # 启动本地应用程序
def connect(self):
try:
connect_device(self.android_url) # 连接到Android设备
print("连接成功")
messagebox.showwarning(title='连接成功', message='连接成功')
except:
messagebox.showwarning(title='警告', message='连接失败,请检查模拟器是否启动后再次尝试')
def connect_game_Princes_Connect(self):
try:
connect_device(self.android_url) # 连接到Android设备
print("连接成功")
except:
self.connect_game_Princes_Connect()
def threading_connect(self):
tc = threading.Thread(target=self.connect)
tc.start()
def connect_game(self):
try:
connect_device("Windows:///?title_re=寻道大千.*") # 连接到游戏窗口
print("连接成功")
except:
messagebox.showwarning(title='警告', message='连接失败,请检查是否启动后再次尝试')
def xuemai(self):
if (exists(Template(r"tpl1692694128579.png", record_pos=(-0.004, 0.639), resolution=(450, 855)))):
if self.control:
touch(Template(r"tpl1692694128579.png", record_pos=(-0.004, 0.639), resolution=(450, 855)))
sleep(1)
if (exists(Template(r"tpl1692694226482.png", record_pos=(-0.247, 0.632), resolution=(450, 855)))):
if self.control:
touch(Template(r"tpl1692694226482.png", record_pos=(-0.247, 0.632), resolution=(450, 855)))
self.xuemai()
def control_xuemai(self):
keyboard.wait('q') # 等待键盘输入 "q"
if self.xuemaibool:
if self.control == True:
self.control = False
messagebox.showwarning(title='切换状态成功', message='目前状态是关闭')
else:
self.control = True
messagebox.showwarning(title='切换状态成功', message='目前状态是开启')
print(self.control)
self.control_xuemai()
def threading_control_xuemai(self):
thread_1 = threading.Thread(target=self.control_xuemai)
thread_1.start()
def threading_main_xuemai(self):
self.connect_game()
thread = threading.Thread(target=self.xuemai)
thread.start()
# 公主连结脚本
# 1.启动公主连结
def start_game_1(self):
if (exists(Template(r"Data/start_game_img/tpl1693030408591.png", record_pos=(0.17, 0.011), resolution=(960, 540)))):
touch(Template(r"Data/start_game_img/tpl1693030408591.png", record_pos=(0.17, 0.011), resolution=(960, 540)))
else:
self.start_game_1()
def start_game_2(self):
if (exists(Template(r"Data/start_game_img/tpl1693030458455.png", record_pos=(-0.428, 0.245), resolution=(960, 540)))):
touch([476, 494])
else:
self.start_game_2()
def start_game_3(self):
if (exists(Template(r"Data/start_game_img/tpl1693030544615.png", record_pos=(0.114, 0.105), resolution=(960, 540)))):
touch(Template(r"Data/start_game_img/tpl1693030544615.png", record_pos=(0.114, 0.105), resolution=(960, 540)))
if (exists(Template(r"Data/start_game_img/tpl1693030618263.png", record_pos=(0.45, -0.246), resolution=(960, 540)))):
touch(Template(r"Data/start_game_img/tpl1693030618263.png", record_pos=(0.45, -0.246), resolution=(960, 540)))
if (exists(Template(r"Data/start_game_img/tpl1693030994223.png", record_pos=(0.0, 0.221), resolution=(960, 540)))):
pass
elif (exists(Template(r"Data/start_game_img/tpl1693030903641.png", record_pos=(-0.411, -0.214), resolution=(960, 540)))):
pass
else:
self.start_game_3()
def start_game_4(self):
if (exists(Template(r"Data/start_game_img/tpl1693030903641.png", record_pos=(-0.411, -0.214),
resolution=(960, 540)))):
touch([781, 299])
touch(
Template(r"Data/start_game_img/tpl1693030938126.png", record_pos=(0.377, 0.231), resolution=(960, 540)))
if (
exists(Template(r"Data/start_game_img/tpl1693030994223.png", record_pos=(0.0, 0.221), resolution=(960, 540)))):
touch(Template(r"Data/start_game_img/tpl1693030994223.png", record_pos=(0.0, 0.221), resolution=(960, 540)))
else:
self.start_game_3()
def star_game_main(self):
self.connect_game_Princes_Connect()
self.start_game_1()
self.start_game_2()
self.start_game_3()
self.start_game_4()
def threading_star_game_main(self):
thread = threading.Thread(target=self.star_game_main)
thread.start()
# 2.领取家园体力 需要家园有体力可领取
def colloct_1(self):
if (exists(Template(r"Data/colloct_img/tpl1693032329567.png", record_pos=(0.152, 0.264), resolution=(960, 540)))):
touch(Template(r"Data/colloct_img/tpl1693032329567.png", record_pos=(0.152, 0.264), resolution=(960, 540)))
if (exists(Template(r"Data/colloct_img/tpl1693032401790.png", record_pos=(0.44, 0.165), resolution=(960, 540)))):
pass
else:
self.colloct_1()
def colloct_2(self, t):
print(t)
if (exists(Template(r"Data/colloct_img/tpl1693032401790.png", record_pos=(0.44, 0.165), resolution=(960, 540)))):
touch(Template(r"Data/colloct_img/tpl1693032401790.png", record_pos=(0.44, 0.165), resolution=(960, 540)))
if (exists(Template(r"Data/colloct_img/tpl1693032468694.png", record_pos=(-0.002, 0.218), resolution=(960, 540)))):
pass
else:
if(t<=1):
self.colloct_2(t = t + 1)
def colloct_3(self, t):
print(t)
if (t <= 1):
if (exists(Template(r"Data/colloct_img/tpl1693032468694.png", record_pos=(-0.002, 0.218), resolution=(960, 540)))):
touch(Template(r"Data/colloct_img/tpl1693032468694.png", record_pos=(-0.002, 0.218), resolution=(960, 540)))
sleep(2)
touch([92,515])
if (exists(Template(r"Data/colloct_img/tpl1693059433636.png", record_pos=(0.14, 0.169), resolution=(960, 540)))):
pass
else:
self.colloct_3(t = t + 1)
else:
if (exists(Template(r"Data/colloct_img/tpl1693059433636.png", record_pos=(0.14, 0.169), resolution=(960, 540)))):
pass
else:
touch([92, 515])
self.colloct_3(t = t + 1)
def main_colloct(self):
self.connect_game_Princes_Connect()
self.colloct_1()
self.colloct_2(t=1) # 重复3次没找到则返回
self.colloct_3(t=1) # 重复3次没找到则返回
def threading_main_collect(self):
thread = threading.Thread(target=self.main_colloct)
thread.start()
FC = Open_And_Connect()
2.Menu_Page.py
import threading # 导入threading模块,用于多线程操作
import tkinter # 导入tkinter库,用于创建图形用户界面
from tkinter import messagebox # 导入tkinter库的messagebox模块,用于显示消息框
from function_test import FC # 导入自定义的FC类,可能包含功能测试相关的代码
class Menu:
def __init__(self, root_Menu:tkinter.Tk):
self.root = root_Menu # 初始化self.root为传入的Tkinter窗口对象
# 创建菜单frame
self.page = tkinter.Frame(self.root) # 创建一个Tkinter Frame对象,用于菜单页面
self.about_frame = tkinter.Frame(self.root) # 创建一个Tkinter Frame对象,用于关于页面
def ceshi(self):
FC.xuemaibool = True # 设置FC类的xuemaibool属性为True
FC.threading_control_xuemai() # 调用FC类的threading_control_xuemai方法,可能用于控制血脉
# 隐藏已有页面
self.page.pack_forget()
self.about_frame.pack_forget()
# 定义Tkinter字符串变量
self.local_url = tkinter.StringVar() # 用于存储本地URL的Tkinter字符串变量
self.android_url = tkinter.StringVar() # 用于存储Android设备URL的Tkinter字符串变量
# 设置默认显示的本地URL和Android设备URL
self.local_url.set(FC.local_url)
self.android_url.set(FC.android_url)
# 创建新的页面
self.page = tkinter.Frame(self.root)
self.page.pack()
# 第0行
tkinter.Label(self.page).grid(row=0, column=1)
tkinter.Label(self.page).grid(row=0, column=2)
tkinter.Label(self.page).grid(row=0, column=3)
tkinter.Label(self.page).grid(row=0, column=4)
# 第1行
tkinter.Button(self.page, text=' 打开模拟器 ', command=FC.star_Android).grid(row=1, column=1, padx=50, pady=15)
tkinter.Button(self.page, text='更改模拟器位置', command=self.change_loacl).grid(row=1, column=2, padx=50, pady=15)
tkinter.Entry(self.page, textvariable=self.local_url).grid(row=1, column=3, padx=25, pady=15)
# 第2行
tkinter.Button(self.page, text='测试连接', command=FC.threading_connect).grid(row=2, column=1, padx=50, pady=15)
tkinter.Button(self.page, text='更改安卓设备位置', command=self.change_androd).grid(row=2, column=2, padx=50, pady=15)
tkinter.Entry(self.page, textvariable=self.android_url).grid(row=2, column=3, padx=25, pady=15)
# 第3行
tkinter.Button(self.page, text='血脉', command=FC.threading_main_xuemai).grid(row=3, column=1, padx=50, pady=15)
tkinter.Label(self.page, text='按"q"控制开关状态').grid(row=3, column=2, padx=50, pady=15)
# 第4行
tkinter.Button(self.page, text='进入公主连接', command=FC.threading_star_game_main).grid(row=4, column=1, padx=50, pady=15)
tkinter.Button(self.page, text='领取体力', command=FC.threading_main_collect).grid(row=4, column=2, padx=50, pady=15)
# 关于页面
def show_about(self):
FC.xuemaibool = False # 设置FC类的xuemaibool属性为False
self.page.update() # 更新菜单页面
self.page.pack_forget() # 隐藏菜单页面
self.about_frame.pack() # 显示关于页面
# 在关于页面中添加标签
tkinter.Label(self.about_frame, text='关于作品:本作品由tkinter制作').grid(row=0, column=1)
tkinter.Label(self.about_frame, text='作者:yuzhoujishu').grid(row=1, column=1)
# 更改本地URL的函数
def change_loacl(self):
FC.local_url = self.local_url.get() # 从Tkinter字符串变量获取本地URL并存储到FC类中
with open('Data/local_url.txt', mode='w', encoding='utf-8') as a:
a.write(f"{self.local_url.get()}")
messagebox.showwarning(title='成功', message=f'现在的本地地址是:{self.local_url.get()}')
print(FC.local_url)
# 更改Android设备URL的函数
def change_androd(self):
FC.android_url = self.android_url.get() # 从Tkinter字符串变量获取Android设备URL并存储到FC类中
with open('Data/andorid_url.txt', mode='w', encoding='utf-8') as a:
a.write(f"{self.android_url.get()}")
messagebox.showwarning(title='成功', message=f'现在的android地址是:{self.android_url.get()}')
print(FC.android_url)
3.主 princes_connect.py
import json # 导入json库,用于处理JSON数据
from tkinter import messagebox # 导入tkinter库的messagebox模块,用于显示消息框
import airtest # 导入airtest库,可能用于UI自动化测试
import os # 导入os库,用于操作操作系统功能
import tkinter # 导入tkinter库,用于创建图形用户界面
from airtest.core.api import connect_device # 导入airtest库的connect_device模块
from function_test import FC # 导入自定义的FC类,可能用于功能测试
from Menu_Page import Menu # 导入自定义的Menu类,可能用于创建菜单页面
class Princes:
def __init__(self, master):
self.android_url = None # 初始化android_url变量
self.local_url = None # 初始化local_url变量
self.root = master # 将传入的master参数赋值给self.root
self.root.geometry('960x600') # 设置窗口大小
self.root.title('Princes') # 设置窗口标题
self.create_page() # 调用create_page方法来创建页面
def create_page(self):
ME = Menu(root_Menu=self.root) # 创建Menu对象,并将self.root传递给它
menubar = tkinter.Menu(self.root) # 创建菜单栏
ME.ceshi() # 调用ceshi方法,可能用于创建测试页面和菜单
menubar.add_command(label='测试', command=ME.ceshi) # 添加“测试”菜单项
menubar.add_command(label='关于', command=ME.show_about) # 添加“关于”菜单项
self.root['menu'] = menubar # 将菜单栏设置为窗口的菜单
if __name__ == '__main__':
root = tkinter.Tk() # 创建一个Tkinter窗口对象
Princes(master=root) # 创建Princes对象,传入窗口对象作为参数
root.mainloop() # 启动Tkinter的主循环,使窗口可以响应用户操作
4.演示
tkinter实现可视化的公主连结脚本演示