鱼C论坛

 找回密码
 立即注册
查看: 1001|回复: 15

[已解决]tkinter中如何获取鼠标按住的反馈?

[复制链接]
发表于 2021-9-3 22:26:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 gdmao002 于 2021-9-3 22:27 编辑

比如我们绑定了鼠标的按键事件,我们敲击键盘的时候,都能得到记录。
但是我看了下键盘事件中 只有按下 KeyPress和按住释放后KeyRelease的键盘事件,
如果是按住不释放的事件有获取的办法吗?
或者说有没有其他思路可以让我们能判定是键盘按住状态,因为在写俄罗斯方块的一个小游戏,
大家也知道如果按住一个方向不释放的话应该是连续的操作!所以写的时候遇到了这个问题,希望大家能帮帮忙!
最佳答案
2021-9-4 12:05:35
gdmao002 发表于 2021-9-4 10:00
我刚也看了下网址,还有你的代码,这个是鼠标的按住,虽然按住是对了,但是呢不是键盘,不过你说的也是可 ...

原理是类似的呀!
并且这个教程里有不少有用的东西,比如 canvas 的tags,和它cv.create_xx后返回的itemID
再多搜一下,cv还有个move()方法,就可以实现移动画布上的任何元素item了
非要我写个完美实现的? ——去,哪来的完美!
  1. # 按键移动方块
  2. from tkinter import *

  3. class App():
  4.     def __init__(self, root):
  5.         self.root = root
  6.         self.root.geometry("500x500")

  7.         self.cv = Canvas(self.root, background="white")
  8.         self.cv.grid(row=0, column=0, sticky="news")

  9.         self.rectId = self.cv.create_rectangle(10, 10, 100, 50, fill='red', outline='blue', tags=('rect_1'))
  10.         self.polyId = self.cv.create_polygon(100, 100, 180, 100, 180, 200, 150, 200, 150, 130, 100, 130, fill='yellow', outline='blue')
  11.         # 下面这两步(按住左键和移动)写在一起,就相当于监测鼠标左键是否被按住和移动了,也就是实现了你所说的"连续事件"
  12.         # self.root.bind("<Button-1>", self.save_pos)
  13.         # self.root.bind("<B1-Motion>", self.add_line_or_do_sth)
  14.         # self.root.bind("<Right>", self.save_pos)
  15.         self.root.bind("<Right>", self.add_line_or_do_sth)
  16.         self.root.bind("<Left>", self.go_left)
  17.         self.root.bind("<Down>", self.go_down)
  18.         # self.root.bind("<KeyRelease>", self.add_line_or_do_sth) # 不需要按键释放检测
  19.         """ 注:要先激活tk窗口,才能操控! """


  20.     def save_pos(self, event):
  21.         # self.lastx, self.lasty = event.x, event.y  
  22.         pass

  23.     def add_line_or_do_sth(self, event):
  24.         # self.cv.create_line((self.lastx, self.lasty, event.x, event.y))
  25.         # self.save_pos(event) # 光标移动了,当前位置就变成了"上一个位置"
  26.         # print(f"鼠标左键被按住了 并且发生了移动,目前光标位置为:({event.x},{event.y})")
  27.         # do something else you want
  28.         # ... 比如,把方块移动到新的位置上
  29.         print(self.cv.gettags(self.rectId), "正在右移...")
  30.         self.cv.move(self.rectId, 5, 0)
  31.         
  32.     def go_left(self, event):
  33.         print(self.cv.gettags(self.rectId), "正在左移...")
  34.         self.cv.move(self.rectId, -5, 0)
  35.     def go_down(self, event):
  36.         print(self.cv.gettags(self.rectId), "正在下移...")
  37.         self.cv.move(self.rectId, 0, 5)

  38. root = Tk()
  39. app = App(root)
  40. app.root.mainloop()
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-9-3 23:09:58 | 显示全部楼层
额外加个多线程读秒,按下后增加一个线程读秒。假如检测到释放便直接结束线程,假如读秒结束未收到释放事件就判定为长按键盘。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-3 23:31:44 | 显示全部楼层
本帖最后由 阿奇_o 于 2021-9-3 23:37 编辑

