Python 如何对齐组合框下拉列表中的字符?
如何调整Python 如何对齐组合框下拉列表中的字符?,python,tkinter,combobox,tk,ttk,Python,Tkinter,Combobox,Tk,Ttk,如何调整ttk.Combobox下拉部分中列出的值?我尝试了justify='center',但这似乎只配置了所选项目。也可以使用资源链接,如果有,我找不到 try: # In order to be able to import tkinter for import tkinter as tk # either in python 2 or in python 3 import tkinter.ttk as ttk excep
ttk.Combobox
下拉部分中列出的值?我尝试了justify='center'
,但这似乎只配置了所选项目。也可以使用资源链接,如果有,我找不到
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
import tkinter.ttk as ttk
except ImportError:
import Tkinter as tk
import ttk
if __name__ == '__main__':
root = tk.Tk()
cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2))
cbb.pack()
root.mainloop()
(编辑:请注意,此解决方案适用于Tcl/Tk 8.6.5及以上版本。@常识提示,某些tkinter安装可能尚未修补,
而这个解决方案将不起作用)
在Tcl中(我不懂python,所以python中的一个人可以编辑这个问题)
组合框是“条目”小部件和“列表框”小部件的合并。有时,要进行所需的配置更改,您需要直接访问内部小部件
Tcl:
Python:
cb = ttk.Combobox(value=['a', 'abc', 'def14', 'kjsdf'])
cb.pack()
pd = cb.tk.call('ttk::combobox::PopdownWindow', cb)
lb = cb.tk.eval('return {}.f.l'.format(pd))
cb.tk.eval('{} configure -justify center'.format(lb))
一些警告。ttk::combobox
的内部结构可能会发生变化。
不太可能,不会很快,但在将来,硬编码的.f.l
可能会改变
ttk::combobox::PopdownWindow
将在调用listbox时强制创建它。更好的方法是将定心调整置于
一个过程,并在映射combobox/listbox时调用该过程
这将对所有组合框运行,您需要检查参数
在proc
中,确保这是要调整的组合框
proc cblbhandler { w } {
if { $w eq ".cb" } {
set pd [ttk::combobox::PopdownWindow $w]
set lb $pd.f.l
$lb configure -justify center
}
}
bind ComboboxListbox <Map> +[list ::cblbhandler %W]
proc cblbhandler{w}{
如果{$w eq“.cb”}{
设置pd[ttk::combobox::PopdownWindow$w]
整磅$pd.f.l
$lb配置-调整中心
}
}
绑定ComboboxListbox+[list::cblbhandler%W]
这里有一种纯Python的方法,可以接近您想要的。下拉列表中的所有项目都将对齐,以适合组合框的宽度(或使用默认值)
更新
我的答案的初始版本不太正确的部分原因是因为代码假设使用了固定宽度的字体。至少在我的测试平台上不是这样的,所以我修改了代码,以实际测量值的宽度(以像素为单位,而不是以整字符为单位),基本上是按照最初的操作,而是以字符串长度为单位进行测量
import tkinter as tk
import tkinter.font as tkFont
from tkinter import ttk
class CenteredCombobox(ttk.Combobox):
DEFAULT_WIDTH = 20 # Have read that 20 is the default width of an Entry.
def __init__(self, master=None, **kwargs):
values = kwargs.get('values')
if values:
entry = ttk.Entry(None) # Throwaway for getting the default font.
font = tkFont.Font(font=entry['font'])
space_width = font.measure(' ')
entry_width = space_width * kwargs.get('width', self.DEFAULT_WIDTH)
widths = [font.measure(str(value)) for value in values]
longest = max(entry_width, *widths)
justified_values = []
for value, value_width in zip(values, widths):
space_needed = (longest-value_width) / 2
spaces_needed = int(space_needed / space_width)
padding = ' ' * spaces_needed
justified_values.append(padding + str(value))
kwargs['values'] = tuple(justified_values)
super().__init__(master, **kwargs)
root = tk.Tk()
ccb = CenteredCombobox(root, justify='center', width=10, values=('I', 'XLII', 'MMXVIII'))
ccb.pack()
root.mainloop()
在深入研究了combobox.tcl
源代码之后,我找到了ttk.combobox
的以下子类RightedComboBox
在第一次创建和自定义并显示1个下拉列表后,几乎完全正确地调整了下拉列表的项目。创建下拉列表后,将self.justify
值再次设置为有效值,几乎在第一次显示下拉列表后即可自定义对齐。享受:
try:#为了能够为
在python 2中或python 3中将tkinter作为tk导入
从tkinter导入ttk
除:
将Tkinter作为tk导入
导入ttk
类JustifiedCombobox(ttk.Combobox):
"""
创建带有下拉列表项的ttk.Combobox小部件
尽可能晚地证明。
"""
定义初始值(self、master、*args、**kwargs):
ttk.Combobox.\uuuu init\uuuuu(self、master、*args、**kwargs)
self.justify='center'
def_justify_弹出列表_文本(self):
self.\u initial\u bindtags=self.bindtags()
_bindtags=列表(自我。\u初始\u bindtags)
_索引\u of\u class\u tag=\u bindtags.index(self.winfo\u class())
#这个伪标记需要每个对象都是唯一的,并且还需要
#不等于str(对象)
self._dummy_tag=''+str(self)
_bindtags.insert(_class_标记+1的索引_,self._dummy_标记)
self.bindtags(元组(_bindtags))
_生成的事件弹出=元组(['',
'',
'',
'',
'',
])
对于生成弹出式菜单的事件中的事件名称:
self.bind\u类(self.\u dummy\u标记、\u事件\u名称、,
自我(初始事件句柄)
定义初始事件句柄(自身、事件):
_instate=str(自['state'])
如果安装残疾人士:
如果event.keysym==“向下”:
自我证明
其他:
_=self.tk.eval('{}标识元素{}{}'。格式(self,
事件x,事件y)
__=self.tk.eval('string match*textarea{}'。格式()
_是否单击项目中的项目=布尔(int(uuu))
如果(\u instate=='readonly')或(not)为\u单击\u条目中的\u):
自我证明
def_证明(自我):
self.tk.eval('{}.popdown.f.l configure-justify{}.format(self,
自我证明)
self.bindtags(self.\u initial\u bindtags)
定义设置属性(自身、名称、值):
self.\uuuu dict\uuuu[name]=值
如果名称=='justify':
self.\u justify\u popdown\u list\u text()
def select_handle():
全球a
_所选=a['values'][a.current()]
如果在“左”、“中”、“右”中选择了“U”:
a、 justify=\u选中
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=tk.tk()
对于中的s(“正常”、“只读”、“禁用”):
JustifiedCombobox(根,状态=s,值=[1,2,3]).grid()
a=对齐组合框(根,值=[“对齐我!”、“左”、“中”、“右”])
a、 电流(0)
a、 网格()
a、 绑定(“,lambda事件:选择\u句柄())
root.mainloop()
1它基本上利用了bindtag事件队列。这主要是因为能够做到这一点。我有一个单行程序解决方案。声明ttk.Combobox
后,使用.option\u add()
方法。例如:
cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2)) # original
cbb.option_add('*TCombobox*Listbox.Justify', 'center') # new line added
“pad”是获得居中输出的方法。pad不是这样
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
from tkinter import ttk
except:
import Tkinter as tk
import ttk
class JustifiedCombobox(ttk.Combobox):
"""
Creates a ttk.Combobox widget with its drop-down list items
justified with self.justify as late as possible.
"""
def __init__(self, master, *args, **kwargs):
ttk.Combobox.__init__(self, master, *args, **kwargs)
self.justify = 'center'
def _justify_popdown_list_text(self):
self._initial_bindtags = self.bindtags()
_bindtags = list(self._initial_bindtags)
_index_of_class_tag = _bindtags.index(self.winfo_class())
# This dummy tag needs to be unique per object, and also needs
# to be not equal to str(object)
self._dummy_tag = '_' + str(self)
_bindtags.insert(_index_of_class_tag + 1, self._dummy_tag)
self.bindtags(tuple(_bindtags))
_events_that_produce_popdown = tuple([ '<KeyPress-Down>',
'<ButtonPress-1>',
'<Shift-ButtonPress-1>',
'<Double-ButtonPress-1>',
'<Triple-ButtonPress-1>',
])
for _event_name in _events_that_produce_popdown:
self.bind_class(self._dummy_tag, _event_name,
self._initial_event_handle)
def _initial_event_handle(self, event):
_instate = str(self['state'])
if _instate != 'disabled':
if event.keysym == 'Down':
self._justify()
else:
_ = self.tk.eval('{} identify element {} {}'.format(self,
event.x, event.y))
__ = self.tk.eval('string match *textarea {}'.format(_))
_is_click_in_entry = bool(int(__))
if (_instate == 'readonly') or (not _is_click_in_entry):
self._justify()
def _justify(self):
self.tk.eval('{}.popdown.f.l configure -justify {}'.format(self,
self.justify))
self.bindtags(self._initial_bindtags)
def __setattr__(self, name, value):
self.__dict__[name] = value
if name == 'justify':
self._justify_popdown_list_text()
def select_handle():
global a
_selected = a['values'][a.current()]
if _selected in ("left", "center", "right"):
a.justify = _selected
if __name__ == '__main__':
root = tk.Tk()
for s in ('normal', 'readonly', 'disabled'):
JustifiedCombobox(root, state=s, values=[1, 2, 3]).grid()
a = JustifiedCombobox(root, values=["Justify me!", "left", "center", "right"])
a.current(0)
a.grid()
a.bind("<<ComboboxSelected>>", lambda event: select_handle())
root.mainloop()
cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2)) # original
cbb.option_add('*TCombobox*Listbox.Justify', 'center') # new line added