1

我正在将应用程序从 PyGTK 移植到 PyGObject。大多数情况下它进展顺利,因为大多数情况下我用 PyGTK 做了常规的事情。但是我使用了一个有点丑陋的技巧来将 SpinButton 的值显示为货币(前面有一个 $)。

在 Stack Overflow 前几天,我最初从PyGTK 邮件列表中获得了这个解决方案。如您所见,魔术发生在输入和输出信号上:

import gtk, ctypes

def _currency_input(spinbutton, gpointer):
    text = spinbutton.get_text()
    if text.startswith('$'):
        text = text[1:]
    double = ctypes.c_double.from_address(hash(gpointer))
    double.value = float(text)
    return True

def _currency_output(spinbutton):
    text = '$%.*f' % (int(spinbutton.props.digits), 
spinbutton.props.adjustment.value)
    spinbutton.set_text(text)
    return True

def format_spinbutton_currency(spinbutton):
    spinbutton.connect('input', _currency_input)
    spinbutton.connect('output', _currency_output)

def _test():
    s = gtk.SpinButton(gtk.Adjustment(value=1, lower=0, upper=1000, 
step_incr=1))
    s.props.digits = 2
    format_spinbutton_currency(s)
    w = gtk.Window()
    w.props.border_width = 12
    w.add(s)
    w.show_all()
    w.connect('destroy', gtk.main_quit)
    gtk.main()

if __name__ == '__main__':
    _test()

尽我所能将其翻译成 PyGObject,我想出了:

from gi.repository import Gtk
import ctypes

def _currency_input(spinbutton, gpointer):
    text = spinbutton.get_text()
    if text.startswith('$'):
        text = text[1:]
    double = ctypes.c_double.from_address(hash(gpointer))
    double.value = float(text)
    return True

def _currency_output(spinbutton):
    text = '$%.*f' % (int(spinbutton.props.digits), 
spinbutton.get_value())
    spinbutton.set_text(text)
    return True

def format_spinbutton_currency(spinbutton):
    spinbutton.connect('input', _currency_input)
    spinbutton.connect('output', _currency_output)

def _test():
    s = Gtk.SpinButton()
    s.set_adjustment(Gtk.Adjustment(value=1, lower=0, upper=1000, 
step_increment=1))
    s.props.digits = 2
    format_spinbutton_currency(s)
    w = Gtk.Window()
    w.props.border_width = 12
    w.add(s)
    w.show_all()
    w.connect('destroy', Gtk.main_quit)
    Gtk.main()

if __name__ == '__main__':
    _test()

不幸的是,这不起作用。它最初显示得很好,但是当我单击向上或向下错误时,它崩溃了,我看到:

/usr/lib/python2.7/dist-packages/gi/types.py:43: Warning: g_value_get_double: assertion `G_VALUE_HOLDS_DOUBLE (value)' failed
  return info.invoke(*args, **kwargs)
Segmentation fault

知道这个错误消息是什么意思吗?

或者我的代码的哪一部分在 PyGObject 下可能不起作用?

或者,更好的是,如何解决这个错误?

或者,更好的是,一个更直接的解决方案来解决我原来的问题(在 SpinButton 内容前显示一个 $)?

4

2 回答 2

2

来自 PyGtk 文档:

http://developer.gnome.org/pygtk/stable/class-gtkspinbutton.html#signal-gtkspinbutton--input

当值改变时发出“输入”信号。value_ptr 是指向无法从 PyGTK 访问的值的 GPointer。PyGTK 无法处理此信号

所以,我很惊讶地看到类似的东西:

double = ctypes.c_double.from_address(hash(gpointer))

这是一个真正的黑客,所以你得到了一个可怕的错误“分段错误”,这意味着你在内存中弄乱了你不必这样做,而且它非常通用,例如当你在 C 中尝试手动访问内存指针时会发生这种情况不由您的应用程序处理。

这将是一个艰难的过程,我尝试了一个小时,我尝试的所有方法都有问题。我知道不是和答案,但作为一种解决方法,如果您只需要货币符号(而不是分组),您可以尝试将货币符号图像添加到继承的 Gtk.Entry set_icon_from_pixbuf()

在此处输入图像描述

(显然是把图片设置为货币图片)

亲切的问候

于 2012-05-10T07:24:15.963 回答
0

或者,更好的是,一个更直接的解决方案来解决我原来的问题(在 SpinButton 内容前显示一个 $)?

我通过将 GTKSpinButton 的output信号连接到一个简单的处理程序来完成这项工作:

    def onSpinOutput(self, spinbutton):
      adjustment = spinbutton.get_adjustment()
      spinbutton.set_text(str(int(adjustment.get_value())) + "%")
      return True

在我的例子中,我在数字后添加了一个百分号,但您可以轻松更改它以在前面插入其他内容。请注意,这会设置文本而不是条目的;这不适用于数字旋转按钮。

于 2021-01-24T17:42:01.357 回答