好像用pygame更合适吧。。
用tkinter应该也行,可以参考 画布的一个例子:A Simple Sketchpad  
https://tkdocs.com/tutorial/canvas.html#bindings

  1. #我的稍微修改了一下,
  2. from tkinter import *

  3. class App():
  4.     def __init__(self, root):
  5.         self.root = root
  6.         self.root.geometry("500x500")

  7.         self.cv = Canvas(self.root, background="white")
  8.         self.cv.grid(row=0, column=0, sticky="news")

  9.         # 下面这两步(按住左键和移动监测)写在一起,就相当于监测鼠标左键是否被按住和移动了,也就是实现了你所说的"连续的操作"
  10.         self.root.bind("<Button-1>", self.save_pos)
  11.         self.root.bind("<B1-Motion>", self.add_line_or_do_sth)  

  12.     def save_pos(self, event):
  13.         self.lastx, self.lasty = event.x, event.y

  14.     def add_line_or_do_sth(self, event):
  15.         self.cv.create_line((self.lastx, self.lasty, event.x, event.y))
  16.         self.save_pos(event) # 光标移动了,当前位置就变成了"上一个位置"
  17.         print(f"鼠标左键被按住了 并且发生了移动,目前光标位置为:({event.x},{event.y})")
  18.         # do something else you want
  19.         # ... 比如,把方块移动到新的位置上

  20. root = Tk()
  21. app = App(root)
  22. app.root.mainloop()
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 08:38:51 From FishC Mobile | 显示全部楼层
tkinter毕竟是gui,用Python做游戏的话还是pygame比较好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 09:40:58 | 显示全部楼层
ink_Ocelot 发表于 2021-9-3 23:09
额外加个多线程读秒,按下后增加一个线程读秒。假如检测到释放便直接结束线程,假如读秒结束未收到释放事件 ...

但是你只是判定了是否按下,但是我们正常操作的时候不是等判定的时候才操作,而是做出了一个反应就要有操作,也就相当于你做了按下到释放期间 这中间时间相当于 没有操作,你说是吧,所以这样判定虽然可以判定是按下,但是对于我们连续按的操作来说就显得不大对,毕竟不可能来个延迟操作把!
但是也很感谢大兄弟你给的一个思路了谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 10:00:08 | 显示全部楼层
阿奇_o 发表于 2021-9-3 23:31
好像用pygame更合适吧。。
用tkinter应该也行,可以参考 画布的一个例子:A Simple Sketchpad  
https:// ...

我刚也看了下网址,还有你的代码,这个是鼠标的按住,虽然按住是对了,但是呢不是键盘,不过你说的也是可能pygame 更合适,哈哈,只是呢 图形界面tkinter更多功能,只是有画布这个想到俄罗斯方块或许可以,但是发现连续的操作发现无法达成,可能只能一步一步的来操作了。也感谢大兄弟的代码,监测了鼠标的按住,谢谢了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 10:01:24 | 显示全部楼层
小伤口 发表于 2021-9-4 08:38
tkinter毕竟是gui,用Python做游戏的话还是pygame比较好

嗯,是的。然后发现对于写游戏这块功能是弱化了不少,毕竟没办法播放音乐不是吗?哈哈。谢谢大兄弟你对我的支持哈。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 10:49:53 From FishC Mobile | 显示全部楼层
gdmao002 发表于 2021-9-4 10:01
嗯,是的。然后发现对于写游戏这块功能是弱化了不少,毕竟没办法播放音乐不是吗?哈哈。谢谢大兄弟你对我 ...

