我需要一个 Spinner 小部件,其中用户可以选择 integer 具有特定步骤且没有下限或上限的值(我的意思是,它们至少应该在十亿范围内,所以没有机会记住整个序列).
I need a Spinner widget in which the user can select integer values with a certain step and without lower or upper limits
(I mean, they should be at least in the billion range, so no chance of memorizing the whole sequence).
我看到了 kivy 的 Spinner 小部件但我不认为像 Spinner(values=itertool.count()) 这样的事情会奏效.它也仅限于字符串值.
I saw kivy's Spinner widget but I don't think doing something like Spinner(values=itertool.count()) would work.
Also it is limited to string values.
有没有什么简单的方法可以获取类似于 QSpinBox 的东西Qt的?
Is there any simple way of obtaining something similar to QSpinBox of the Qt?
目前看来 kivy 没有提供类似于 Spinner 或 SpinBox 的任何东西,但是你想调用它.可以使用的小部件是 Slider 但它看起来很糟糕,如果你想允许一个非常大的范围但只有一小步,它就不是那么有用了.
It seems like kivy at the moment does not provide anything similar to a Spinner or SpinBox or however you want to call it. A widget that might be used instead is the Slider but it looks awful and it's not so useful if you want to allow a very big range but with a small step.
因此,我编写了自己的 SpinBox 实现:
Therefore I wrote my own implementation of a SpinBox:
class SpinBox(BoxLayout):
"""A widget to show and take numeric inputs from the user.
:param min_value: Minimum of the range of values.
:type min_value: int, float
:param max_value: Maximum of the range of values.
:type max_value: int, float
:param step: Step of the selection
:type step: int, float
:param value: Initial value selected
:type value: int, float
:param editable: Determine if the SpinBox is editable or not
:type editable: bool
"""
min_value = NumericProperty(float('-inf'))
max_value = NumericProperty(float('+inf'))
step = NumericProperty(1)
value = NumericProperty(0)
range = ReferenceListProperty(min_value, max_value, step)
def __init__(self, btn_size_hint_x=0.2, **kwargs):
super(SpinBox, self).__init__(orientation='horizontal', **kwargs)
self.value_label = Label(text=str(self.value))
self.inc_button = TimedButton(text='+')
self.dec_button = TimedButton(text='-')
self.inc_button.bind(on_press=self.on_increment_value)
self.inc_button.bind(on_time_slice=self.on_increment_value)
self.dec_button.bind(on_press=self.on_decrement_value)
self.dec_button.bind(on_time_slice=self.on_decrement_value)
self.buttons_vbox = BoxLayout(orientation='vertical',
size_hint_x=btn_size_hint_x)
self.buttons_vbox.add_widget(self.inc_button)
self.buttons_vbox.add_widget(self.dec_button)
self.add_widget(self.value_label)
self.add_widget(self.buttons_vbox)
def on_increment_value(self, btn_instance):
if float(self.value) + float(self.step) <= self.max_value:
self.value += self.step
def on_decrement_value(self, btn_instance):
if float(self.value) - float(self.step) >= self.min_value:
self.value -= self.step
def on_value(self, instance, value):
instance.value_label.text = str(value)
实际上我使用的代码略有不同,因为我认为子类化布局来实现小部件很丑,因此我将 Widget 子类化并添加了一个水平 BoxLayout 作为Widget 的唯一子项,然后我 binded 每个大小和位置更改以更新此子项的大小和位置(请参阅 这个问题我为什么必须这样做).
Actually the code I use is slightly different because I think it is ugly to subclass a layout to implement a widget and thus I subclassed Widget and added a horizontal BoxLayout as only children of the Widget, then I binded every size and position change to update the size and position of this child(see this question for why I had to do that).
TimedButton 是 Button 的子类,它允许长按,并且当长按时,每隔一定时间发出一个 on_time_slice 事件毫秒数(因此用户将能够按住按钮进行连续增量).如果需要,您可以简单地使用普通的 Button,删除 bind 到 on_time_slice 事件.
The TimedButton is a subclass of Button that allows long-presses and, when long-pressed, emits a on_time_slice event every a certain amount of millisecond(thus the user will be able to hold the button to do a continuous increment). You can simply use a normal Button if you want, removing the binds to on_time_slice event.
TimedButton源代码是这样的:
class TimedButton(Button):
"""A simple ``Button`` subclass that produces an event at regular intervals
when pressed.
This class, when long-pressed, emits an ``on_time_slice`` event every
``time_slice`` milliseconds.
:param long_press_interval: Defines the minimum time required to consider
the press a long-press.
:type long_press_interval: int
:param time_slice: The number of milliseconds of each slice.
:type time_slice: int
"""
def __init__(self, long_press_interval=550, time_slice=225, **kwargs):
super(TimedButton, self).__init__(**kwargs)
self.long_press_interval = long_press_interval
self.time_slice = time_slice
self._touch_start = None
self._long_press_callback = None
self._slice_callback = None
self.register_event_type('on_time_slice')
self.register_event_type('on_long_press')
def on_state(self, instance, value):
if value == 'down':
start_time = time.time()
self._touch_start = start_time
def callback(dt):
self._check_long_press(dt)
Clock.schedule_once(callback, self.long_press_interval / 1000.0)
self._long_press_callback = callback
else:
end_time = time.time()
delta = (end_time - (self._touch_start or 0)) * 1000
Clock.unschedule(self._slice_callback)
# Fixes the bug of multiple presses causing fast increase
Clock.unschedule(self._long_press_callback)
if (self._long_press_callback is not None and
delta > self.long_press_interval):
self.dispatch('on_long_press')
self._touch_start = None
self._long_press_callback = self._slice_callback = None
def _check_long_press(self, dt):
delta = dt * 1000
if delta > self.long_press_interval and self.state == 'down':
self.dispatch('on_long_press')
self._long_press_callback = None
def slice_callback(dt):
self.dispatch('on_time_slice')
return self.state == 'down'
Clock.schedule_interval(slice_callback, self.time_slice / 1000.0)
self._slice_callback = slice_callback
def on_long_press(self):
pass
def on_time_slice(self):
pass
请注意,我必须绑定 state 属性,而不是使用 on_touch_down 和 on_touch_up 因为它们提供了一些 奇怪的行为,即使在工作"时,也会无缘无故地发生一些奇怪的事情(例如点击递减按钮导致on_increment 被调用,即使 bindings 正确).
Note that I had to bind the state property instead of using on_touch_down and on_touch_up because they give some strange behaviour, and even when "working" there were some strange things happening by no reason(e.g. clicking the decrement button caused on_increment to be called even though the bindings where correct).
更新了 TimedButton 类,修复了一个小错误(之前的实现在快速单击多次然后按住按钮会产生太多 on_time_slice 事件:当状态变为 'normal'
Updated the TimedButton class fixing a little bug(the previous implementation when clicked rapidly multiple times and then holding down the button would yield too many on_time_slice events: I'd forgot to "unschedule" the _long_press_callback when the state goes 'normal'
这篇关于如何在微调器中允许无限整数值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!
如何制作一个在 Python 中提供角色的不和谐机器人How to make a discord bot that gives roles in Python?(如何制作一个在 Python 中提供角色的不和谐机器人?)
Discord 机器人没有响应命令Discord bot isn#39;t responding to commands(Discord 机器人没有响应命令)
你能得到“关于我"吗?Discord 机器人的功能?Can you Get the quot;About mequot; feature on Discord bot#39;s? (Discord.py)(你能得到“关于我吗?Discord 机器人的功能?(不和谐.py))
message.channel.id Discord PYmessage.channel.id Discord PY(message.channel.id Discord PY)
如何在 heroku 上托管我的 discord.py 机器人?How do I host my discord.py bot on heroku?(如何在 heroku 上托管我的 discord.py 机器人?)
discord.py - 自动更改角色颜色discord.py - Automaticaly Change an Role Color(discord.py - 自动更改角色颜色)