Tkinter display class list text - python-3.x

I have the following piece of code: I am trying to get the text from function showText to actually appear in the window
from tkinter import *
import wikipedia
from nltk.tokenize import sent_tokenize, word_tokenize
import time
subject = wikipedia.page("Assembly language")
#print(p.url)
#print(p.title)
plain_text = subject.content
plain_text_words = word_tokenize(plain_text)
class Window(Frame):
def __init__(self, master= None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title('Test')
self.pack(fill=BOTH, expand =1)
quitButton = Button(self, text = 'Exit', command=self.client_exit)
quitButton.place(x=500, y=300)
menu = Menu(self.master)
self.master.config(menu=menu)
file = Menu(menu)
menu.add_cascade(label='File', menu=file)
file.add_command(label='Run', command=self.showText)
file.add_command(label='Exit', command=self.client_exit)
help_menu = Menu(menu)
menu.add_cascade(label='Help', menu=help_menu)
help_menu.add_command(label='About')
def showText(self):
for i in range (0, len(plain_text_words)):
words = [i]
time.sleep(3)
words.pack()
def client_exit(self):
exit()
root = Tk()
w = 600 # width of the window
h = 370 # height of the window
# get screen width and height
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
# calculate x and y coordinates for the Tk root window
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
The piece that's causing me grief is this bit:
def showText(self):
for i in range (0, len(plain_text_words)):
words = [i]
time.sleep(3)
words.pack()
I am trying to get each piece of text to show as individual words on the window but no matter how I try and do it, I get an error. I have tried various things such as converting to lists etc Hoping someone can help..
PS: You will need to download the nltk dataset before this code will run

First of all, your pack function misses the brackets.
Second, your var words is a list. Not a tkinter widget. You can only pack tkinter widgets.
To solve it you need to add the list to a text widget for example.

Related

How to change the button position when pressed in tkinter python

please tell me how to change the position of the button in tkinter. I predicted that it could be done by button['padx' = 4], but it doesn't work. Do you know how to do it?
from tkinter import ttk
import random
window = tk.Tk()
window.geometry('512x512')
def click():
pass
button = ttk.Button(
text="No",
command=click
).pack(padx=5, pady=15)
window.mainloop()
I instead assigned 2 variables to random integers, and then updated the position of the button with those variables. If you want the random position to be a wider area increase the number "100" in "random_int".
from tkinter import *
import random
window = Tk()
window.geometry('512x512')
x = 5
y = 15
def click():
random_int = random.randint(0, 100)
x = (random_int)
random_int = random.randint(0, 100)
y = (random_int)
button.place(x=x, y=y)
button = Button(text="No", command=click)
button.pack(padx=5, pady=15)
window.mainloop()

Drag Drop List in Tkinter

from tkinter import *
import tkinter as tk
root = tk.Tk()
def add_many_songs():
# Loop thru to fill list box
for song in range(11):
playlist_box.insert(END, song)
playlist_box =tk.Listbox(root,bg="black", fg="green", width=60, selectbackground="green", selectforeground='black',font = 20)
playlist_box.grid(row=0, column=0)
add_many_songs()
class DragDropListbox(tk.Listbox):
""" A Tkinter listbox with drag'n'drop reordering of entries. """
def __init__(self, master, **kw):
kw['selectmode'] = tk.SINGLE
tk.Listbox.__init__(self, master, kw)
self.bind('<Button-1>', self.setCurrent)
self.bind('<B1-Motion>', self.shiftSelection)
self.curIndex = None
def setCurrent(self, event):
self.curIndex = self.nearest(event.y)
def shiftSelection(self, event):
i = self.nearest(event.y)
if i < self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i+1, x)
self.curIndex = i
elif i > self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i-1, x)
self.curIndex = i
##I found this code that does drag and drop features within tkinter list. I got it to work with the example code. However, I am not able to get it to work within the attached code. I am still learning Python.
You should use the class DragDropListbox instead of tk.Listbox when creating playlist_box:
import tkinter as tk
def add_many_songs():
# Loop thru to fill list box
for song in range(11):
playlist_box.insert(tk.END, song)
class DragDropListbox(tk.Listbox):
""" A Tkinter listbox with drag'n'drop reordering of entries. """
def __init__(self, master, **kw):
kw['selectmode'] = tk.SINGLE
tk.Listbox.__init__(self, master, kw)
self.bind('<Button-1>', self.setCurrent)
self.bind('<B1-Motion>', self.shiftSelection)
self.curIndex = None
def setCurrent(self, event):
self.curIndex = self.nearest(event.y)
def shiftSelection(self, event):
i = self.nearest(event.y)
if i < self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i+1, x)
self.curIndex = i
elif i > self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i-1, x)
self.curIndex = i
root = tk.Tk()
playlist_box = DragDropListbox(root,bg="black", fg="green", width=60, selectbackground="green", selectforeground='black',font = 20)
playlist_box.grid(row=0, column=0)
add_many_songs()
root.mainloop()
Note that it is not recommended to import tkinter like below:
from tkinter import *
import tkinter as tk
Just use import tkinter as tk.