加油,期待你之后的作品
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 12:05:35 | 显示全部楼层    本楼为最佳答案   
gdmao002 发表于 2021-9-4 10:00
我刚也看了下网址,还有你的代码,这个是鼠标的按住,虽然按住是对了,但是呢不是键盘,不过你说的也是可 ...

原理是类似的呀!
并且这个教程里有不少有用的东西,比如 canvas 的tags,和它cv.create_xx后返回的itemID
再多搜一下,cv还有个move()方法,就可以实现移动画布上的任何元素item了
非要我写个完美实现的? ——去,哪来的完美!
  1. # 按键移动方块
  2. from tkinter import *

  3. class App():
  4.     def __init__(self, root):
  5.         self.root = root
  6.         self.root.geometry("500x500")

  7.         self.cv = Canvas(self.root, background="white")
  8.         self.cv.grid(row=0, column=0, sticky="news")

  9.         self.rectId = self.cv.create_rectangle(10, 10, 100, 50, fill='red', outline='blue', tags=('rect_1'))
  10.         self.polyId = self.cv.create_polygon(100, 100, 180, 100, 180, 200, 150, 200, 150, 130, 100, 130, fill='yellow', outline='blue')
  11.         # 下面这两步(按住左键和移动)写在一起,就相当于监测鼠标左键是否被按住和移动了,也就是实现了你所说的"连续事件"
  12.         # self.root.bind("<Button-1>", self.save_pos)
  13.         # self.root.bind("<B1-Motion>", self.add_line_or_do_sth)
  14.         # self.root.bind("<Right>", self.save_pos)
  15.         self.root.bind("<Right>", self.add_line_or_do_sth)
  16.         self.root.bind("<Left>", self.go_left)
  17.         self.root.bind("<Down>", self.go_down)
  18.         # self.root.bind("<KeyRelease>", self.add_line_or_do_sth) # 不需要按键释放检测
  19.         """ 注:要先激活tk窗口,才能操控! """


  20.     def save_pos(self, event):
  21.         # self.lastx, self.lasty = event.x, event.y  
  22.         pass

  23.     def add_line_or_do_sth(self, event):
  24.         # self.cv.create_line((self.lastx, self.lasty, event.x, event.y))
  25.         # self.save_pos(event) # 光标移动了,当前位置就变成了"上一个位置"
  26.         # print(f"鼠标左键被按住了 并且发生了移动,目前光标位置为:({event.x},{event.y})")
  27.         # do something else you want
  28.         # ... 比如,把方块移动到新的位置上
  29.         print(self.cv.gettags(self.rectId), "正在右移...")
  30.         self.cv.move(self.rectId, 5, 0)
  31.         
  32.     def go_left(self, event):
  33.         print(self.cv.gettags(self.rectId), "正在左移...")
  34.         self.cv.move(self.rectId, -5, 0)
  35.     def go_down(self, event):
  36.         print(self.cv.gettags(self.rectId), "正在下移...")
  37.         self.cv.move(self.rectId, 0, 5)

  38. root = Tk()
  39. app = App(root)
  40. app.root.mainloop()
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 12:09:51 | 显示全部楼层
gdmao002 发表于 2021-9-4 10:01
嗯,是的。然后发现对于写游戏这块功能是弱化了不少,毕竟没办法播放音乐不是吗?哈哈。谢谢大兄弟你对我 ...

可以在tkinter里播放音乐,把pygame.mixer.music的load() 和 play()方法,用上,就行了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 13:01:51 | 显示全部楼层
阿奇_o 发表于 2021-9-4 12:09
可以在tkinter里播放音乐,把pygame.mixer.music的load() 和 play()方法,用上,就行了

哈哈 我知道,我说的不能播放的意思是这个库没有带播放音乐的功能,当然引入的那就是其他库了哈,感谢你的分享了Thanks&#9834;(&#65381;ω&#65381;)&#65417;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 13:04:13 | 显示全部楼层
小伤口 发表于 2021-9-4 10:49
加油,期待你之后的作品

