有没有一种官方方法可以在 GTK 中创建离散值范围小部件?

Is there an official way to create discrete-valued range widget in GTK?

据我所知,任何基于 Range 的小部件的行为都是由 Adjustements 小部件定义的。

由于似乎没有官方方法可以将范围限制为几个离散值,因此我尝试了很多方法来实际重置这些值。

什么有效,但不是最优的,只是获取当前值并确定哪个有效离散值最接近该连续值并使用它。

但我想要的是在视觉上将滑块冻结到其当前位置,直到用户将其抓得足够远,然后立即将其值更改为下一个有效值。

我想让用户理解并感受到这些是离散值。我上面的工作解决方案的问题是,测试该程序的 3 个用户告诉我,我应该在我显示的数字中添加更多数字,认为变化是连续的。

注意:"official" 是指 "hidden" 选项或 Adjustements class 的子 class(如果有的话)。如果不是,则可以通过任何合理有效的方式来实现这样的要求(即不要将 CPU 的 50% 用于简单的滑块!)。特别是,我 不要求 "ultimate best way" 这样做。

看来你可以覆盖 change-value 信号:

class DiscreteScale(Gtk.Scale):
    def __init__(self, values, *args, **kwargs):
        super().__init__(*args, **kwargs)

        values.sort()
        self.values= values

        adjustment= self.get_adjustment()
        adjustment.set_lower(values[0])
        adjustment.set_upper(values[-1])

        self.__changed_value_id= self.connect('change-value', self.__change_value)

    def __change_value(self, scale, scroll_type, value):
        # find the closest valid value
        value= self.__closest_value(value)
        # emit a new signal with the new value
        self.handler_block(self.__changed_value_id)
        self.emit('change-value', scroll_type, value)
        self.handler_unblock(self.__changed_value_id)
        return True #prevent the signal from escalating

    def __closest_value(self, value):
        return min(self.values, key=lambda v:abs(value-v))

一个小演示:

w= Gtk.Window()
s= DiscreteScale([0, 1, 5, 20, 22])
w.add(s)
w.set_size_request(500, 50)

w.connect('delete-event', Gtk.main_quit)
w.show_all()
Gtk.main()

您没有指定要查找的离散值区间,但 GtkRange(因此 GtkScale)支持舍入:

scale_widget.set_round_digits(1)
scale_widget.set_digits(1)

我怀疑这是许多用户正在寻找的离散值 GtkScale 的解决方案。

https://developer.gnome.org/pygtk/stable/class-gtkrange.html#method-gtkrange--set-round-digits https://developer.gnome.org/gtk3/stable/GtkRange.html#gtk-range-set-round-digits