问题描述
我有发票相关数据的树状视图显示.发票标识符有下划线.我注意到下划线在 GUI 中正确显示,但是从树行数据中获得的发票编号值忽略了下划线.我目前正在将 - 替换为 _,然后将数据插入到完整的应用程序中以处理该问题.
I have a treeview display of invoice related data. The invoice identifiers have underscores. I have noticed the underscore displays correctly in the GUI however the invoice number value obtained from the tree row data omits the underscore.I am currently doing a substitution of - for _ before inserting the data in the full application to handle the issue.
我使用树视图或检索用户选择的行数据的方式导致了问题吗?或者,对于 GUI 显示和检索到的具有下划线字符的值之间的差异是否有另一种解释?
Is the way I am using the treeview or retrieving the row data the user selected causing the issue? Or, is there another explanation for the discrepancy between GUI display and the retrieved values that have underscore characters?
我使用的是 python 3.6 和 tkinter 8.6
I am using python 3.6 and tkinter 8.6
这是一个例子.
谢谢.
import tkinter as tk
from tkinter import ttk
DATA = [('180518-23', '23/06/18'),
('180618_24', '27/06/18')]
def invoice_selected(event):
row_selected = event.widget.focus()
values = event.widget.item(row_selected)['values']
invoicenumber = values[0]
print('invoice number', invoicenumber)
ROOT = tk.Tk()
header = ('Invoice', 'Due')
tree = ttk.Treeview(columns=header,
show="headings",
height=5)
tree.grid()
for col, text in enumerate(header):
tree.heading(col, text=text)
tree.bind('<<TreeviewSelect>>', invoice_selected)
for record in DATA:
tree.insert('', 'end', values=record)
ROOT.mainloop()
推荐答案
tl;dr: 与其做 item(row_selected)['values']
,不如做 item(row_selected, option='values')
.
tl;dr: Instead of doing item(row_selected)['values']
, do item(row_selected, option='values')
.
我认为这实际上是 tkinter 中的一个错误,解决方法实际上依赖于另一个错误,所以我将两者都提交为 bpo#34447.但让我们看看那边的 tkinter 专家怎么说.
I think this is actually a bug in tkinter, and the workaround is actually relying on another bug, so I filed both as b.p.o. #34447. But let's see what the tkinter experts over there say.
与此同时,您希望了解为什么会有所作为,对吗?
Meanwhile, you hopefully want to understand why that makes a difference, right?
如果您查看 的文档项目
:
If you look at the docs for item
:
查询或修改指定项的选项.
如果没有给出选项,则返回一个包含该项目的选项/值的字典.如果指定了 option,则返回该选项的值.否则,将选项设置为 kw 给出的相应值.
If no options are given, a dict with options/values for the item is returned. If option is specified then the value for that option is returned. Otherwise, sets the options to the corresponding values as given by kw.
因此,如果您请求 values
选项,您将获得 values
选项的值.
So, if you ask for the values
option, you get the values
option's value.
但是如果您不要求任何东西,tkinter 会尝试变得聪明并为您提供所有选项的字典.
But if you don't ask for anything, tkinter tries to get clever and give you a dict with all of the options.
问题在于,在幕后,tkinter 是 Tcl/Tk 的包装器.在 Tcl 中,一切都是字符串(在这方面,它更像是 bash 而不是 Python);数字 123
和字符串 '123'
之间没有区别.在 TreeView
项中存储整数是完全合法的,但它们的存储方式与字符串完全相同.
The problem is that, under the covers, tkinter is a wrapper around Tcl/Tk. In Tcl, everything is a string (it's more like, say, bash in this regard than Python); there's no difference between the number 123
and the string '123'
. It's perfectly legal to store ints in TreeView
items, but they get stored exactly the same way as strings.
Tcl 代码返回的用于获取项目的所有选项的是 Tcl 键值对的 Tcl 列表,其中所有值都是 Tcl 字符串.Tkinter 不知道哪些应该是字符串,哪些应该是 int. 所以它试图猜测:任何可以使用 int 构造函数是一个 int,其他任何东西都是一个字符串. 而你的字符串可以转换为
int
,所以它是.
And what's returned by the Tcl code to get all of the options for an item is a Tcl list of Tcl key-value pairs where all of the values are Tcl strings. Tkinter has no idea which ones were supposed to be strings, and which were supposed to be ints. So it tries to guess: any string that can be converted to an int with the int
constructor is an int, anything else is a string. And your string can be converted to an int
, so it is.
当然,这很hacky,但它通常会做你想做的事情,而且当它做的时候它会让事情变得更方便,并且非常hacky但通常可以方便地做你想做的事情"几乎是 tkinter 的定义.
Of course this is pretty hacky, but it usually does what you want, and it makes things more convenient when it does, and "pretty hacky but usually does what you want conveniently" is almost the definition of tkinter.
然而,我认为它应该认识到,虽然 '123_456'
是一个完全有效的 Python 整数文字,它不是一个可以由 Tcl 创建的字符串对于一个整数,所以它不应该尝试解析它.
However, I think it ought to recognize that, while '123_456'
is a perfectly valid Python integer literal, it's not a string that could ever be created by Tcl for an integer, so it shouldn't try to parse that.
如果您想查看执行此操作的代码:ttk.TreeView.item
调用 ttk._val_or_dict
,它调用 tkinter._splitdict
和 ttk._tclobj_to_py
作为值转换器.
If you want to see the code that does this: ttk.TreeView.item
calls ttk._val_or_dict
, which calls tkinter._splitdict
with ttk._tclobj_to_py
as a value-converter.
但是为什么 _val_or_dict
不在单个键值对上运行转换器?老实说,我找不到这样做的充分理由.但事实并非如此,因此我们可以利用这一事实来解决问题.
But why doesn't _val_or_dict
run the converter over a single key-value pair? I can't honestly see a good reason for this. But it doesn't, so we can take advantage of that fact to work around the problem.
这篇关于tkinter 树视图行显示值与下划线的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!