谢谢大兄弟鼓励
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 13:33:10 | 显示全部楼层
本帖最后由 gdmao002 于 2021-9-4 13:35 编辑
阿奇_o 发表于 2021-9-4 12:05
原理是类似的呀!
并且这个教程里有不少有用的东西,比如 canvas 的tags,和它cv.create_xx后返回的item ...


兄弟辛苦了,我仔细看了下,关于你定义的设置中,我有几个要说明的,你在__init__() 这个构造方法中 底下的几个关于
  1. self.root.bind("<Right>", self.add_line_or_do_sth)
  2. self.root.bind("<Left>", self.go_left)
  3. self.root.bind("<Down>", self.go_down)
复制代码

这样写应该是不行的,因为先去内存申请了一块空间后,然后是这个构造方法,而你直接运行他的绑定事件,那么请问这个时候绑定事件应该是还没有生成的,那么你直接写会调用?因为我记得要想执行下面的这个应该是编译类型才能可以把,python解释型的要先有才能找到把。所以我估计这里估计你设置了也没反应。关于按键应该是<key-键名>或者<keyPress-键名> 把 然后我看到你直接写键名 应该是不行!
谢谢兄弟你这么不辞辛苦了,给我写代码回复。因为我那个是按住是指键盘按住,不是鼠标按住。
通过对比发现兄弟你最辛苦,最用心了。我就把最佳答案给你了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 15:26:36 | 显示全部楼层
本帖最后由 阿奇_o 于 2021-9-4 15:34 编辑
gdmao002 发表于 2021-9-4 13:33
兄弟辛苦了,我仔细看了下,关于你定义的设置中,我有几个要说明的,你在__init__() 这个构造 ...


真不知道是我傻,还是你傻,我都写到这种程度,肯定是试过了能正常运行了的呀。。

这是写 在类里面,绑定到实例对象self的方法上,就是这样写(因为创建实例时,这些的"回调函数/方法",就被创建了)。
不是在类里面,则必须把"回调函数" 写在绑定命令之前,否则"找不到"(没创建就用了)。

明白了么?

至于绑定的键名字,应该有几种写法,就好比 一个人学名叫"张三",小名叫"小张",也有江湖名号叫"法外狂徒张三",只要能用就行,随便你叫!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-4 16:09:03 | 显示全部楼层
本帖最后由 gdmao002 于 2021-9-4 16:11 编辑
阿奇_o 发表于 2021-9-4 15:26
真不知道是我傻,还是你傻,我都写到这种程度,肯定是试过了能正常运行了的呀。。

这是写 在类里面 ...


还有请在沟通中用正常的语言说问题,别用什么你傻不傻的这类语言来说,我们要就事论事?明白吗?说什么傻不傻的只会让人觉得语言低俗!
看来你没懂我的详细描述
你说的这些什么回调函数方法就被创建,这是在构造之后才产生的,而不是同时产生,你的逻辑是没有先后直接说有!明白吗?我的意思是想跟你讲明白 创建一个实例的先后执行顺序!
一个类的实例对象的创建
首先会执行def__new__()这个方法 这个方法是创建一个内存分配给这个对象,然后创建成功后才会执行构造方法也就是def __init__()内的方法,这时候会创建初始化的变量值,这个时候还没创建那些定义的类方法,所以这时候你就开始把下面方法直接绑定事件了,但是我试了下发现这样也可以写,但是我觉得你这种写法不好,如果你自己觉得好就这样写吧。毕竟每个人的写代码风格也有不同,可能你就喜欢在构造方法中写这些!不过代码怎么写 我也管不了太多,我只是指出你这样写是不好!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-4 20:08:53 | 显示全部楼层
gdmao002 发表于 2021-9-4 16:09
还有请在沟通中用正常的语言说问题,别用什么你傻不傻的这类语言来说,我们要就事论事?明白吗?说什么 ...

  
  一个"傻"字,就让你觉得"低俗",我挺无语的。。哎,我真是傻,太傻了……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 08:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表