Event for text in Tkinter text widget - python

May I know is it possible to create a event for a text in tkinter text widget?
Example, I click on a word on text box, and a small window will pop out and give a brief definition of the word.

You can add bindings to a text widget just like you can with any other widget. I think that's what you mean by "create a event".
In the following example I bind to the release of the mouse button and highlight the word under the cursor. You can just as easily pop up a window, display the word somewhere else, etc.
import Tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.text = tk.Text(self, wrap="none")
self.text.pack(fill="both", expand=True)
self.text.bind("<ButtonRelease-1>", self._on_click)
self.text.tag_configure("highlight", background="green", foreground="black")
with open(__file__, "rU") as f:
data = f.read()
self.text.insert("1.0", data)
def _on_click(self, event):
self.text.tag_remove("highlight", "1.0", "end")
self.text.tag_add("highlight", "insert wordstart", "insert wordend")
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()

Here's a simple example:
from tkinter import *
def callback(event):
info_window = Tk()
info_window.overrideredirect(1)
info_window.geometry("200x24+{0}+{1}".format(event.x_root-100, event.y_root-12))
label = Label(info_window, text="Word definition goes here.")
label.pack(fill=BOTH)
info_window.bind_all("<Leave>", lambda e: info_window.destroy()) # Remove popup when pointer leaves the window
info_window.mainloop()
root = Tk()
text = Text(root)
text.insert(END, "Hello, world!")
text.pack()
text.tag_add("tag", "1.7", "1.12")
text.tag_config("tag", foreground="blue")
text.tag_bind("tag", "<Button-1>", callback)
root.mainloop()
Clicking on "world" will pop up a small window which disappears when mouse pointer leaves the widget

Yes, it is possible. You can add a tag to a word or text region using the tag_add function, then use the tag_bind method (with a <Button> event) to make the text "clickable".
You can create a new TopLevel widget to pop up a new window in the callback function.

Related

How to create a simpledialog-like window with a combo with tkinter?

simpledialog or filedialog are widgets very convenient to use.
I would like to do the same :
modal window which pops up on screen like these simpledialogs
combo box inside
and when I select a value in combo, return this value without needing a button
Something like:
def askComboValue():
root = Tk() #how to pops up this window?
label = ttk.Label(root, text = "select your value")
label.pack()
box_value = ''
combo = ttk.Combobox(root, textvariable=box_value, values=['bla', 'bli', 'blo'])
combo.current(0)
combo.pack()
combo.bind("<<ComboboxSelected>>", returnValue) #how to catch this value?
root.grab_set_global() #is it the right way to make it modal?
root.mainloop()
return box_value #how to return this value?
Does anyone know how to deal with it?
Thanks for your help
If the function is called when there is already a tkinter window, then better use Toplevel() instead of Tk(). Also box_value should be instance of StringVar() instead. grab_set() is used instead of grab_set_global() as well.
Below is an example based on your code:
import tkinter as tk
from tkinter import ttk
def askComboValue(*values):
top = tk.Toplevel() # use Toplevel() instead of Tk()
tk.Label(top, text='Select your value').pack()
box_value = tk.StringVar()
combo = ttk.Combobox(top, textvariable=box_value, values=values)
combo.pack()
combo.bind('<<ComboboxSelected>>', lambda _: top.destroy())
top.grab_set()
top.wait_window(top) # wait for itself destroyed, so like a modal dialog
return box_value.get()
def test():
result = askComboValue('bla', 'bli', 'blo')
print(result)
root = tk.Tk()
tk.Button(root, text='Test', command=test).pack()
root.mainloop()

How to refresh the window in Tkinter?

I've been writing this program using the Tkinter module in Python3.6.2. There are buttons to to open a list of teams and a list of competitors and I'd prefer to keep the outputs in one window, however if I click the "Teams" button followed by the "Individuals" button, the two elements open one after the other.
I'm hoping to add a button that resets the window (removing the outputs, leaving just the buttons), but I haven't found any solutions online that work with my program.
from tkinter import *
import tkinter as tk
bgcol = "#0B8CFF"
class MainMenu:
def __init__(self, master):
self.master = master
master.title("Scoring System GUI")
master.geometry("500x750+75+60")
self.label = Label(master, text="GUI")
self.label.pack()
self.team_button = Button(master, text="Teams", command=self.openTeams)
self.team_button.pack()
def openTeams(self):
self.label = Label(text="Team #1:")
self.label.pack()
team1 = open("team1.csv", "r")
message = team1.read()
text = Text(root, width = "50", height = "6", fg = "#000000")
text.pack()
text.insert(END, message)
redteam.close()
Here's a photo of the current output:
You have to clear the Text widget before inserting new strings. Just insert the following line before your text.insert(...) statement:
text.delete('1.0', END)
By the way, if you only want to display a list and not edit it (as I guess is the case here) a Listbox widget if often a better choice than a Text widget.
To do that you need to create another method inside your class and parse it to another button as callback command.
def reset_func(self):
self.text.delete('1.0', END)
with this method inside when you parse it as command to your button it will clear the content in text widget .

