如何证明Combobox下拉列表中的字符?

问题描述 投票:2回答:4

如何证明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()
python tkinter combobox tk ttk
4个回答
3
投票

(编辑:请注意,此解决方案适用于Tcl / Tk版本8.6.5及更高版本。@ CommonSense注意到某些tkinter安装可能尚未修补,此解决方案将无法正常工作)。

在Tcl(我不知道python,所以其中一个python人可以编辑这个问题)。

组合框是“条目”小部件和“列表框”小部件的合并。有时为了进行所需的配置更改,您需要直接访问内部小部件。

TCL:

% ttk::combobox .cb -values [list a abc def14 kjsdf]
.cb
% pack .cb
% set pd [ttk::combobox::PopdownWindow .cb]
.cb.popdown
% set lb $pd.f.l
.cb.popdown.f.l
% $lb configure -justify center

蟒蛇:

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将在调用时强制创建列表框。更好的方法是将居中调整放入一个过程,并在映射组合框/列表框时调用该过程。

这将运行所有组合框,你需要检查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]

2
投票

这是一种接近你想要的纯Python方式。下拉列表中的项目都被证明符合Combobox的宽度(或者将使用默认值)。

更新

我的答案的初始版本不太正确的部分原因是因为代码假定使用了固定宽度的字体。至少在我的测试平台上并非如此,所以我修改了代码以实际测量像素的宽度而不是整个字符,并且基本上完成它原来的工作,但是在字符串长度测量的单位中。

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()

1
投票

我有一个单线解决方案。在声明.option_add()后使用ttk.Combobox方法。例:

cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2)) # original
cbb.option_add('*TCombobox*Listbox.Justify', 'center')       # new line added

0
投票

在通过combobox.tcl源代码挖掘之后,我想出了ttk.Combobox的以下子类。 JustifiedCombobox几乎准确地证明了弹出列表的项目,首先创建并自定义然后显示1个弹出列表。创建下拉列表后,再次将self.justify值设置为有效值,几乎在首次显示弹出列表后自定义对齐。请享用:

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()

1它基本上使用了bindtag事件队列。这很可能是因为能够creating a custom bindtag

© www.soinside.com 2019 - 2024. All rights reserved.