¿Cómo obtener la entrada del widget de texto de Tkinter?

98

¿Cómo obtener la entrada de Tkinter desde el Textwidget?

EDITAR

Hice esta pregunta para ayudar a otros con el mismo problema, esa es la razón por la que no hay un código de ejemplo. Este problema me había estado preocupando durante horas y usé esta pregunta para enseñar a otros. Por favor , no lo califique como si fuera una pregunta real, la respuesta es lo que importa.

xxmbabanexx
fuente

Respuestas:

132

Para obtener la entrada de Tkinter desde el cuadro de texto, debe agregar algunos atributos más a la .get()función normal . Si tenemos un cuadro de texto myText_Box, este es el método para recuperar su entrada.

def retrieve_input():
    input = self.myText_Box.get("1.0",END)

La primera parte "1.0"significa que la entrada debe leerse desde la línea uno, carácter cero (es decir, el primer carácter). ENDes una constante importada que se establece en la cadena "end". La ENDparte significa leer hasta llegar al final del cuadro de texto. El único problema con esto es que en realidad agrega una nueva línea a nuestra entrada. Entonces, para solucionarlo, debemos cambiar ENDa end-1c(Gracias Bryan Oakley ) El -1celimina 1 carácter, mientras -2cque significaría eliminar dos caracteres, y así sucesivamente.

def retrieve_input():
    input = self.myText_Box.get("1.0",'end-1c')
xxmbabanexx
fuente
20
Debería hacerlo "end-1c"o END+"1c", de lo contrario, obtendrá la nueva línea adicional que el widget de texto siempre agrega.
Bryan Oakley
2
@xxmbabanexx: No, "-1c" significa "menos un carácter".
Bryan Oakley
2
Esto es lo que quieres:.get('1.0', 'end-1c')
Honest Abe
1
¡Gracias! Solo por curiosidad, si end+1ctuviera que escribir, ¿agregaría una nueva línea al código? Por último, Bryan y Honest Abe, muchas gracias por ayudarme con mis sencillas preguntas sobre Tkinter y Python. Realmente me ha ayudado a obtener una comprensión más profunda del idioma y siempre ha sido cortés, rápido y, lo mejor de todo, conocedor. ¡Estoy seguro de que sus consejos me ayudarán a medida que avance hacia la escuela secundaria y más allá!
xxmbabanexx
1
El ejemplo que agregaste no funciona. Las comillas 'end-1c'son necesarias para que sea una sola cadena. 'end'es un alias para el índice después del último carácter. Entonces, si 'end'fuera '3.8'entonces 'end-1c'sería '3.7'. Quiero recomendar nuevamente revisar: Índices de widgets de texto .
Honest Abe
19

Así es como lo hice con Python 3.5.2:

from tkinter import *
root=Tk()
def retrieve_input():
    inputValue=textBox.get("1.0","end-1c")
    print(inputValue)

textBox=Text(root, height=2, width=10)
textBox.pack()
buttonCommit=Button(root, height=1, width=10, text="Commit", 
                    command=lambda: retrieve_input())
#command=lambda: retrieve_input() >>> just means do this when i press the button
buttonCommit.pack()

mainloop()

con eso, cuando escribí "bla bla" en el widget de texto y presioné el botón, todo lo que escribí se imprimió. Entonces creo que esa es la respuesta para almacenar la entrada del usuario desde el widget de texto a la variable.

Skarga
fuente
9

Para obtener la entrada de Tkinter desde el cuadro de texto en Python 3, el programa completo de nivel de estudiante que utilizo es el siguiente:

#Imports all (*) classes,
#atributes, and methods of tkinter into the
#current workspace

from tkinter import *

#***********************************
#Creates an instance of the class tkinter.Tk.
#This creates what is called the "root" window. By conventon,
#the root window in Tkinter is usually called "root",
#but you are free to call it by any other name.

root = Tk()
root.title('how to get text from textbox')


