Como obter a entrada do widget de texto Tkinter?

98

Como obter a entrada do Tkinter no Textwidget?

EDITAR

Eu fiz esta pergunta para ajudar outras pessoas com o mesmo problema - essa é a razão pela qual não existe um código de exemplo. Esse problema estava me incomodando por horas e usei essa pergunta para ensinar outras pessoas. Por favor , não avalie como se fosse uma pergunta real - a resposta é o que importa.

xxmbabanexx
fonte

Respostas:

132

Para obter a entrada do Tkinter na caixa de texto, você deve adicionar mais alguns atributos à .get()função normal . Se tivermos uma caixa de texto myText_Box, este é o método para recuperar sua entrada.

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

A primeira parte "1.0"significa que a entrada deve ser lida a partir da linha um, caractere zero (ou seja: o primeiro caractere). ENDé uma constante importada que é definida para a string "end". A ENDparte significa ler até que o final da caixa de texto seja alcançado. O único problema com isso é que ele realmente adiciona uma nova linha à nossa entrada. Então, para consertar, devemos mudar ENDpara end-1c(Obrigado Bryan Oakley ) O -1cexclui 1 caractere, enquanto -2csignificaria excluir dois caracteres e assim por diante.

def retrieve_input():
    input = self.myText_Box.get("1.0",'end-1c')
xxmbabanexx
fonte
20
Você deve fazer "end-1c"ou END+"1c", caso contrário, obterá a nova linha extra que o widget de texto sempre adiciona.
Bryan Oakley
2
@xxmbabanexx: Não, "-1c" significa "menos um caractere".
Bryan Oakley
2
Isto é o que você quer:.get('1.0', 'end-1c')
Honest Abe
1
Obrigado! Só por curiosidade, se eu fosse escrever end+1c, isso acrescentaria uma nova linha ao código? Por último, Bryan e Honest Abe, muito obrigado a vocês por me ajudarem com minhas perguntas simples sobre Tkinter e Python. Você realmente me ajudou a obter uma compreensão mais profunda do idioma e sempre foi cortês, rápido e, o melhor de tudo, conhecedor. Tenho certeza de que seu conselho vai me ajudar enquanto eu mudo para o ensino médio e além!
xxmbabanexx
1
O exemplo que você adicionou não funciona. As aspas 'end-1c'são necessárias para que seja uma única string. 'end'é um alias para o índice após o último caractere. Então, se 'end'fosse '3.8', 'end-1c'seria '3.7'. Eu quero recomendar novamente a revisão: Índices de widget de texto .
Honest Abe
19

Aqui está como fiz isso com o 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()

com isso, quando eu digitei "blá blá" no widget de texto e apertei o botão, tudo o que eu digitei foi impresso. Então, acho que essa é a resposta para armazenar a entrada do usuário do widget de texto na variável.

Skarga
fonte
9

Para obter a entrada do Tkinter na caixa de texto em Python 3, o programa de nível de aluno completo usado por mim é o seguinte:

#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
fonte
6

Para obter a string em um Textwidget, pode-se simplesmente usar o getmétodo definido para o Textqual aceita 1 a 2 argumentos starte endposições de caracteres text_widget_object.get(start, end=None),. Se apenas startfor passado e endnão for passado, retorna apenas o único caractere posicionado em start, se end for passado também, retorna todos os caracteres entre as posições starte endcomo string.

Existem também strings especiais, que são variáveis para o Tk subjacente. Um deles seria "end"ou tk.ENDque representa a posição variável do último caractere no Textwidget. Um exemplo seria retornar todo o texto no widget, com text_widget_object.get('1.0', 'end')ou text_widget_object.get('1.0', 'end-1c')se você não quiser o último caractere de nova linha.

Demo

Veja a demonstração abaixo que seleciona os personagens entre as posições fornecidas com 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
fonte
2

Eu acho que esta é a melhor maneira-

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)

Ao pressionar o botão, o valor no campo de texto seria impresso. Mas certifique-se de importar o ttk separadamente.

O código completo para um aplicativo básico é-

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
fonte
0

Eu enfrentei o problema de obter o texto inteiro do widget de Texto e a solução a seguir funcionou para mim:

txt.get(1.0,END)

Onde 1.0 significa primeira linha, o caractere zero (ou seja, antes da primeira!) É a posição inicial e END é a posição final.

Agradecimentos a Alan Gauld neste link

Javad Norouzi
fonte
-3

Digamos que você tenha um Textwidget chamado my_text_widget.

Para obter informações do, my_text_widgetvocê pode usar oget função.

Vamos supor que você importou tkinter. Vamos definir my_text_widgetprimeiro, vamos torná-lo apenas um widget de texto simples.

my_text_widget = Text(self)

Para obter a entrada de um textwidget, você precisa usar a getfunção, ambos, texte os entrywidgets têm isso.

input = my_text_widget.get()

O motivo de salvá-lo em uma variável é para usá-lo no processo posterior, por exemplo, testando o que é a entrada.

Adam Rajczakowski
fonte
1
Esta resposta está incorreta. O método Textwidget getrequer pelo menos um argumento.
Bryan Oakley