AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76919604
Accepted
d'Elbreil Clément
d'Elbreil Clément
Asked: 2023-08-17 16:13:58 +0800 CST2023-08-17 16:13:58 +0800 CST 2023-08-17 16:13:58 +0800 CST

Python tkinter/ ttkboostrap dateentry não funciona quando no estado somente leitura

  • 772

Estou trabalhando atualmente com a biblioteca ttkbootstrap em vez da biblioteca ttk no passado. Eu costumava usar o widget ttk DateEntry no estado "somente leitura", que funcionava perfeitamente bem. No entanto, por alguns motivos, preciso parar de usar a biblioteca ttk e, em vez disso, usar a biblioteca ttkbootstrap. Então eu criei um ttkbootstrap DateEntry como dito nas documentações: https://ttkbootstrap.readthedocs.io/en/latest/styleguide/dateentry/

import ttkbootstrap as tb
from ttkbootstrap import constants

root = tb.Window()
date_entry = tb.DateEntry(root)
date_entry.pack(padx = 10, pady = 10)
date_entry["state"] = "readonly"

root.mainloop()

O estado 'somente leitura' está em vigor porque não consigo escrever com o keboard na entrada. No entanto, quando tento escolher uma nova data, a data não parece mudar, de modo que a entrada será apenas na data de hoje para sempre.

insira a descrição da imagem aqui

Eu sei que esta interação está especificamente ligada à biblioteca ttkbootstrap porque o widget dateentry funcionou perfeitamente bem na biblioteca ttk.

Tentei pesquisar no código fonte da classe DateEntry mas não encontrei nada que explicasse esse comportamento. Ainda tenho certeza de que não é impossível criar uma DateEntry somente leitura, pois é uma das coisas mais importantes que você precisa nesta biblioteca.

python
  • 3 3 respostas
  • 30 Views