#**********************************
mystring = StringVar()

####define the function that the signup button will do
def getvalue():
##    print(mystring.get())
#*************************************

Label(root, text="Text to get").grid(row=0, sticky=W)  #label
Entry(root, textvariable = mystring).grid(row=0, column=1, sticky=E) #entry textbox

WSignUp = Button(root, text="print text", command=getvalue).grid(row=3, column=0, sticky=W) #button


############################################
# executes the mainloop (that is, the event loop) method of the root
# object. The mainloop method is what keeps the root window visible.
# If you remove the line, the window created will disappear
# immediately as the script stops running. This will happen so fast
# that you will not even see the window appearing on your screen.
# Keeping the mainloop running also lets you keep the
# program running until you press the close buton
root.mainloop()
Abdul Wahid
fuente
6

Para obtener la cadena en un Textwidget, simplemente se puede usar el getmétodo definido para el Textcual acepta de 1 a 2 argumentos como starty endposiciones de caracteres text_widget_object.get(start, end=None),. Si solo startse pasa y endno se pasa, devuelve solo el carácter individual posicionado en start, si también end se pasa, devuelve todos los caracteres entre posiciones starty endcomo cadena.

También hay cadenas especiales, que son variables para el Tk subyacente. Uno de ellos sería "end"o tk.ENDque representa la posición variable del último carácter en el Textwidget. Un ejemplo sería devolver todo el texto en el widget, con text_widget_object.get('1.0', 'end')o text_widget_object.get('1.0', 'end-1c')si no desea el último carácter de nueva línea.

Manifestación

Vea la demostración a continuación que selecciona los caracteres entre las posiciones dadas con controles deslizantes:

try:
    import tkinter as tk
except:
    import Tkinter as tk


