参考链接:https://blog.csdn.net/wxkhturfun/article/details/108927253
https://blog.csdn.net/wxkhturfun/article/details/108964682
https://www.jianshu.com/p/7d35eb953eb9
sudo apt-get install python3-tk
本人是在windows10上测试使用的,所以填的是COM号
pip3 uninstall serial
pip3 uninstall pyserial
pip3 install pyserial
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Master
import serial,threading
import tkinter as tk # 使用Tkinter前需要先导入
#点击按钮的响应(点击之后会显示数据,否则不显示接收的数据,但是不影响小车运动界面是显示)
def hit_me():
global on_hit
global var
if on_hit == False:
on_hit = True
var.set('bluetooth is working')
else:
on_hit = False
var.set('')
#画运动轨迹
def drawLine(cor_list):
global height
x1=ini_x
y1=ini_y
for i in cor_list:
temp_x=x1
temp_y=y1
print(i)
x1=i[0]
y1=height-i[1]
print(x1)
print(y1)
x0=temp_x
y0=temp_y
print(x1-x0)
print(y0-y1)
canvas.create_line(x0,y0, x1,y1,tag="blue")
canvas.move(rect, x1-x0, y1-y0)
canvas.pack()
#接收串口数据
def ReadUART():
global rect
while (True):
try:
idx = ser.read(dataSize)
OutputText.insert(tk.END, int(idx))
OutputText.insert(tk.END, ' ')
print('idx is' +str(idx) )
dif_x = int(idx[0:int(dataSize/2)])-500
dif_y = int(idx[int(dataSize/2):dataSize])-500
idx_x = cor_list[-1][0] + dif_x
idx_y = cor_list[-1][1] + dif_y
n= (idx_x, idx_y)
#if n not in cor_list:
print(n)
cor_list.append(n)
drawLine(cor_list)
rect = canvas.create_rectangle(cor_list[0][0]-5, cor_list[0][1]+5, \
(cor_list[0][0]+5), (cor_list[0][1]-5),fill='red',outline='red',tag="red") # 画矩形正方形
#print(idx, end='')
except:
print("There's something wrong")
#串口是COM4,若不同注意修改
ser = serial.Serial('COM4')
#设置波特率
ser.baudrate=9600
#绘制运动的窗口大小
height = 500
width = 700
#小车初始位置
ini_x = 300
ini_y = 250
#一次接收数据位数
dataSize = 6
n1= (ini_x, ini_y)
#存储小车运动历程坐标的列表cor_list
cor_list=[]
cor_list.append(n1)
#按钮初始点击为False
on_hit=False
var = None
window = tk.Tk()
window.title('Bluetooth')
#gui整体界面大小
window.geometry('800x700')
var = tk.StringVar()
#Label控件
l = tk.Label(window, textvariable=var, bg='green', fg='white', font=('Arial', 12), width=30, height=2)
l.pack()
on_hit = False
#按钮
b = tk.Button(window, text='点击开始', font=('Arial', 12), width=10, height=1, command=hit_me)
b.pack()
ReadyToStart = True
write = tk.StringVar()
OutputText = tk.Text(window, wrap=tk.WORD, width=113, height=3)
OutputText.pack()
canvas = tk.Canvas(window, bg='white', height=height, width=width)
#绘制矩形
rect = canvas.create_rectangle(ini_x, ini_y, (ini_x+10), (ini_y-10),fill='red',outline='red',tag="red") # 画矩形正方形
drawLine(cor_list)
#采用多线程调用蓝牙通信函数
ReadUARTThread = threading.Thread(target=ReadUART)#多线程
ReadUARTThread.start()
#对gui界面进行循环
window.mainloop()
经测试手机app:https://cloud.189.cn/t/IB3EBf7n6vea可以蓝牙发送数据就行,确实可行,需要注意的时,我是一次发六位数,中间以500为差值,比如:
发送600700表示x方向移动600-500=100,而y方向移动700-500=200。
发送200500表示x方向移动200-500=-300,而y方向移动500-500=0
后面我尝试加一些对串口的扫描和选择,不是很成功,留个记录,以备后用:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Master
import serial,threading
import serial.tools.list_ports
import tkinter as tk # 使用Tkinter前需要先导入
import tkinter.messagebox# 使用Tkinter前需要先导入
import time
#点击按钮的响应(点击之后会显示数据,否则不显示接收的数据,但是不影响小车运动界面是显示)
def hit_me():
global on_hit
global var
if on_hit == False:
on_hit = True
var.set('bluetooth is working')
else:
on_hit = False
var.set('')
#画运动轨迹
def drawLine(cor_list):
global height
x1=ini_x
y1=ini_y
for i in cor_list:
temp_x=x1
temp_y=y1
print(i)
x1=i[0]
y1=height-i[1]
print(x1)
print(y1)
x0=temp_x
y0=temp_y
print(x1-x0)
print(y0-y1)
canvas.create_line(x0,y0, x1,y1,tag="blue")
canvas.move(rect, x1-x0, y1-y0)
canvas.pack()
#接收串口数据
def ReadUART():
global rect
while (True):
try:
idx = ser.read(dataSize)
OutputText.insert(tk.END, int(idx))
OutputText.insert(tk.END, ' ')
print('idx is' +str(idx) )
dif_x = int(idx[0:int(dataSize/2)])-500
dif_y = int(idx[int(dataSize/2):dataSize])-500
idx_x = cor_list[-1][0] + dif_x
idx_y = cor_list[-1][1] + dif_y
n= (idx_x, idx_y)
#if n not in cor_list:
print(n)
cor_list.append(n)
drawLine(cor_list)
rect = canvas.create_rectangle(cor_list[0][0]-5, cor_list[0][1]+5, \
(cor_list[0][0]+5), (cor_list[0][1]-5),fill='red',outline='red',tag="red") # 画矩形正方形
#print(idx, end='')
except:
print("There's something wrong")
def menu(tk):
global menubar
global filemenu
menubar = tk.Menu(window)
# 第6步,创建一个File菜单项(默认不下拉,下拉内容包括New,Open,Save,Exit功能项)
filemenu = tk.Menu(menubar, tearoff=0)
# 将上面定义的空菜单命名为File,放在菜单栏中,就是装入那个容器中
menubar.add_cascade(label='scan', menu=filemenu)
port_com = scan()
if port_com is not None:
for i in range(0,len(port_com)):
filemenu.add_command(label=str(port_com[i]),command=lambda:setSerial(str(port_com[i])))
filemenu.add_separator() # 添加一条分隔线
filemenu.add_command(label='Exit', command=window.quit) # 用tkinter里面自带的quit()函数
def scan():
port_com=[]
port_list = list(serial.tools.list_ports.comports())
if len(port_list) == 0:
print('找不到串口')
return None
else:
for i in range(0,len(port_list)):
comx=str(port_list[i])
comx=comx.split(' ',1)
port_com.append(comx[0])
return port_com
#print(port_com)
def setSerial(com_x):
'''global ser
ser = serial.Serial(com_x)
print(ser)
print(com_x)'''
print("com_x")
#串口是COM4,若不同注意修改
ser = serial.Serial('COM4')
#设置波特率
ser.baudrate=9600
#绘制运动的窗口大小
height = 500
width = 700
#小车初始位置
ini_x = 300
ini_y = 250
#一次接收数据位数
dataSize = 6
n1= (ini_x, ini_y)
#存储小车运动历程坐标的列表cor_list
cor_list=[]
cor_list.append(n1)
#按钮初始点击为False
on_hit=False
var = None
window = tk.Tk()
window.title('Bluetooth')
#gui整体界面大小
window.geometry('800x700')
var = tk.StringVar()
#Label控件
l = tk.Label(window, textvariable=var, bg='green', fg='white', font=('Arial', 12), width=30, height=2)
l.pack()
on_hit = False
#按钮
b = tk.Button(window, text='点击开始', font=('Arial', 12), width=10, height=1, command=hit_me)
b.pack()
ReadyToStart = True
write = tk.StringVar()
OutputText = tk.Text(window, wrap=tk.WORD, width=113, height=3)
OutputText.pack()
canvas = tk.Canvas(window, bg='white', height=height, width=width)
#绘制矩形
rect = canvas.create_rectangle(ini_x, ini_y, (ini_x+10), (ini_y-10),fill='red',outline='red',tag="red") # 画矩形正方形
drawLine(cor_list)
#采用多线程调用蓝牙通信函数
ReadUARTThread = threading.Thread(target=ReadUART)#多线程
ReadUARTThread.start()
menu(tk)
#显示菜单
window.config(menu=menubar)
#对gui界面进行循环
window.mainloop()
最初没有加蓝牙功能,纯绘图时的代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Master
import tkinter as tk # 使用Tkinter前需要先导入
class movement:
on_hit=False
var = None
def __init__(self,cor_list):
# 第1步,实例化object,建立窗口window
window = tk.Tk()
# 第2步,给窗口的可视化起名字
window.title('Bluetooth')
# 第3步,设定窗口的大小(长 * 宽)
window.geometry('800x600') # 这里的乘是小x
# 第4步,在图形界面上设定标签
self.var = tk.StringVar() # 将label标签的内容设置为字符类型,用var来接收hit_me函数的传出内容用以显示在标签上
l = tk.Label(window, textvariable=self.var, bg='green', fg='white', font=('Arial', 12), width=30, height=2)
# 说明: bg为背景,fg为字体颜色,font为字体,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
l.pack()
# 定义一个函数功能(内容自己自由编写),供点击Button按键时调用,调用命令参数command=函数名
self.on_hit = False
# 第5步,在窗口界面设置放置Button按键
b = tk.Button(window, text='点击开始', font=('Arial', 12), width=10, height=1, command=self.hit_me)
b.pack()
height = 500
width = 700
x0=0
y0=0
temp_x=0
temp_y=0
x1=0
y1=500
canvas = tk.Canvas(window, bg='white', height=height, width=width)
# 说明图片位置,并导入图片到画布上
# 定义多边形参数,然后在画布上画出指定图形
rect = canvas.create_rectangle(0, 500, 10, 490,fill='red',outline='red',tag="red") # 画矩形正方形
for i in cor_list:
temp_x=x1
temp_y=y1
print(i)
x1=i[0]
y1=height-i[1]
print(x1)
print(y1)
x0=temp_x
y0=temp_y
print(x1-x0)
print(y0-y1)
#line = canvas.create_line(x0,y0, x1,y1,tag="blue")
canvas.create_line(x0,y0, x1,y1,tag="blue")
canvas.move(rect, x1-x0, y1-y0) # 移动正方形rect(也可以改成其他图形名字用以移动一起图形、元素),按每次(x=2, y=2)步长进行移动
canvas.pack()
#canvas.delete("blue")#删除对应的tag
# 第6步,主窗口循环显示
window.mainloop()
def hit_me(self):
on_hit = self.on_hit
var = self.var
if on_hit == False:
on_hit = True
var.set('bluetooth is working')
else:
on_hit = False
var.set('')
if __name__ == "__main__":
n1= (20, 130)
n2 = (150, 150)
n3=(200,250)
cor_list=[]
cor_list.append(n1)
cor_list.append(n2)
cor_list.append(n3)
movement(cor_list)