Як отримати вхідні дані з текстового віджету Tkinter?


98

Як отримати ввід Tkinter з Textвіджета?

РЕДАГУВАТИ

Я поставив це питання, щоб допомогти іншим із тією ж проблемою - це є причиною , чому немає ні одного прикладу коду. Це питання турбувало мене годинами, і я використовував це питання, щоб навчати інших. Будь ласка , не оцінюйте це так, ніби це справжнє запитання - відповідь має значення.

Відповіді:


132

Щоб отримати вхідні дані Tkinter із текстового поля, потрібно додати ще кілька атрибутів до звичайної .get()функції. Якщо у нас є текстове поле myText_Box, то це метод отримання його вводу.

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

Перша частина "1.0"означає, що введення слід читати з першого рядка, нульового символу (тобто: самого першого символу). END- це імпортована константа, для якої встановлено рядок "end". В ENDозначає частину читати до кінця текстового поля не буде досягнутий. Єдина проблема в тому, що він насправді додає новий рядок до нашого вводу. Отже, для того, щоб це виправити, нам слід змінити ENDна end-1c(Спасибі, Брайан Оклі ). -1cВидаляє 1 символ, тоді як -2cце означатиме видалення двох символів тощо.

def retrieve_input():
    input = self.myText_Box.get("1.0",'end-1c')

20
Ви повинні зробити "end-1c"абоEND+"1c" , в іншому випадку ви отримаєте додатковий символ нового рядка , що текст віджета завжди додає.
Bryan Oakley

2
@xxmbabanexx: Ні, "-1c" означає "мінус один символ".
Bryan Oakley

2
Це те, що ви хочете:.get('1.0', 'end-1c')
Чесний Ейб

1
Дякую! Просто з цікавості, якби я писав end+1c, це додало б новий рядок до коду? Нарешті, Брайан та Чесний Ейб, дякую вам, хлопці, що допомогли мені з моїми простими запитаннями про Tkinter та Python. Ви дійсно допомогли мені глибше зрозуміти мову і завжди були ввічливими, оперативними, а найкраще - знаними. Я впевнений, що ваші поради допоможуть мені, коли я перейду до середньої школи та не тільки!
xxmbabanexx

1
Доданий вами приклад не працює. Лапки навколо 'end-1c'необхідні, щоб це був єдиний рядок. 'end'є псевдонімом для індексу після останнього символу. Так що, якщо 'end'було , '3.8'то 'end-1c'було б '3.7'. Я хочу ще раз рекомендувати переглянути: Індекси текстових віджетів .
Honest Abe

19

Ось як я це зробив з 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()

при цьому, коли я набирав "бла-бла" у текстовому віджеті та натискав кнопку, все, що я набрав, роздруковувалось. Тож я думаю, що це відповідь на збереження введеного користувачем тексту з віджета до змінної.


9

Щоб отримати вхідні дані Tkinter із текстового поля в python 3, повна програма, що використовується мною, наведена нижче:

#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()

6

Для того , щоб отримати рядок в Textміні-програмі можна просто використовувати getметод , описаний в Textякий приймає від 1 до 2 аргументів як startі endпозицію символів, text_widget_object.get(start, end=None). Якщо тільки startпередається і endне передається він повертає тільки один символ , розташований на start, якщо end буде прийнятий, а він повертає всі символи між позиціями startіend в вигляді рядка.

Існують також спеціальні рядки, які є змінними до базового Tk. Одним з них буде "end"або tk.ENDякий представляє змінну позицію останнього символу у Textвіджеті. Прикладом може бути повернення всього тексту у віджеті, з text_widget_object.get('1.0', 'end')або text_widget_object.get('1.0', 'end-1c')якщо ви не хочете останній символ нового рядка.

Демо

Див. Нижче демонстрацію, яка вибирає символи між заданими позиціями за допомогою повзунків:

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()

2

Я думаю, що це кращий спосіб -

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)

При натисканні кнопки значення в текстовому полі друкується. Але обов’язково імпортуйте ttk окремо.

Повний код для основного додатки IS -

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()

0

Я зіткнувся з проблемою отримання всього тексту з віджету Text, і мені допомогло таке рішення:

txt.get(1.0,END)

Де 1.0 означає перший рядок, нульовий символ (тобто перед першим!) Є початковою позицією, а END - кінцевою.

Дякую Алану Голду за цим посиланням


-3

Скажімо, у вас Textназивається віджет my_text_widget.

Щоб отримати вхідні дані з, my_text_widgetви можете використовуватиget функцію.

Припустимо, що ви імпортували tkinter. Давайте визначимося my_text_widgetспочатку, давайте зробимо це просто простим текстовим віджетом.

my_text_widget = Text(self)

Щоб отримати вхід з textвіджета, вам потрібно скористатися getфункцією, як у віджетів , так textі у entryвіджетах.

input = my_text_widget.get()

Причиною того, що ми зберігаємо його у змінну, є використання в подальшому процесі, наприклад, тестування на вхідні дані.


1
Ця відповідь неправильна. Метод Textвіджетів getвимагає принаймні одного аргументу.
Брайан Оклі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.