class Demo(tk.LabelFrame):
    """
    A LabeFrame that in order to demonstrate the string returned by the
    get method of Text widget, selects the characters in between the
    given arguments that are set with Scales.
    """

    def __init__(self, master, *args, **kwargs):
        tk.LabelFrame.__init__(self, master, *args, **kwargs)
        self.start_arg = ''
        self.end_arg = None
        self.position_frames = dict()
        self._create_widgets()
        self._layout()
        self.update()


    def _create_widgets(self):
        self._is_two_args = tk.Checkbutton(self,
                                    text="Use 2 positional arguments...")
        self.position_frames['start'] = PositionFrame(self,
                                    text="start='{}.{}'.format(line, column)")
        self.position_frames['end'] = PositionFrame(   self,
                                    text="end='{}.{}'.format(line, column)")
        self.text = TextWithStats(self, wrap='none')
        self._widget_configs()


    def _widget_configs(self):
        self.text.update_callback = self.update
        self._is_two_args.var = tk.BooleanVar(self, value=False)
        self._is_two_args.config(variable=self._is_two_args.var,
                                    onvalue=True, offvalue=False)
        self._is_two_args['command'] = self._is_two_args_handle
        for _key in self.position_frames:
            self.position_frames[_key].line.slider['command'] = self.update
            self.position_frames[_key].column.slider['command'] = self.update


    def _layout(self):
        self._is_two_args.grid(sticky='nsw', row=0, column=1)
        self.position_frames['start'].grid(sticky='nsew', row=1, column=0)
        #self.position_frames['end'].grid(sticky='nsew', row=1, column=1)
        self.text.grid(sticky='nsew', row=2, column=0,
                                                    rowspan=2, columnspan=2)
        _grid_size = self.grid_size()
        for _col in range(_grid_size[0]):
            self.grid_columnconfigure(_col, weight=1)
        for _row in range(_grid_size[1] - 1):
            self.grid_rowconfigure(_row + 1, weight=1)


    def _is_two_args_handle(self):
        self.update_arguments()
        if self._is_two_args.var.get():
            self.position_frames['end'].grid(sticky='nsew', row=1, column=1)
        else:
            self.position_frames['end'].grid_remove()


    def update(self, event=None):
        """
        Updates slider limits, argument values, labels representing the
        get method call.
        """

        self.update_sliders()
        self.update_arguments()


    def update_sliders(self):
        """
        Updates slider limits based on what's written in the text and
        which line is selected.
        """

        self._update_line_sliders()
        self._update_column_sliders()


    def _update_line_sliders(self):
        if self.text.lines_length:
            for _key in self.position_frames:
                self.position_frames[_key].line.slider['state'] = 'normal'
                self.position_frames[_key].line.slider['from_'] = 1
                _no_of_lines = self.text.line_count
                self.position_frames[_key].line.slider['to'] = _no_of_lines
        else:
            for _key in self.position_frames:
                self.position_frames[_key].line.slider['state'] = 'disabled'


    def _update_column_sliders(self):
        if self.text.lines_length:
            for _key in self.position_frames:
                self.position_frames[_key].column.slider['state'] = 'normal'
                self.position_frames[_key].column.slider['from_'] = 0
                _line_no = int(self.position_frames[_key].line.slider.get())-1
                _max_line_len = self.text.lines_length[_line_no]
                self.position_frames[_key].column.slider['to'] = _max_line_len
        else:
            for _key in self.position_frames:
                self.position_frames[_key].column.slider['state'] = 'disabled'


    def update_arguments(self):
        """
        Updates the values representing the arguments passed to the get
        method, based on whether or not the 2nd positional argument is
        active and the slider positions.
        """

        _start_line_no = self.position_frames['start'].line.slider.get()
        _start_col_no = self.position_frames['start'].column.slider.get()
        self.start_arg = "{}.{}".format(_start_line_no, _start_col_no)
        if self._is_two_args.var.get():
            _end_line_no = self.position_frames['end'].line.slider.get()
            _end_col_no = self.position_frames['end'].column.slider.get()
            self.end_arg = "{}.{}".format(_end_line_no, _end_col_no)
        else:
            self.end_arg = None
        self._update_method_labels()
        self._select()


    def _update_method_labels(self):
        if self.end_arg:
            for _key in self.position_frames:
                _string = "text.get('{}', '{}')".format(
                                                self.start_arg, self.end_arg)
                self.position_frames[_key].label['text'] = _string
        else:
            _string = "text.get('{}')".format(self.start_arg)
            self.position_frames['start'].label['text'] = _string


    def _select(self):
        self.text.focus_set()
        self.text.tag_remove('sel', '1.0', 'end')
        self.text.tag_add('sel', self.start_arg, self.end_arg)
        if self.end_arg:
            self.text.mark_set('insert', self.end_arg)
        else:
            self.text.mark_set('insert', self.start_arg)


class TextWithStats(tk.Text):
    """
    Text widget that stores stats of its content:
    self.line_count:        the total number of lines
    self.lines_length:      the total number of characters per line
    self.update_callback:   can be set as the reference to the callback
                            to be called with each update
    """

    def __init__(self, master, update_callback=None, *args, **kwargs):
        tk.Text.__init__(self, master, *args, **kwargs)
        self._events = ('<KeyPress>',
                        '<KeyRelease>',
                        '<ButtonRelease-1>',
                        '<ButtonRelease-2>',
                        '<ButtonRelease-3>',
                        '<Delete>',
                        '<<Cut>>',
                        '<<Paste>>',
                        '<<Undo>>',
                        '<<Redo>>')
        self.line_count = None
        self.lines_length = list()
        self.update_callback = update_callback
        self.update_stats()
        self.bind_events_on_widget_to_callback( self._events,
                                                self,
                                                self.update_stats)


    @staticmethod
    def bind_events_on_widget_to_callback(events, widget, callback):
        """
        Bind events on widget to callback.
        """

        for _event in events:
            widget.bind(_event, callback)


    def update_stats(self, event=None):
        """
        Update self.line_count, self.lines_length stats and call
        self.update_callback.
        """

        _string = self.get('1.0', 'end-1c')
        _string_lines = _string.splitlines()
        self.line_count = len(_string_lines)
        del self.lines_length[:]
        for _line in _string_lines:
            self.lines_length.append(len(_line))
        if self.update_callback:
            self.update_callback()