Python - How to switch frames in a Tkinter window

I want to switch frames in a Tkinter window but the previous frame always stays visible in the background.
This is the code I have:
from tkinter import *
class frame(Frame):
def __init__(self,display):
Frame.__init__(self,display)
l = Label(self,text="frame1")
l.pack()
class frame2(Frame):
def __init__(self,display):
Frame.__init__(self,display)
l = Label(self,text="frame2")
l.pack()
class test(Tk):
def __init__(self):
Tk.__init__(self)
f = frame(self)
f.grid(row=0)
f2 = frame2(self)
f2.grid(row=0)
f.tkraise()
t = test()
t.mainloop()
This works if the layout of the two frames is the same but if I add another label to the second frame, it will still be visible in the Background. Is there a way to switch frames so that only elements from the raised frame are visible?
As requested, this is what I used to fix my problem:
from tkinter import *
class frame(Frame):
def __init__(self,display):
Frame.__init__(self,display)
l = Label(self,text="frame1")
l.pack()
class frame2(Frame):
def __init__(self,display):
Frame.__init__(self,display)
l = Label(self,text="frame2")
l.pack()
class test(Tk):
def __init__(self):
Tk.__init__(self)
f2 = frame2(self)
f2.grid(row=0)
#To raise the first frame, I used the following
frame2.grid_remove()
f = frame(self)
f.grid(row=0)
t = test()
t.mainloop()

Tkinter Text widget tag_add does not work second time

