如何在 Python Tkinter 的按钮下方移动单选按钮的文本标签?

Posted

技术标签:

【中文标题】如何在 Python Tkinter 的按钮下方移动单选按钮的文本标签?【英文标题】:How can I move the text label of a radiobutton below the button in Python Tkinter? 【发布时间】:2017-05-23 21:46:47 【问题描述】:

我想知道是否有办法将单选按钮的标签文本移动到不同的区域,例如在实际按钮下方。

下面是一些使用我正在使用的网格放置的单选按钮的示例:

from tkinter import *
from tkinter import ttk


class MainGUI(Frame):

    def __init__(self, parent):
        self.parent = parent
        Frame.__init__(self, parent, background="white")
        self.mainframe = ttk.Frame(root, padding="8 8 12 12")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)
        ttk.Radiobutton(self.mainframe, text="Button 1", value=0).grid(column=1, row=2)
        ttk.Radiobutton(self.mainframe, text="Button 2", value=1).grid(column=2, row=2)
        ttk.Radiobutton(self.mainframe, text="Button 3", value=2).grid(column=3, row=2)
        ttk.Radiobutton(self.mainframe, text="Button 4", value=3).grid(column=4, row=2)

if __name__ == '__main__':
    root = Tk()
    root.geometry("300x100")
    app = MainGUI(root)
    root.mainloop()

下面是代码运行时的框架图:

如您所见,默认设置在按钮的一侧,但我正在寻找一种方法来移动下面的文本,我似乎找不到任何解决这个问题的方法!

谢谢,拉杰

【问题讨论】:

问得好问题!欢迎来到 *** :) 您可能也想使用 tour :) 【参考方案1】:

没有选项可以在单选按钮中设置文本位置,所以我能想到的最简单的解决方法是删除单选按钮文本并在其下方放置一个标签。

此外,我宁愿让MainGUI 类继承自Tk 而不是Frame,这样您就不必在if __name__ == '__main__': 部分创建根窗口,但这只是一个建议。

from tkinter import *
from tkinter import ttk

class MainGUI(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.geometry("300x100")
        self.configure(background="white")
        self.mainframe = ttk.Frame(self, padding="8 8 12 12")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)
        ttk.Radiobutton(self.mainframe,  value=0).grid(column=1, row=2)
        ttk.Label(self.mainframe, text="Button 1").grid(column=1, row=3, padx=4)
        ttk.Radiobutton(self.mainframe,  value=1).grid(column=2, row=2)
        ttk.Label(self.mainframe, text="Button 2").grid(column=2, row=3, padx=4)
        ttk.Radiobutton(self.mainframe,  value=2).grid(column=3, row=2)
        ttk.Label(self.mainframe, text="Button 3").grid(column=3, row=3, padx=4)
        ttk.Radiobutton(self.mainframe,  value=3).grid(column=4, row=2)
        ttk.Label(self.mainframe, text="Button 4").grid(column=4, row=3, padx=4)
        self.mainloop()

if __name__ == '__main__':
    app = MainGUI()

备注:为了得到这张图片,我还使用了ttk.Style 来在 linux 中获得更好的结果。

【讨论】:

【参考方案2】:

我的想法是尝试修改 ttk.RadioButton 的布局元素或元素的选项。见http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-layouts.html

其元素的布局似乎由一个标签组成,即在焦点内,即在指示器内,即在填充内(参见下面的变量 rbLayout)。 Radiobutton.indicator 的 side 选项值被保留。 Radiobutton.label 的锚选项显示为空白。我认为改变这两个选项中的任何一个都可能得到你想要的。您还必须将选项“style=your_customed_stylename”添加到您的 ttk.Radiobutton 声明中。

>>> import tkinter.ttk as ttk
>>> s = ttk.Style()
>>> rb = ttk.Radiobutton(None, text='RB1')
>>> rbClass = rb.winfo_class()
>>> rbClass
'TRadiobutton'
>>> rbLayout = s.layout('TRadiobutton')
>>> rbLayout
[('Radiobutton.padding', 'sticky': 'nswe', 'children': [('Radiobutton.indicator', 'sticky': '', 'side': 'left'), ('Radiobutton.focus', 'children': [('Radiobutton.label', 'sticky': 'nswe')], 'sticky': '', 'side': 'left')])]
>>> type(rbLayout)
<class 'list'>

更新:

    我认为 rbLayout 变量显示默认情况下 Radiobutton.padding 包含两个子元素,即 Radiobutton.indicator 和 Radiobutton.focus,它们是定位的 在 Radiobutton.padding 的左侧。此外, Radiobutton.focus 包含 Radiobutton.label。更正我的 较早的解释。 为了实现所描述的布局,我认为 Radiobutton.indicator 的 'side' 键应该有值 'top' 和 'sticky' 键应该有 值'n'。此外,Radiobutton.focus 的 'side' 键应该有 值 'bottom' 和 'sticky' 值应该是 's'。 我创建了一个脚本来实施这些更改。请参见下面的代码。 但是,它没有用。我很惊讶单选按钮布局 没变。不明白为什么它不起作用。

希望有更多知识的人能解释一下为什么对 Radiobutton 元素布局的修改没有更改为所需的布局。

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root.geometry("300x100")

s = ttk.Style()
m = s.layout('TRadiobutton')
print('TRadiobutton.Layout : Default')
print(m , "\n")

# Change to default Radiobutton.indicator elements
list(list(m[0])[1]['children'][0])[1]['side'] = 'top'
list(list(m[0])[1]['children'][0])[1]['sticky'] = 'n'

# Change to default Radiobutton.focus elements
list(list(m[0])[1]['children'][1])[1]['side']='bottom'
list(list(m[0])[1]['children'][1])[1]['sticky']='s'

print('TRadiobutton.Layout : Amended')
print(m, "\n")

frame1 = ttk.Frame(root)
frame1.grid()
rb1 = ttk.Radiobutton(frame1, text="Button 1")
rb1.grid()

root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)

更新 2:解决方案

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root.geometry("300x100")

s = ttk.Style()
s.theme_use('default')

print('TRadiobutton.Layout : Default')
print(s.layout('TRadiobutton'), "\n")

s.layout('TRadiobutton',
         [('Radiobutton.padding',
           'children':
            [('Radiobutton.indicator', 'side': 'top', 'sticky': ''), # Just need to change indicator's 'side' value
             ('Radiobutton.focus', 'side': 'left',
                                    'children':
                                    [('Radiobutton.label', 'sticky': 'nswe')],
                                    'sticky': '')],
            'sticky': 'nswe')])

print('TRadiobutton.Layout : Amended')
print(s.layout('TRadiobutton'), "\n")

frame1 = ttk.Frame(root)
frame1.grid()
rb1 = ttk.Radiobutton(frame1, text="Button 1")
rb1.grid()

root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)

非常感谢 :) j_4321 根据我建议的方法构建的最新解决方案。我已经在我之前的代码中实现了它(见上文)并且它可以工作。我想强调以下几点:

    我的代码显示对单选按钮的默认样式“TRAdiobutton”的布局所做的更改,而不是创建具有更改布局的新样式。这种差异的优势似乎克服了 j_4321 第二种解决方案提到的缺点。也就是说,它适用于所有 ttk 主题('clam'、'alt'、'default'、'classic'),而不仅仅适用于 'clam' 和 'alt'。至少这适用于我的 Linux 16.04 平台。 我之前的代码中的错误是我创建了一个新的 s.layout() 实例(即 m = s.layout())并更改了它的布局,而不是实际更改默认 Radiobutton 样式 s 的布局.layout('TRAdiobutton')。我从 j_4321 的解决方案中了解到,可以通过添加小部件布局的更改细节作为元组 ttk.Style.layout(小部件的默认样式名称)中的第二项来更改默认样式的布局,即 ttk.Style.layout(widget 的默认样式名称 eg 'TRAdiobutton', [changed layout details of widget]). 要将 Radiobutton 指示器的位置更改为显示在其标签顶部,将 Radiobutton.indicator 的“side”值更改为“top”只需要。更改 Radiobutton.focus 的“side”值对 Radiobutton 的布局没有影响。

【讨论】:

您需要在参数中将修改后的布局传递给s.layout:请参阅我的第二个答案以获取工作示例。 @j_4321 非常感谢!我从您的解决方案中学习并更新了我的代码(请参阅更新 2:解决方案)。另外,请注意我的新发现,它克服了您提到的限制(适用于所有 ttk.Style 主题)和观察(只需要更改指标的“侧面”值)。【参考方案3】:

正如 Sun Bear 所建议的,另一种获取按钮下方单选按钮标签的方法是自定义 ttk 样式:

from tkinter import *
from tkinter import ttk

class MainGUI(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.geometry("300x100")
        self.configure(background="white")
        self.mainframe = ttk.Frame(self, padding="8 8 12 12")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)
        style = ttk.Style(self)
        style.theme_use('clam')
        # create custom radiobutton style layout
        style.layout('CustomRadiobutton', 
                     [('Radiobutton.padding',
                       'children': 
                           [('Radiobutton.indicator', 
                             'side': 'top', 'sticky': ''), # changed side from left to top
                            ('Radiobutton.focus',
                             'children': [('Radiobutton.label', 'sticky': 'nswe')],
                              'side': 'top', # changed side from left to top
                              'sticky': '')],
                        'sticky': 'nswe')])
        style.configure('TFrame', background="white")
        style.configure('CustomRadiobutton', background="white")
        ttk.Radiobutton(self.mainframe, style='CustomRadiobutton',
        text="Button 1", value=0).grid(column=1, row=2, padx=4)
        ttk.Radiobutton(self.mainframe, style='CustomRadiobutton',
        text="Button 2", value=1).grid(column=2, row=2, padx=4)
        ttk.Radiobutton(self.mainframe, style='CustomRadiobutton',
        text="Button 3", value=2).grid(column=3, row=2, padx=4)
        ttk.Radiobutton(self.mainframe, style='CustomRadiobutton',
        text="Button 4", value=3).grid(column=4, row=2, padx=4)
        self.mainloop()

if __name__ == '__main__':
    app = MainGUI()

但是,这不适用于所有 ttk 主题。它适用于 clamalt,但提供了在 linux 中无法使用 classicdefault 选择的按钮。

【讨论】:

以上是关于如何在 Python Tkinter 的按钮下方移动单选按钮的文本标签?的主要内容,如果未能解决你的问题,请参考以下文章

Python里tkinter如何重置单选按钮?

如何使用 tkinter 按钮在 python 中写入文件?

python tkinter如何设置组件在窗口中的位置,比如说一个按钮,我希望这个按钮在窗口的左边,上边………

你如何使用tkinter按钮重启python程序?

如何使用 Tkinter 按钮运行 Python 脚本?

如何在没有按钮的情况下关闭tkinter窗口而不完全关闭Python?