class PositionFrame(tk.LabelFrame):
    """
    A LabelFrame that has two LabelFrames which has Scales.
    """

    def __init__(self, master, *args, **kwargs):
        tk.LabelFrame.__init__(self, master, *args, **kwargs)
        self._create_widgets()
        self._layout()


    def _create_widgets(self):
        self.line = SliderFrame(self, orient='vertical', text="line=")
        self.column = SliderFrame(self, orient='horizontal', text="column=")
        self.label = tk.Label(self, text="Label")


    def _layout(self):
        self.line.grid(sticky='ns', row=0, column=0, rowspan=2)
        self.column.grid(sticky='ew', row=0, column=1, columnspan=2)
        self.label.grid(sticky='nsew', row=1, column=1)
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(1, weight=1)


class SliderFrame(tk.LabelFrame):
    """
    A LabelFrame that encapsulates a Scale.
    """

    def __init__(self, master, orient, *args, **kwargs):
        tk.LabelFrame.__init__(self, master, *args, **kwargs)

        self.slider = tk.Scale(self, orient=orient)
        self.slider.pack(fill='both', expand=True)


if __name__ == '__main__':
    root = tk.Tk()
    demo = Demo(root, text="text.get(start, end=None)")

    with open(__file__) as f:
        demo.text.insert('1.0', f.read())
    demo.text.update_stats()
    demo.pack(fill='both', expand=True)
    root.mainloop()
Nae
fuente
2

Creo que esta es una mejor manera

variable1=StringVar() # Value saved here

def search():
  print(variable1.get())
  return ''

ttk.Entry(mainframe, width=7, textvariable=variable1).grid(column=2, row=1)

ttk.Label(mainframe, text="label").grid(column=1, row=1)

ttk.Button(mainframe, text="Search", command=search).grid(column=2, row=13)

Al presionar el botón, se imprime el valor en el campo de texto. Pero asegúrese de importar el ttk por separado.

El código completo para una aplicación básica es-

from tkinter import *
from tkinter import ttk

root=Tk()
mainframe = ttk.Frame(root, padding="10 10 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)


variable1=StringVar() # Value saved here

def search():
  print(variable1.get())
  return ''

ttk.Entry(mainframe, width=7, textvariable=variable1).grid(column=2, row=1)

ttk.Label(mainframe, text="label").grid(column=1, row=1)

ttk.Button(mainframe, text="Search", command=search).grid(column=2, row=13)

root.mainloop()
bhaskar
fuente
0

Me enfrenté al problema de obtener el texto completo del widget de texto y la siguiente solución funcionó para mí:

txt.get(1.0,END)

Donde 1.0 significa primera línea, el carácter cero (es decir, antes de la primera) es la posición inicial y FIN es la posición final.

Gracias a Alan Gauld en este enlace

Javad Norouzi
fuente
-3

Digamos que tienes un Textwidget llamado my_text_widget.

Para obtener información del my_text_widget, puede usar la getfunción.

Supongamos que ha importado tkinter. Definamos my_text_widgetprimero, hagámoslo simplemente un widget de texto simple.

my_text_widget = Text(self)

Para obtener información de un textwidget, debe usar la getfunción, ambos, texty los entrywidgets la tienen.

input = my_text_widget.get()

La razón por la que lo guardamos en una variable es para usarlo en el proceso posterior, por ejemplo, probando cuál es la entrada.

Adam Rajczakowski
fuente
1
Esta respuesta es incorrecta. El método del Textwidget getrequiere al menos un argumento.
Bryan Oakley