Làm cách nào để lấy dữ liệu đầu vào từ Tkinter Text Widget?


98

Làm cách nào để nhận đầu vào Tkinter từ Texttiện ích?

BIÊN TẬP

Tôi đặt câu hỏi này để giúp những người khác có cùng vấn đề - đó là lý do tại sao không có mã ví dụ. Vấn đề này đã làm tôi lo lắng trong nhiều giờ và tôi đã sử dụng câu hỏi này để dạy những người khác. Vui lòng không đánh giá nó như thể nó là một câu hỏi thực sự - câu trả lời mới là điều quan trọng.

Câu trả lời:


132

Để nhận đầu vào Tkinter từ hộp văn bản, bạn phải thêm một vài thuộc tính nữa vào .get()hàm bình thường . Nếu chúng ta có một hộp văn bản myText_Box, thì đây là phương thức để lấy đầu vào của nó.

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

Phần đầu tiên, "1.0"có nghĩa là đầu vào phải được đọc từ dòng một, ký tự không (nghĩa là: ký tự đầu tiên). ENDlà một hằng số đã nhập được đặt thành chuỗi "end". Phần ENDcó nghĩa là đọc cho đến khi đạt đến cuối hộp văn bản. Vấn đề duy nhất với điều này là nó thực sự thêm một dòng mới vào đầu vào của chúng tôi. Vì vậy, để sửa nó, chúng ta nên thay đổi ENDthành end-1c(Cảm ơn Bryan Oakley ) -1cXóa 1 ký tự, trong khi -2ccó nghĩa là xóa hai ký tự, v.v.

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

20
Bạn nên làm "end-1c"hoặc END+"1c", nếu không, bạn sẽ nhận được dòng mới bổ sung mà tiện ích văn bản luôn thêm vào.
Bryan Oakley

2
@xxmbabanexx: Không, "-1c" có nghĩa là "trừ một ký tự".
Bryan Oakley

2
Đây là những gì bạn muốn:.get('1.0', 'end-1c')
Honest Abe

1
Cảm ơn! Chỉ vì tò mò, nếu tôi viết end+1csẽ thêm một dòng mới vào mã? Cuối cùng, Bryan và Honest Abe, cảm ơn các bạn rất nhiều vì đã giúp tôi giải đáp các câu hỏi đơn giản về Tkinter và Python. Bạn đã thực sự giúp tôi hiểu sâu hơn về ngôn ngữ này, và luôn lịch sự, nhanh chóng, và tốt nhất là - hiểu biết. Tôi chắc chắn rằng lời khuyên của bạn sẽ giúp ích cho tôi khi tôi chuyển sang học trung học và cao hơn nữa!
xxmbabanexx

1
Ví dụ bạn đã thêm không hoạt động. Các dấu ngoặc kép xung quanh 'end-1c'là cần thiết để nó là một chuỗi đơn. 'end'là một bí danh cho chỉ mục sau ký tự cuối cùng. Vì vậy, nếu 'end''3.8'sau đó 'end-1c'sẽ được '3.7'. Một lần nữa tôi muốn khuyên bạn nên xem lại: Chỉ số tiện ích con văn bản .
Honest Abe

19

Đây là cách tôi đã làm điều đó với 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()

cùng với đó, khi tôi nhập "blah blah" trong tiện ích văn bản và nhấn nút, bất cứ thứ gì tôi đã nhập sẽ được in ra. Vì vậy, tôi nghĩ rằng đó là câu trả lời cho việc lưu trữ dữ liệu đầu vào của người dùng từ tiện ích Văn bản thành biến.


9

Để nhận đầu vào Tkinter từ hộp văn bản trong python 3, tôi đã sử dụng chương trình cấp sinh viên hoàn chỉnh như sau:

#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

Để lấy chuỗi trong một Textwidget, người ta có thể chỉ cần sử dụng getphương thức được định nghĩa để Textchấp nhận 1 đến 2 đối số là startendvị trí của các ký tự text_widget_object.get(start, end=None),. Nếu chỉ startđược truyền và endkhông được truyền, nó chỉ trả về một ký tự duy nhất được đặt tại vị trí start, nếu end cũng được truyền, nó trả về tất cả các ký tự ở giữa các vị trí startenddưới dạng chuỗi.

Ngoài ra còn có các chuỗi đặc biệt, đó là các biến của Tk bên dưới. Một trong số chúng sẽ là "end"hoặc tk.ENDđại diện cho vị trí thay đổi của ký tự cuối cùng trong Textwidget. Một ví dụ sẽ là trả về tất cả văn bản trong tiện ích con, có text_widget_object.get('1.0', 'end')hoặc text_widget_object.get('1.0', 'end-1c')nếu bạn không muốn ký tự dòng mới cuối cùng.

Bản giới thiệu

Xem phần minh họa dưới đây chọn các ký tự ở giữa các vị trí nhất định bằng thanh trượt:

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

Tôi nghĩ đây là cách tốt hơn-

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)

Khi nhấn nút, giá trị trong trường văn bản sẽ được in. Nhưng hãy chắc chắn rằng Bạn nhập ttk riêng biệt.

Các mã đầy đủ cho một ứng dụng cơ bản là-

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

Tôi đã đối mặt với vấn đề gettng toàn bộ văn bản từ tiện ích Văn bản và giải pháp sau đã phù hợp với tôi:

txt.get(1.0,END)

Trong đó 1,0 có nghĩa là dòng đầu tiên, ký tự thứ 0 (tức là trước chữ đầu tiên!) Là vị trí bắt đầu và END là vị trí kết thúc.

Cảm ơn Alan Gauld trong liên kết này


-3

Giả sử rằng bạn có một Textwidget được gọi là my_text_widget.

Để nhận đầu vào từ my_text_widgetbạn có thể sử dụng gethàm.

Giả sử rằng bạn đã nhập tkinter. Hãy xác định my_text_widgettrước, hãy biến nó thành một widget văn bản đơn giản.

my_text_widget = Text(self)

Để nhận đầu vào từ một textwidget, bạn cần sử dụng getchức năng này, cả hai textentrywidget đều có chức năng này.

input = my_text_widget.get()

Lý do chúng tôi lưu nó vào một biến là để sử dụng nó trong quá trình tiếp theo, chẳng hạn như kiểm tra đầu vào là gì.


1
Câu trả lời này không chính xác. Các Textphụ tùng getphương pháp đòi hỏi ít nhất một đối số.
Bryan Oakley
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.