I am writing my first python app for the last 20 years. I have a problem with the tag_add() function of the Tkinter Text widget. Adding a tag just works the first time, but not the second time. I checked with tag_names() if my tag got deleted on unchecking the "Highlight Errors" checkbutton. And it is deleted. It is even re-added on checking the checkbutton again, but the text is not colored on second attempt.
Anyone an idea?
As its the first python code for years, do you have feedback to the way I have implemented and structured it? (Sorry cant get away from CamelCase)
Thanks in advance
SLi
from Tkinter import Tk, BOTH, END, N, W, S, TOP, BOTTOM, INSERT, LEFT, RIGHT, SUNKEN, RAISED, X, Y, PanedWindow, Frame, LabelFrame, Scrollbar, Checkbutton, Entry, Button, Label, Text, Menu, IntVar
from ScrolledText import ScrolledText
class Application(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initializeUiVariables()
self.doWindowSetup()
self.createWidgets()
self.doColorSetup()
def doWindowSetup(self):
self.parent.title('PACE Client Log Viewer')
self.screenWidth = self.parent.winfo_screenwidth()
self.screenHeight = self.parent.winfo_screenheight()
desiredWindowWidth = (self.screenWidth * 1.0)
desiredWindowHeight = (self.screenHeight * 1.0)
x = (self.screenWidth / 2) - (desiredWindowWidth / 2)
y = (self.screenHeight / 2) - (desiredWindowHeight / 2)
self.parent.geometry('%dx%d+%d+%d' % (desiredWindowWidth, desiredWindowHeight, x, y))
def initializeUiVariables(self):
self.fontSize = 12
self.highlightErrors = IntVar()
def createWidgets(self):
panedWindow = PanedWindow(sashrelief=RAISED)
panedWindow.pack(fill=BOTH, expand=1)
self.wText = ScrolledText(panedWindow)
self.wText.config(font=("consolas", self.fontSize))
self.wText.pack(side=LEFT, fill=BOTH, expand=True)
panedWindow.add(self.wText, minsize=(self.screenWidth * 0.75))
self.wText.insert(END, "2018-09-28 11:15:03 GMT - my.app.id (ERROR): Class:CertChecker:error: No certificate loaded. Load certificate before continuing.\n2018-09-28 11:15:07 GMT - my.app.id (INFO): Class:PerformInitialization: begin - version 0.3.10")
frameToolbar = Frame(panedWindow, padx=10)
frameToolbar.pack(side=LEFT, fill=BOTH, expand=True)
panedWindow.add(frameToolbar)
# Highlight Options
frameHighlightOptions = LabelFrame(frameToolbar, text="Highlight", padx=5, pady=5)
frameHighlightOptions.pack(side=TOP, fill=BOTH)
cbErrors = Checkbutton(frameHighlightOptions, text="Errors", anchor=W, padx=5, justify=LEFT, variable=self.highlightErrors, command=self.onHighlightErrors)
cbErrors.pack(side=TOP, fill=X)
def doColorSetup(self):
self.wText.tag_config("highlightError", background="#EE2C2C", foreground="#FFFFFF") # red
def onHighlightErrors(self):
if self.highlightErrors.get() == 0:
self.wText.tag_delete("highlightError")
else:
self.highlightRow("error", "highlightError")
def highlightRow(self, pattern, tag):
self.highlightPattern(pattern, tag, True)
def highlightPattern(self, pattern, tag, highlightRow=False):
start = self.wText.index("1.0")
end = self.wText.index(END)
self.wText.mark_set("matchStart", start)
self.wText.mark_set("matchEnd", start)
self.wText.mark_set("searchLimit", end)
count = IntVar()
while True:
index = self.wText.search(pattern, "matchEnd","searchLimit", count=count, regexp=True, nocase=True)
if index == "": break
if count.get() == 0: break # degenerate pattern which matches zero-length strings
if highlightRow:
row, col = index.split('.')
self.wText.mark_set("matchStart", "%s.%s" % (int(row), 0))
else:
self.wText.mark_set("matchStart", index)
if highlightRow:
lineEndIndex = self.wText.search("\n", index, "searchLimit", count=count, regexp=False, nocase=False)
row, col = lineEndIndex.split('.')
self.wText.mark_set("matchEnd", lineEndIndex)
else:
self.wText.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
self.wText.tag_add(tag, "matchStart", "matchEnd")
def main():
root = Tk()
ex = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
When you delete the tag, you destroy all of the information associated with that tag. The next time you add the tag it has no colors associate with it, so you can't see the tag.
Instead of deleting the tag, you should just remove it from the text.
Replace this:
self.wText.tag_delete("highlightError")
... with this:
self.wText.tag_remove("highlightError", "1.0", "end")

python tkinter image layers (paste / unpaste image on background)

i have a background image using tkinter canvas,
and i'm adding images on top of it.
so far so good it works well. but what i would like to do is to be able to remove some of the forground images on demand. and when i remove some of them i would like to see the background behind them as it were before adding those forground images on it.
that would be like: paste 5 foreground images and then remove 1 or 2 of them.
so this program i have to far, adds little white filled circles at random position.
if i keep a handle on every little white circles (i can put them in variables and have them all in a list, and get their coordinates later for example). how can i remove some of them and get to see my background behind the removed whites circles ?
is it even possible ?
#!/usr/bin/env python3
from tkinter import *
from PIL import Image, ImageTk
from random import *
class App(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(self.root, height=222, width=227)
self.canvas.grid()
# small nature landscape
self.backgnd = PhotoImage( file = "images/nature.png" )
# small white circle
self.mycloud = PhotoImage( file = "images/white.png" )
backgnd_width = (self.backgnd.width()/2)
backgnd_height = (self.backgnd.height()/2)
self.canvas.create_image(backgnd_width,backgnd_height,image=self.backgnd)
def cloud(self):
pos_x = randint(1,220)
pos_y = randint(1,220)
self.canvas.create_image(pos_x,pos_y, image=self.mycloud)
app = App()
app.cloud()
app.cloud()
app.cloud()
app.cloud()
app.cloud()
app.root.mainloop()
in case it might help others here's a working solution.
i added a button that will remove each object placed on the canvas, one a a time.
(thanks for the help, Bryan Oakley)
#!/usr/bin/env python3
from tkinter import *
from PIL import Image, ImageTk
from tkinter import ttk
from random import *
class App(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(self.root, height=300, width=227)
self.canvas.grid()
self.mylist=[]
self.backgnd = PhotoImage( file = "images/nature.png" )
self.mycloud = PhotoImage( file = "images/white.png" )
backgnd_width = (self.backgnd.width()/2)
backgnd_height = (self.backgnd.height()/2)
self.canvas.create_image(backgnd_width,backgnd_height,image=self.backgnd)
# button to remove things on the canvas
button_del = ttk.Button(self.root, text='Del')
button_del['command'] = self.rem
button_del.place(x=100, y=250)
def cloud(self):
# add 5 object at random position on the canvas
for idx in range(5):
pos_x = randint(1,220)
pos_y = randint(1,220)
self.mylist.append(self.canvas.create_image(pos_x,pos_y, image=self.mycloud))
def rem(self):
# delete elements placed on the canvas
self.canvas.delete(self.mylist[-1])
self.mylist.pop()
app = App()
app.cloud()
app.root.mainloop()
made a few changes to make above code compatible with python 2:
from Tkinter import *
from PIL import Image, ImageTk
import ttk
from random import *
class App(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(self.root, height=300, width=227)
self.canvas.grid()
self.mylist=[]
self.backgnd = ImageTk.PhotoImage( Image.open("sunshine.jpg") )
self.mycloud = ImageTk.PhotoImage( Image.open("Y.png") )
backgnd_width = (self.backgnd.width()/2)
backgnd_height = (self.backgnd.height()/2)
self.canvas.create_image(backgnd_width,backgnd_height,image=self.backgnd)
# button to remove things on the canvas
button_del = ttk.Button(self.root, text='Del')
button_del['command'] = self.rem
button_del.place(x=100, y=250)
def cloud(self):
# add 5 object at random position on the canvas
for idx in range(5):
pos_x = randint(1,220)
pos_y = randint(1,220)
self.mylist.append(self.canvas.create_image(pos_x,pos_y, image=self.mycloud))
def rem(self):
# delete elements placed on the canvas
self.canvas.delete(self.mylist[-1])
self.mylist.pop()
app = App()
app.cloud()
app.root.mainloop()

Resources