how I can change the background color and text color of a textbox done with Tkinter?

how I can change the background color of a textbox done with Tkinter in python?
i used the code below but i can't understand why it doesn't work
from Tkinter import *
def onclick():
pass
root = Tk()
text = Text(root)
text.pack()
text.tag_add("here", "1.0", "1.4")
text.tag_add("start", "1.8", "1.13")
text.tag_config("here", background="black", foreground="green")
root.mainloop()
It does work. If you insert text:
text.insert(1.0, 'Hello World')
before calling the tag_add and tag_config methods, that tag will be attached to the inserted text. However, at the time it's currently being called, there's no index to insert the tag at, so there's effectively no tag.
If you want to modify the text contents real-time as the user types in the widget, you can bind the text widget to a keypress event, which calls a function that adds and configures tags for the text widget:
from Tkinter import *
def track_change_to_text(event):
text.tag_add("here", "1.0", "1.4")
text.tag_config("here", background="black", foreground="green")
root = Tk()
text = Text(root)
text.pack()
text.bind('<KeyPress>', track_change_to_text)
root.mainloop()
Use bg to determine the background color, when creating the text box itself:
text = Text(root, bg = 'black')

Tkinter Scrollbar in frame with multiple textframes

Question
How can I have a scrollbar which moves an entire Tkinter frame? Note: I am using Python 2.7.3.
Code and Explanation
I have this code for defining the scrollbar
scrollbar = Scrollbar(soeg)
scrollbar.pack(side=RIGHT, fill="y")
And this code for defining the textframes
h = 0
s = 0
for i in dom_nodup:
abc = dom_nodup[h]
text = Text(soeg, bg="brown", fg="white", height="10", width="60")
text.insert(INSERT, "%s \n" % abc[0])
text.insert(END, "%s \n\n\n" % abc[1])
text.pack()
h += 1
s += 1
A new textframe is created for each text entity for later easier overview (planning on having a button to show/hide the input).
The scrollbar is present but is not functional
I would recommend that you use the ScrolledText widget. It automatically adds a scrollbar to each text widget, and has the same arguments as Text. Here is a brief example of how to do it.
from Tkinter import * #Import the Tkinter module
from ScrolledText import ScrolledText #import the scrolled text module
message = "I \n am \n scroll \n able. \n\n\n\n\n\n Yes I am!"
class Application(Frame): #Create a frame for the widgets
def __init__(self, master): #initialize the grid and widgets
Frame.__init__(self,master)
self.grid()
self.widgets()
def widgets(self):
self.mytext = ScrolledText(self, width = 10) #Creates the widget
self.mytext.grid() #Places it
root = Tk()
root.title("My Text Example")
#make my screen dimensions work
root.geometry("500x1000")
app = Application(root)
root.mainloop()
For more information, please see the Tkinterbook and this question.
To make a scrollbar functional you must do two things: you must tell it which scrollable widget to scroll, and you must tell the scrollable widget which scrollbar to update with the current position.
scrollbar.configure(command=text.yview)
text.configure(yscrollcommand=scrollbar.set)

How to wait for return to be clicked with the entry widget?

I am just trying to make a non-graphic game in Tkinter but am having trouble with the entry widget. How can I wait for "<Return>" to be pressed before printing something?
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
f = Frame(master, width=500, height=300)
f.pack(fill=X, expand=True)
mt = StringVar()
menubar = Menu(master)
menubar.add_command(label="New Game", command=self.new_game)
menubar.add_command(label="Continue Game", command=self.continue_game)
master.config(menu=menubar)
maintext = Label(master, fg="blue", textvariable=mt)
maintext.pack(side=BOTTOM)
mt.set("")
self.e1 = Entry(master)
self.e1.pack()
self.e1.bind("<Return>")
self.e1.lower()
global mt
def new_game(self):
mt.set("What do you want your username to be?")
self.e1.lift()
#wait for <Return> to be pressed
mt.set("Welcome " + self.e1.get())
def continue_game(self):
mt.set("Type your username in.")
root = Tk()
app = App(root)
root.mainloop()
I want it to be when I click "New Game" on the top menubar, it shows the entry box and waits for me to type something in, and then click enter. THEN it prints out "Welcome"+(what the person types in). What actually happens is when I click New game, it immediately just prints "Welcome".
By print, I mean aet the Label at the bottom to something else, which is reffered to by "mt.set".
In GUI programs you don't wait* for something to happen, you respond to events. So, to call a function when the user presses return you would do something like:
self.e1.bind("<Return>", self._on_return)
The above will call the function _on_return when the user presses the return key.
In your specific code you don't really need a StringVar. For example, you could do this:
def __init__(self, master):
...
self.maintext = Label(master, fg="blue")
...
def _on_return(self, event):
self.maintext.configure(text="Welcome, %s" % self.e1.get())
* strictly speaking, you can wait for things, but that's not the right way to write GUI programs except under specific circumstances, such as waiting for a dialog to be dismissed.

Categories

Resources