簡體   English   中英

如何從 Tkinter Text Widget 獲取輸入?

[英]How to get the input from the Tkinter Text Widget?

如何從Text小部件獲取 Tkinter 輸入?

編輯

我問這個問題是為了幫助遇到同樣問題的其他人 -就是沒有示例代碼的原因。 這個問題困擾了我好幾個小時,我用這個問題來教別人。 不要把它當作一個真正的問題來評價——答案才是最重要的。

要從文本框中獲取 Tkinter 輸入,您必須向普通的.get()函數添加更多屬性。 如果我們有一個文本框myText_Box ,那么這是檢索其輸入的方法。

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

第一部分, "1.0"意味着輸入應該從第一行,字符零(即:第一個字符)讀取。 END是一個導入的常量,它被設置為字符串"end" END部分表示一直讀到文本框的末尾。 唯一的問題是它實際上為我們的輸入添加了一個換行符。 因此,為了修復它,我們應該將END更改為end-1c (感謝Bryan Oakley-1c刪除 1 個字符,而-2c表示刪除兩個字符,依此類推。

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

這是我用 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()

有了這個,當我在文本小部件中輸入“blah blah”並按下按鈕時,我輸入的任何內容都會被打印出來。 所以我認為這是將用戶輸入從 Text 小部件存儲到變量的答案。

要從 python 3 的文本框中獲取 Tkinter 輸入,我使用的完整學生級程序如下:

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

為了獲取Text小部件中的字符串,可以簡單地使用為Text定義的get方法,該方法接受 1 到 2 個參數作為字符的startend位置text_widget_object.get(start, end=None) 如果只傳遞了start而沒有傳遞end它只返回位於start處的單個字符,如果傳遞了end ,它會將startend位置之間的所有字符作為字符串返回。

還有一些特殊的字符串,它們是底層 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()

我認為這是一個更好的方法-

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。

基本應用程序完整代碼是-

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

我認為創建 Text 的簡單擴展並將text轉換為屬性是最簡潔的方法。 然后,您可以將該擴展名粘貼到您始終導入的某個文件中,並使用它代替原始的Text小部件。 通過這種方式,您不必記住、編寫、重復等所有 tkinter 使您跳過去做最簡單的事情,而是擁有一個可以在任何項目中重用的簡單界面。 您也可以對Entry執行此操作,但語法略有不同。

import tkinter as tk

root = tk.Tk()    
    
class Text(tk.Text):
    @property
    def text(self) -> str:
        return self.get('1.0', 'end-1c')
        
    @text.setter
    def text(self, value) -> None:
        self.replace('1.0', 'end-1c', value)
        
    def __init__(self, master, **kwargs):
        tk.Text.__init__(self, master, **kwargs)

#Entry version of the same concept as above      
class Entry(tk.Entry):
    @property
    def text(self) -> str:
        return self.get()
        
    @text.setter
    def text(self, value) -> None:
        self.delete(0, 'end')
        self.insert(0, value)
        
    def __init__(self, master, **kwargs):
        tk.Entry.__init__(self, master, **kwargs)      
      
textbox = Text(root)
textbox.grid()

textbox.text = "this is text" #set
print(textbox.text)           #get  

entry = Entry(root)
entry.grid()

entry.text = 'this is text'   #set
print(entry.text)             #get

root.mainloop()

我遇到了從 Text 小部件獲取整個文本的問題,以下解決方案對我有用:

txt.get(1.0,END)

其中 1.0 表示第一行,第零個字符(即在第一個之前!)是起始位置,END 是結束位置。

感謝 Alan Gauld 在此鏈接中

我確實也是為了尋找如何從 Text 小部件獲取輸入數據。 關於字符串末尾換行的問題。 您可以只使用 .strip() 因為它是一個始終是字符串的 Text 小部件。

此外,我正在共享代碼,您可以在其中看到如何創建多個 Text 小部件並將它們作為表單數據保存在字典中,然后通過單擊提交按鈕獲取該表單數據並對其進行任何操作。 我希望它可以幫助其他人。 它應該適用於任何 3.x python 並且可能也適用於 2.7。

from tkinter import *
from functools import partial

class SimpleTkForm(object):
    def __init__(self):
        self.root = Tk()

    def myform(self):
        self.root.title('My form')
        frame = Frame(self.root, pady=10)
        form_data = dict()
        form_fields = ['username', 'password', 'server name', 'database name']
        cnt = 0
        for form_field in form_fields:
            Label(frame, text=form_field, anchor=NW).grid(row=cnt,column=1, pady=5, padx=(10, 1), sticky="W")
            textbox = Text(frame, height=1, width=15)
            form_data.update({form_field: textbox})
            textbox.grid(row=cnt,column=2, pady=5, padx=(3,20))
            cnt += 1

        conn_test = partial(self.test_db_conn, form_data=form_data)
        Button(frame, text='Submit', width=15, command=conn_test).grid(row=cnt,column=2, pady=5, padx=(3,20))
        frame.pack()
        self.root.mainloop()

    def test_db_conn(self, form_data):
        data = {k:v.get('1.0', END).strip() for k,v in form_data.items()}
        # validate data or do anything you want with it
        print(data)


if __name__ == '__main__':
    api = SimpleTkForm()
    api.myform()

假設您有一個名為my_text_widgetText小部件。

要從my_text_widget獲取輸入,您可以使用get函數。

假設您已導入tkinter 讓我們先定義my_text_widget ,讓它只是一個簡單的文本小部件。

my_text_widget = Text(self)

要從text小部件獲取輸入,您需要使用get函數, textentry小部件都具有此功能。

input = my_text_widget.get()

我們將它保存到變量的原因是為了在進一步的過程中使用它,例如,測試輸入是什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM