|
发表于 2024-5-30 15:21:44
|
显示全部楼层
本帖最后由 被诅咒的章鱼 于 2024-5-30 15:23 编辑
由于按钮长按的需求还挺常见,所以花时间研究了一下其他实现方法。
参考了两个Lemma论坛的帖子:
https://lemmasoft.renai.us/forums/viewtopic.php?p=566450
https://lemmasoft.renai.us/forums/viewtopic.php?p=556570
下面的部分还待完善的成果:
1. 首先需要自定义一个组件,来捕获鼠标在组件区域内按下和抬起的两个事件:
[RenPy] 纯文本查看 复制代码 init python:
import pygame
class OnPressAction(renpy.Displayable):
def __init__(self, press_action, release_action, button_dispalyable, **kwargs):
super().__init__(**kwargs)
self.press_action = press_action
self.release_action = release_action
self.width = 0
self.height = 0
self.child = button_dispalyable
def render(self, width, height, st, at):
t = Transform(child=self.child)
cr = renpy.render(t, width, height, st, at)
self.width, self.height = cr.get_size()
r = renpy.Render(self.width, self.height)
r.blit(cr, (0, 0))
return r
def event(self, ev, x, y, st):
if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
if x > 0 and x < self.width and y > 0 and y < self.height:
return renpy.run(self.press_action)
elif ev.type == pygame.MOUSEBUTTONUP and ev.button == 1:
return renpy.run(self.release_action)
使用自定义组件而不是 keysym 按键映射的原因在于,keysym绑定鼠标事件后,点击整个屏幕都会触发按钮的action。如果之后再根据鼠标位置进行处理反而麻烦了。
这个自定义组件总共有3个入参,分别对应鼠标左键按下的action、鼠标左键抬起的action和显示的图像。入参有两个action的原因后面说。
2. 只包含一个自定义组件的界面,可以当作一个封装的特殊按钮:
[RenPy] 纯文本查看 复制代码 screen button_with_long_press:
add OnPressAction(press_action, release_action, child_displayable)
3. 新建一个界面,设置一些变量,包括:要调整的值,值的范围,点击等待和重复执行间隔等。
[RenPy] 纯文本查看 复制代码 screen value_tune:
default is_pressed = False
default hovered_button = ""
default value = 0
default value_max = 10
default value_min = 0
default press_time = 0.0
default press_wait_time = 0.5
default press_repeat_time = 0.1
text "[is_pressed]" xalign 0.5 yalign 0.2
text "[hovered_button]" xalign 0.5 yalign 0.3
hbox:
align 0.5, 0.5
spacing 50
use button_with_long_press(button_name="-", press_action=[SetScreenVariable("is_pressed", True), SetScreenVariable("value", max(value_min, value-1)), SetScreenVariable("hovered_button", "-")], release_action=[SetScreenVariable("is_pressed", False), SetScreenVariable("press_time", 0.0), SetScreenVariable("hovered_button", "")], child_displayable=Text("-"))
text "[value]"
use button_with_long_press(button_name="+", press_action=[SetScreenVariable("is_pressed", True), SetScreenVariable("value", min(value_max, value+1)), SetScreenVariable("hovered_button", "+")], release_action=[SetScreenVariable("is_pressed", False), SetScreenVariable("press_time", 0.0), SetScreenVariable("hovered_button", "")], child_displayable=Text("+"))
timer press_repeat_time repeat True:
if is_pressed:
if press_time < press_wait_time:
action SetScreenVariable("press_time", press_time + 0.1)
else:
if hovered_button == "+":
action SetScreenVariable("value", min(value_max, value+1))
elif hovered_button == "-":
action SetScreenVariable("value", max(value_min, value-1))
此时就会用到上面自定义组件的两个不同时间触发的action,按下时调整数值 value,抬起时重置标识 is_pressed 和 hovered_button 。
这些调整都仅限界面 value_tune 内的标量。如果要调整全局变量,把某些action中的SetScreenVariable改用SetVariable即可。
自定义组件在显示层面还不完善,不像button组件那样有idle、hover、selected等多个状态。
|
|