I try to search for Python keywords (print, for, if, while....) in tkinter Tetx widget, but my code found both keywords and words, which contains keywords and i have to eliminate this words. Thanks for help.
My code:
import tkinter as Tk
def search(word):
try:
pos = t.search(word,"insert", stopindex="end")
col, line = pos.split(".")
except ValueError:
print("all")
else:
print(pos)
t.mark_set("insert","%i.%i"%(int(col),int(int(line)+len(word))))
search(word)
main=Tk.Tk()
t = Tk.Text(main)
t.pack()
t.insert("insert","word in tkinter")
t.mark_set("insert","1.0")
search("in")
main.mainloop()
Related
Why does the search fail when taking a string from a tk-inter text box?
The search works fine if I define the keyword as a string.
Minimal example:
import tkinter as tk
root = tk.Tk()
string="banana\napplepie\napple\n"
def searchcall():
textboxcontent=textExample.get("1.0","end")
keyword=filterbox.get("1.0","end")
keyword="apple" # search works as expected
print("keyword",keyword)
print("is keyword in textbox",keyword in textboxcontent)
for elem in textboxcontent.split():
print("seaching for",keyword,"in",elem,keyword in elem)
textExample=tk.Text(root, height=10)
textExample.insert(1.0,string)
textExample.pack()
filterbox=tk.Text(root, height=1)
filterbox.insert(1.0,"apple")
filterbox.pack()
btnRead=tk.Button(root, height=1, width=11, text="search",
command=searchcall)
btnRead.pack()
root.mainloop()
The problem is that tk inter appends a line break "\n" at the end when you read the contents of a widget.
Remove the "\n" at the end of the strings. For example, with strip
keyword=filterbox.get("1.0","end").strip()
you can also choose to read everything but the last character like this (source):
keyword=filterbox.get("1.0",'end-1c')
I am making a text editor in tkinter for code, and I want to loop through every single word in the ScrolledText, and then change the color of it depending which word it is, but how?
I've already searched it up and found nothing that helped me. I also tried it on myself but I didn't know how to loop through the words forever (since while True made the program stop responding) and I don't know how to change the text color for only one bit.
This is all the code of my editor, some variables are defined in different functions:
def bie_save():
bie_file_read = open(bie_file,"r")
contents = bie_file_read.read()
bie_file_read.close()
data = text_area.get("1.0",tk.END + "-1c")
bie_file_file = open(bie_file,"w")
bie_file_file.write(data)
bie_file_file.close()
def builtin_editor(file,protype,proname):
global bie_file
bie_file = file
bie = tk.Tk()
bie.title("FIDE - Editor")
bie.geometry("800x450")
global text_area
text_area = st.ScrolledText(bie,width=800,height=450)
text_area.pack()
bie_file_read = open(bie_file,"r")
contents = bie_file_read.read()
bie_file_read.close()
text_area.insert("1.0",contents)
menu = tk.Menu(bie)
bie.config(bg=bg_theme,menu=menu)
fileMenu = tk.Menu(menu)
menu.add_cascade(label="File",menu=fileMenu)
fileMenu.add_command(label="Save",command=bie_save)
fileMenu.add_separator()
fileMenu.add_command(label="Exit")
bie.mainloop()
I want it like when you type "pass" it changes to orange or something like that, but if you type something else it won't.
I want to make a program that show me the divisors of the number introduced in a text box using python tkinter GUI and store the results into a plain text file.
I don't how to get the value from the text box. I understood that is something linked with get() , I read something but I still don't get it.
Here is the code:
from tkinter import *
def create_file():
file_object = open("C:/Users/valis/Desktop/Divisors.txt","w+")
def evaluate():
show_after= Label(text= "Check your Desktop !")
show_after.pack(pady=2, anchor=SW)
create_file()
#Windows size and Title
window = Tk()
window.title("Show Divisors")
window.geometry("300x100")
message = Label(window, text="Enter a number : ")
message.pack(pady=2, anchor=NW)
textbox_input = Text(window,height=1, width=11)
textbox_input.pack(padx= 2,pady= 2, anchor=NW)
window.mainloop()
The code isn't complete, so what should I do ?
As you said, you will use the get() function but with some additional attributes.
If we have a text box textbox_input, then you can return its input using this line:
test_input = textbox_input.get("1.0",END)
The first part, "1.0" means that the input should be read from line one, character zero (ie: the very first character). END is an imported constant which is set to the string "end". The END part means to read until the end of the text box is reached.
Reference: This answer.
I try to create an update of my text widget in tkinter .
def affichage_update ():
with open('archives/monitor1_loc35L.txt') as monitor1, open('archives/monitor2_loc35L.txt') as monitor2:
s= Scrollbar(generalites)
T= Text(generalites,bg='powder blue',width=450,height=350,font=('arial',14,'bold'))
s.pack(side=RIGHT, fill=Y)
T.pack(side=LEFT, fill=Y)
s.config(command=T.yview)
T.config(yscrollcommand=s.set)
while True:
line1 = monitor1.readline()
if len(line1) == 0:
break
line1 = line1.strip().split()
line2 = monitor2.readline()
line2 = line2.strip().split()
T.insert(END, f'{line1[0]:15}\t {line1[1]:10}\t\t {line2[1]:10}\n')
T.after(1000, affichage_update)
affichage_update()
I would like help to find a solution to the automatic update of the content of my Text widget for example every 1 second
thanks
My answer should help you 2 ways here.
To show you what a minimum example looks like.
To provide some detail on how to use after().
Please in the future use a MCVE for questions. You will need your imports a root window and the minimum amount of code needed to reproduce the problem.
This example should help:
import tkinter as tk
generalites = tk.Tk()
s = tk.Scrollbar(generalites)
T = tk.Text(generalites)
s.pack(side="right", fill="y")
T.pack(side="left", fill="y")
s.config(command=T.yview)
T.config(yscrollcommand=s.set)
def affichage_update():
with open('archives/monitor1_loc35L.txt') as monitor1, open('archives/monitor2_loc35L.txt') as monitor2:
while True:
line1 = monitor1.readline()
if len(line1) == 0:
break
line1 = line1.strip().split()
line2 = monitor2.readline()
line2 = line2.strip().split()
T.insert("end", f'{line1[0]:15}\t {line1[1]:10}\t\t {line2[1]:10}\n')
T.after(1000, affichage_update)
affichage_update()
generalites.mainloop()
my code is so long and I have minimized it :
generalites is a tab of the notebook
so I think I can't write the last line : generalites.mainloop()
because there is'nt yet the end of my code
at the first picture, I must to write data into labelframe
add data into labelframe
and I will to recieve the informations and write it into text by textfiles
like this picture
data in Text widget
How to justify the values listed in drop-down part of a ttk.Combobox? I have tried justify='center' but that seems to only configure the selected item. Could use a resource link too if there is, I couldn't find it.
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
import tkinter.ttk as ttk
except ImportError:
import Tkinter as tk
import ttk
if __name__ == '__main__':
root = tk.Tk()
cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2))
cbb.pack()
root.mainloop()
I have a one-liner solution. Use the .option_add() method after declaring ttk.Combobox. Example:
cbb = ttk.Combobox(root, justify='center', values=(0, 1, 2)) # original
cbb.option_add('*TCombobox*Listbox.Justify', 'center') # new line added
Here's one pure Python way that gets close to what you want. The items in the dropdown list all get justified to fit within the Combobox's width (or a default value will be used).
Update
Part of the reason the initial version of my answer wasn't quite right was because the code assumed that a fixed-width font was being used. That's not the case on my test platform at least, so I've modified the code to actually measure the width of values in pixels instead of whole characters, and do essentially what it did originally, but in those units of string-length measure.
import tkinter as tk
import tkinter.font as tkFont
from tkinter import ttk
class CenteredCombobox(ttk.Combobox):
DEFAULT_WIDTH = 20 # Have read that 20 is the default width of an Entry.
def __init__(self, master=None, **kwargs):
values = kwargs.get('values')
if values:
entry = ttk.Entry(None) # Throwaway for getting the default font.
font = tkFont.Font(font=entry['font'])
space_width = font.measure(' ')
entry_width = space_width * kwargs.get('width', self.DEFAULT_WIDTH)
widths = [font.measure(str(value)) for value in values]
longest = max(entry_width, *widths)
justified_values = []
for value, value_width in zip(values, widths):
space_needed = (longest-value_width) / 2
spaces_needed = int(space_needed / space_width)
padding = ' ' * spaces_needed
justified_values.append(padding + str(value))
kwargs['values'] = tuple(justified_values)
super().__init__(master, **kwargs)
root = tk.Tk()
ccb = CenteredCombobox(root, justify='center', width=10, values=('I', 'XLII', 'MMXVIII'))
ccb.pack()
root.mainloop()
(Edit: Note that this solution works for Tcl/Tk versions 8.6.5 and above. #CommonSense notes that some tkinter installations may not be patched yet,
and this solution will not work).
In Tcl ( I don't know python, so one of the python people can edit the question).
A combobox is an amalgamation of an 'entry' widget and a 'listbox' widget. Sometimes to make the configuration changes you want, you need to access the internal widgets directly.
Tcl:
% ttk::combobox .cb -values [list a abc def14 kjsdf]
.cb
% pack .cb
% set pd [ttk::combobox::PopdownWindow .cb]
.cb.popdown
% set lb $pd.f.l
.cb.popdown.f.l
% $lb configure -justify center
Python:
cb = ttk.Combobox(value=['a', 'abc', 'def14', 'kjsdf'])
cb.pack()
pd = cb.tk.call('ttk::combobox::PopdownWindow', cb)
lb = cb.tk.eval('return {}.f.l'.format(pd))
cb.tk.eval('{} configure -justify center'.format(lb))
Some caveats. The internals of ttk::combobox are subject to change.
Not likely, not anytime soon, but in the future, the hard-coded .f.l
could change.
ttk::combobox::PopdownWindow will force the creation of the listbox when it is called. A better method is to put the centering adjustment into
a procedure and call that procedure when the combobox/listbox is mapped.
This will run for all comboboxes, you will need to check the argument
in the proc to make sure that this is the combobox you want to adjust.
proc cblbhandler { w } {
if { $w eq ".cb" } {
set pd [ttk::combobox::PopdownWindow $w]
set lb $pd.f.l
$lb configure -justify center
}
}
bind ComboboxListbox <Map> +[list ::cblbhandler %W]
After digging through combobox.tcl source code I've come up with the following subclass of ttk.Combobox. JustifiedCombobox justifies the pop-down list's items almost precisely after1 pop-down list's been first created & customized and then displayed. After the pop-down list's been created, setting self.justify value to a valid one will again, customize the justification almost right after the pop-down list's first been displayed. Enjoy:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
from tkinter import ttk
except:
import Tkinter as tk
import ttk
class JustifiedCombobox(ttk.Combobox):
"""
Creates a ttk.Combobox widget with its drop-down list items
justified with self.justify as late as possible.
"""
def __init__(self, master, *args, **kwargs):
ttk.Combobox.__init__(self, master, *args, **kwargs)
self.justify = 'center'
def _justify_popdown_list_text(self):
self._initial_bindtags = self.bindtags()
_bindtags = list(self._initial_bindtags)
_index_of_class_tag = _bindtags.index(self.winfo_class())
# This dummy tag needs to be unique per object, and also needs
# to be not equal to str(object)
self._dummy_tag = '_' + str(self)
_bindtags.insert(_index_of_class_tag + 1, self._dummy_tag)
self.bindtags(tuple(_bindtags))
_events_that_produce_popdown = tuple([ '<KeyPress-Down>',
'<ButtonPress-1>',
'<Shift-ButtonPress-1>',
'<Double-ButtonPress-1>',
'<Triple-ButtonPress-1>',
])
for _event_name in _events_that_produce_popdown:
self.bind_class(self._dummy_tag, _event_name,
self._initial_event_handle)
def _initial_event_handle(self, event):
_instate = str(self['state'])
if _instate != 'disabled':
if event.keysym == 'Down':
self._justify()
else:
_ = self.tk.eval('{} identify element {} {}'.format(self,
event.x, event.y))
__ = self.tk.eval('string match *textarea {}'.format(_))
_is_click_in_entry = bool(int(__))
if (_instate == 'readonly') or (not _is_click_in_entry):
self._justify()
def _justify(self):
self.tk.eval('{}.popdown.f.l configure -justify {}'.format(self,
self.justify))
self.bindtags(self._initial_bindtags)
def __setattr__(self, name, value):
self.__dict__[name] = value
if name == 'justify':
self._justify_popdown_list_text()
def select_handle():
global a
_selected = a['values'][a.current()]
if _selected in ("left", "center", "right"):
a.justify = _selected
if __name__ == '__main__':
root = tk.Tk()
for s in ('normal', 'readonly', 'disabled'):
JustifiedCombobox(root, state=s, values=[1, 2, 3]).grid()
a = JustifiedCombobox(root, values=["Justify me!", "left", "center", "right"])
a.current(0)
a.grid()
a.bind("<<ComboboxSelected>>", lambda event: select_handle())
root.mainloop()
1 It basically makes use of bindtag event queue. This was mostly possible thanks to being able to creating a custom bindtag.