3 respostas

  • Voted
  1. Best Answer
    Tranbi
    2023-08-17T16:51:08+08:002023-08-17T16:51:08+08:00

    Você não deve editar o código do ttkbootstrap. Ele seria substituído na próxima atualização.

    Você pode simplesmente criar uma nova classe herdando de DateEntry, definindo o estado da entrada no init e habilitando o campo somente quando você pressionar o botão:

    import ttkbootstrap as tb
    
    class CustomDateEntry(tb.DateEntry):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.entry["state"] = "readonly"
    
        def _on_date_ask(self):
            self.entry["state"] = "normal"
            super()._on_date_ask()
            self.entry["state"] = "readonly"
    
    root = tb.Window()
    date_entry = CustomDateEntry(root)
    date_entry.pack(padx = 10, pady = 10)
    
    root.mainloop()
    

    Editar: chamando super()._on_date_ask()em vez de escrever uma nova função, conforme sugerido por @acw1668.

    • 1
  2. Trynabal
    2023-08-17T16:33:44+08:002023-08-17T16:33:44+08:00

    O estado readonly faz com que a data só possa ser lida e não alterada/editada, então define-a como a data atual, bastante autoexplicativo, eu acho, minha pergunta seria por que não apenas se livrar da linha somente leitura desde o usuário ainda pode selecionar a data através do pop-up do calendário?

    • 0
  3. d'Elbreil Clément
    2023-08-17T16:43:01+08:002023-08-17T16:43:01+08:00

    Ok, acabei de entrar no código-fonte do ttkbootstrap DateEntry e copiar a classe e também a classe Querybox. Para evitar esse problema, expliquei que encontrei uma coisa, você deve vincular a entrada de data a uma variável de texto global. Então você pode alternar todos entry.insert(...) com o textvariable.set(...). Você também precisa transformar todas as inserções na textvariable.get(...)classe Querybox copiada.

    Aqui está a classe DateEntry:

    class DateEntry_test(ttk.Frame):
        """A date entry widget combines the `Combobox` and a `Button`
        with a callback attached to the `get_date` function.
    
        When pressed, a date chooser popup is displayed. The returned
        value is inserted into the combobox.
    
        The date chooser popup will use the date in the combobox as the
        date of focus if it is in the format specified by the
        `dateformat` parameter. By default, this format is "%Y-%m-%d".
    
        The bootstyle api may be used to change the style of the widget.
        The available colors include -> primary, secondary, success,
        info, warning, danger, light, dark.
    
        The starting weekday on the date chooser popup can be changed
        with the `firstweekday` parameter. By default this value is
        `6`, which represents "Sunday".
    
        The `Entry` and `Button` widgets are accessible from the
        `DateEntry.Entry` and `DateEntry.Button` properties.
    
        ![](../../assets/widgets/date-entry.png)
        """
    
        def __init__(
            self,
            master=None,
            dateformat=r"%x",
            firstweekday=6,
            startdate=None,
            bootstyle="",
            **kwargs,
        ):
            """
            Parameters:
    
                master (Widget, optional):
                    The parent widget.
    
                dateformat (str, optional):
                    The format string used to render the text in the entry
                    widget. For more information on acceptable formats, see https://strftime.org/
    
                firstweekday (int, optional):
                    Specifies the first day of the week. 0=Monday, 1=Tuesday,
                    etc...
    
                startdate (datetime, optional):
                    The date that is in focus when the widget is displayed. Default is
                    current date.
    
                bootstyle (str, optional):
                    A style keyword used to set the focus color of the entry
                    and the background color of the date button. Available
                    options include -> primary, secondary, success, info,
                    warning, danger, dark, light.
    
                **kwargs (Dict[str, Any], optional):
                    Other keyword arguments passed to the frame containing the
                    entry and date button.
            """
            self._dateformat = dateformat
            self._firstweekday = firstweekday
    
            self._startdate = startdate or datetime.today()
            self._bootstyle = bootstyle
            super().__init__(master, **kwargs)
    
            # add visual components
            entry_kwargs = {"bootstyle": self._bootstyle}
            if "width" in kwargs:
                entry_kwargs["width"] = kwargs.pop("width")
            self.textvariable = tk.StringVar()
            self.entry = ttk.Entry(self, textvariable=self.textvariable, **entry_kwargs)
            
            self.entry.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES)
    
            self.button = ttk.Button(
                master=self,
                command=self._on_date_ask,
                bootstyle=f"{self._bootstyle}-date",
            )
            self.button.pack(side=tk.LEFT)
    
            # starting value
            self.textvariable.set(self._startdate.strftime(self._dateformat))
    
        def __getitem__(self, key: str):
            return self.configure(cnf=key)
    
        def __setitem__(self, key: str, value):
            self.configure(cnf=None, **{key: value})
    
        def _configure_set(self, **kwargs):
            """Override configure method to allow for setting custom
            DateEntry parameters"""
    
            if "state" in kwargs:
                state = kwargs.pop("state")
                if state in ["readonly", "invalid"]:
                    self.entry.configure(state=state)
                elif state in ("disabled", "normal"):
                    self.entry.configure(state=state)
                    self.button.configure(state=state)
                else:
                    kwargs[state] = state
            if "dateformat" in kwargs:
                self._dateformat = kwargs.pop("dateformat")
            if "firstweekday" in kwargs:
                self._firstweekday = kwargs.pop("firstweekday")
            if "startdate" in kwargs:
                self._startdate = kwargs.pop("startdate")
            if "bootstyle" in kwargs:
                self._bootstyle = kwargs.pop("bootstyle")
                self.entry.configure(bootstyle=self._bootstyle)
                self.button.configure(bootstyle=[self._bootstyle, "date"])
            if "width" in kwargs:
                width = kwargs.pop("width")
                self.entry.configure(width=width)
    
            super(ttk.Frame, self).configure(**kwargs)
    
        def _configure_get(self, cnf):
            """Override the configure get method"""
            if cnf == "state":
                entrystate = self.entry.cget("state")
                buttonstate = self.button.cget("state")
                return {"Entry": entrystate, "Button": buttonstate}
            if cnf == "dateformat":
                return self._dateformat
            if cnf == "firstweekday":
                return self._firstweekday
            if cnf == "startdate":
                return self._startdate
            if cnf == "bootstyle":
                return self._bootstyle
            else:
                return super(ttk.Frame, self).configure(cnf=cnf)
    
        def configure(self, cnf=None, **kwargs):
            """Configure the options for this widget.
    
            Parameters:
    
                cnf (Dict[str, Any], optional):
                    A dictionary of configuration options.
    
                **kwargs:
                    Optional keyword arguments.
            """
            if cnf is not None:
                return self._configure_get(cnf)
            else:
                return self._configure_set(**kwargs)
    
        def _on_date_ask(self):
            """Callback for pushing the date button"""
            _val = self.entry.get() or datetime.today().strftime(self._dateformat)
            try:
                self._startdate = datetime.strptime(_val, self._dateformat)
            except Exception as e:
                print("Date entry text does not match", self._dateformat)
                self._startdate = datetime.today()
                self.entry.delete(first=0, last=tk.END)
                self.textvariable.set(self._startdate.strftime(self._dateformat))
    
            old_date = datetime.strptime(_val, self._dateformat)
    
            # get the new date and insert into the entry
            new_date = Querybox_test.get_date(
                parent=self.entry,
                startdate=old_date,
                firstweekday=self._firstweekday,
                bootstyle=self._bootstyle,
            )
            self.entry.delete(first=0, last=tk.END)
            self.textvariable.set(new_date.strftime(self._dateformat))
            self.entry.focus_force()
    

    e a classe Querybox:

    class Querybox_test:
        """This class contains various static methods that request data
        from the end user."""
    
        @staticmethod
        def get_color(
            parent=None, title="Color Chooser", initialcolor=None, **kwargs
        ):
            """Show a color picker and return the select color when the
            user pressed OK.
    
            ![](../../assets/dialogs/querybox-get-color.png)
    
            Parameters:
    
                parent (Widget):
                    The parent widget.
    
                title (str):
                    Optional text that appears on the titlebar.
    
                initialcolor (str):
                    The initial color to display in the 'Current' color
                    frame.
    
            Returns:
    
                Tuple[rgb, hsl, hex]:
                    The selected color in various colors models.
            """
            from ttkbootstrap.dialogs.colorchooser import ColorChooserDialog
    
            dialog = ColorChooserDialog(parent, title, initialcolor)
            if "position" in kwargs:
                position = kwargs.pop("position")
            else:
                position = None
            dialog.show(position)
            return dialog.result
    
        @staticmethod
        def get_date(
            parent=None,
            title=" ",
            firstweekday=6,
            startdate=None,
            bootstyle="primary",
        ):
            """Shows a calendar popup and returns the selection.
    
            ![](../../assets/dialogs/querybox-get-date.png)
    
            Parameters:
    
                parent (Widget):
                    The parent widget; the popup will appear to the
                    bottom-right of the parent widget. If no parent is
                    provided, the widget is centered on the screen.
    
                title (str):
                    The text that appears on the popup titlebar.
    
                firstweekday (int):
                    Specifies the first day of the week. `0` is Monday, `6` is
                    Sunday (the default).
    
                startdate (datetime):
                    The date to be in focus when the widget is displayed;
    
                bootstyle (str):
                    The following colors can be used to change the color of the
                    title and hover / pressed color -> primary, secondary, info,
                    warning, success, danger, light, dark.
    
            Returns:
    
                datetime:
                    The date selected; the current date if no date is selected.
            """
            chooser = DatePickerDialog(
                parent=parent,
                title=title,
                firstweekday=firstweekday,
                startdate=startdate,
                bootstyle=bootstyle,
            )
            return chooser.date_selected
    
        @staticmethod
        def get_string(
            prompt="", title=" ", initialvalue=None, parent=None, **kwargs
        ):
            """Request a string type input from the user.
    
            ![](../../assets/dialogs/querybox-get-string.png)
    
            Parameters:
    
                prompt (str):
                    A message to display in the message box above the entry
                    widget.
    
                title (str):
                    The string displayed as the title of the message box. This
                    option is ignored on Mac OS X, where platform guidelines
                    forbid the use of a title on this kind of dialog.
    
                initialvalue (Any):
                    The initial value in the entry widget.
    
                parent (Widget):
                    Makes the window the logical parent of the message box. The
                    messagebox is displayed on top of its parent window.
    
                **kwargs (Dict):
                    Other optional keyword arguments.
    
            Returns:
    
                str:
                    The string value of the entry widget.
            """
            initialvalue = initialvalue or ""
            if "position" in kwargs:
                position = kwargs.pop("position")
            else:
                position = None
            dialog = QueryDialog(
                prompt, title, initialvalue, parent=parent, **kwargs
            )
            dialog.show(position)
            return dialog._result
    
        @staticmethod
        def get_integer(
            prompt="",
            title=" ",
            initialvalue=None,
            minvalue=None,
            maxvalue=None,
            parent=None,
            **kwargs,
        ):
            """Request an integer type input from the user.
    
            ![](../../assets/dialogs/querybox-get-integer.png)
    
            Parameters:
    
                prompt (str):
                    A message to display in the message box above the entry
                    widget.
    
                title (str):
                    The string displayed as the title of the message box. This
                    option is ignored on Mac OS X, where platform guidelines
                    forbid the use of a title on this kind of dialog.
    
                initialvalue (int):
                    The initial value in the entry widget.
    
                minvalue (int):
                    The minimum allowed value.
    
                maxvalue (int):
                    The maximum allowed value.
    
                parent (Widget):
                    Makes the window the logical parent of the message box. The
                    messagebox is displayed on top of its parent window.
    
                **kwargs (Dict):
                    Other optional keyword arguments.
    
            Returns:
    
                int:
                    The integer value of the entry widget.
            """
            initialvalue = initialvalue or ""
            if "position" in kwargs:
                position = kwargs.pop("position")
            else:
                position = None
            dialog = QueryDialog(
                prompt,
                title,
                initialvalue,
                minvalue,
                maxvalue,
                datatype=int,
                parent=parent,
                **kwargs,
            )
            dialog.show(position)
            return dialog._result
    
        @staticmethod
        def get_float(
            prompt="",
            title=" ",
            initialvalue=None,
            minvalue=None,
            maxvalue=None,
            parent=None,
            **kwargs,
        ):
            """Request a float type input from the user.
    
            ![](../../assets/dialogs/querybox-get-float.png)
    
            Parameters:
    
                prompt (str):
                    A message to display in the message box above the entry
                    widget.
    
                title (str):
                    The string displayed as the title of the message box. This
                    option is ignored on Mac OS X, where platform guidelines
                    forbid the use of a title on this kind of dialog.
    
                initialvalue (float):
                    The initial value in the entry widget.
    
                minvalue (float):
                    The minimum allowed value.
    
                maxvalue (float):
                    The maximum allowed value.
    
                parent (Widget):
                    Makes the window the logical parent of the message box. The
                    messagebox is displayed on top of its parent window.
    
                **kwargs (Dict):
                    Other optional keyword arguments.
    
            Returns:
    
                float:
                    The float value of the entry widget.
            """
            initialvalue = initialvalue or ""
            if "position" in kwargs:
                position = kwargs.pop("position")
            else:
                position = None
            dialog = QueryDialog(
                prompt,
                title,
                initialvalue,
                minvalue,
                maxvalue,
                datatype=float,
                parent=parent,
                **kwargs,
            )
            dialog.show(position)
            return dialog._result
    
        @staticmethod
        def get_font(parent=None, **kwargs):
            """Request a customized font
    
            ![](../../assets/dialogs/querybox-get-font.png)
    
            Parameters:
    
                parent (Widget):
                    Makes the window the logical parent of the dialog box. The
                    dialog is displayed on top of its parent window.
    
                **kwargs (Dict):
                    Other keyword arguments.
    
            Returns:
    
                Font:
                    A font object.
            """
            if "position" in kwargs:
                position = kwargs.pop("position")
            else:
                position = None
            dialog = FontDialog(parent=parent, **kwargs)
            dialog.show(position)
            return dialog.result
    
    • 0

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve