如何在单击按钮时禁用文本抖动?

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

我正在 Tkinter、Python 中使用按钮。

问题是,当我单击一个按钮时,按钮的文本会抖动。这可能是这个小部件的默认行为,我不知道如何禁用它并使其静态。

python tkinter button widget
2个回答
3
投票

我假设您的意思是当您单击按钮时浮雕从凸起变为凹陷。

这是我在 http://wiki.tcl.tk/1048 上找到的内容(单击“显示讨论”即可查看):

不幸的是,单击时使用的浮雕是硬编码的(如 'sunken'),所以你不能在不破解 Tk 的情况下为每个小部件配置它 按钮绑定的内部结构。

因此,解决此问题的最简单方法是始终使按钮看起来凹陷

MyButton = Tkinter.Button(
    self.frame, 
    text = "Foobar", 
    command = self.foobar, 
    relief=Tkinter.SUNKEN
)

这样做的缺点是它可能会使按钮看起来没有反应。

您还可以使用按钮以外的小部件作为可点击项目(由 Joel Cornett 建议)。这是一个简单的示例,其中标签用作按钮:

import Tkinter

class main:
        def __init__(self,root):
                # make a label with some space around the text
                self.lbl1 = Tkinter.Label(root,
                                          width = 16, height = 4,
                                          text = "Foobar")                
                self.lbl1.pack()

                # Call a function when lbl1 is clicked
                # <Button-1> means a left mouse button click
                self.lbl1.bind("<Button-1>", self.yadda)
                self.lbl1.bind("<Enter>", self.green)
                self.lbl1.bind("<Leave>", self.red)

        def yadda(self, event):
                self.lbl1.config(text="Clicked!")

        def green(self, event):
                self.lbl1.config(bg="green")

        def red(self,event):
                self.lbl1.config(bg="red")

if __name__ == "__main__":
    root = Tkinter.Tk()
    main(root)
    root.mainloop() 

0
投票

为了保留它作为参考,我采用了 @Junuxx 代码并对其进行了修改,以创建我认为是 Ttk 按钮的直接替代品。我重新配置了一些选项,使其行为尽可能接近 Ttk 按钮:

from tkinter import Event
from tkinter.ttk import Widget, Label

class FlatButton(Label):
    '''This label behaves like a button, without click animation

    By default the label has no borders

    It can be used like a button, with the same initial values. Please consider
    however that this is still a label for styling.

    Took inspiration from https://stackoverflow.com/a/10674950/3368201

    Options comparison:

    - Some options are common to both and behave the same: class, compound,
        cursor, image, style, text, textvariable, underline, width
    - Some are common to both, but behave differently:
        - takefocus -> it has a different default value; managed in __init__
                       (point #2)
    - Some are only present in BUTTON:
        - command -> it is managed in a more "pythonic" way using a global
                     wrapper and special cases in bind, unbind and configure.
                     It is also managed in __init__ (point #1)
    - Some are only present in LABEL; these values can be redefined in the
        __init__ call or through configure,: anchor (default value changed to
        'center'), background, font, foreground, justify, padding, relief,
        wraplength, borderwidth
    '''

    @staticmethod
    def overriden_default_states() -> dict[str, Any]:
        '''Provide default states for properties

        These values will be set when not passed in __init__

        Returns:
            dict[str, Any]: The dictionary with the properties and their value
        '''
        return {
                'takefocus': True,
                'anchor': 'center'
            }

    def __init__(self, parent: Widget = None, **kw):
        '''Construct a Ttk Button-like widget with the provided parent.

        This is in fact a Label, with some button behavior implemented inside.

        See class description for more info on what is allowed

        Args:
            parent (Widget, optional): The parent widget. Defaults to None.
        '''
        # 1) Manually manage command
        self._command = kw.pop('command', None)

        # 2) If not provided, set overriden_default_states
        for k, v in self.overriden_default_states().items():
            if k not in kw:
                kw[k] = v

        # Create the button
        super().__init__(parent, **kw)

        # All events in _click_binds will trigger a command
        self._click_binds = {'<Button-1>': [], '<space>': []}

        # Bind them to the special wrapper function
        for seq in self._click_binds.keys():
            super().bind(seq, lambda ev, seq=seq: self.click_event(seq, ev))

    # ------------------------
    # Command management

    def click_event(self, sequence: str, event: Event):
        '''The _btn_pressed_sequence was triggered

        Args:
            event (Event): The event data
        '''
        for b in self._click_binds.get(sequence, []):
            b(event)

        self.invoke()

    def invoke(self) -> Any:
        '''If there is a command, call it

        If the button is disabled nothing will be done

        Returns:
            Any: The command return value if it is executed, otherwise None
        '''
        if self._command and not self.instate(['disabled']):
            return self._command()

    def bind(self, sequence=None, func=None, add=None):
        '''Overriding bind to extract the _btn_pressed_sequence
        '''
        if sequence in self._click_binds.keys():
            if (not func) or (not add):
                self._click_binds[sequence].clear()
            if func:
                self._click_binds[sequence].append(func)
            result = '__unsupported__'
        else:
            result = super().bind(sequence, func, add)

        return result

    def unbind(self, sequence, funcid=None):
        '''Overriding unbind to extract the _btn_pressed_sequence
        '''
        if sequence in self._click_binds.keys():
            self._click_binds[sequence].clear()
        else:
            super().unbind(sequence, funcid)

    def configure(self, cnf=None, **kw):
        '''Overriding unbind to extract the command
        '''
        if 'command' in kw:
            self._command = kw.pop('command', None)
        return self.configure(cnf, kw)

默认外观是一个平面按钮,但是你可以在构造函数中将其更改为

relief='raised'
,然后将其用作普通按钮:

def command(self):
    print("Clicked command!")

def yadda(self, event):
    print("Clicked yadda!")

btn = FlatButton(root, text='aaa', relief='raised', command=command)
btn.pack()
btn.bind("<Button-1>", self.yadda)

然后该对象将在启用和禁用状态下正确管理命令和绑定,并且单击时不会移动

与“真实”按钮的区别:

  • 没有“焦点”亮点
  • 它有一些附加功能(例如
    anchor
    foreground
    属性)
  • 风格上继承于
    TLable
© www.soinside.com 2019 - 2024. All rights reserved.