how to use multiple frames in a canvas with scrollbar in tkinter? - python-3.x

I am building a GUI app for showing some data results.I want to show name and some details in a frame for each result I have.So I created a frame and a canvas inside of it.Now I want to place multiple frames in canvas with scrollbars but it didn't seems to work .So I tried to place results in multiple canvas but its is also not working with scrollbar.Here is a snipet of it.
from tkinter import *
class Results:
def __init__(self,master,topic = None):
self.result_frame = Frame(master, bg = '#ffffff', bd =5)
self.result_frame.place(relx=0.5,rely=0.25, relwidth = 1,relheight =
0.75, anchor ='n')
self.canvas = Canvas(self.result_frame,bg =
'#ffffff',bd=0,width=500,height=500)
self.canvas.place(relx = 0.0, rely = 0.0 )
self.sbar = Scrollbar(self.result_frame, orient = 'vertical')
self.sbar.config(command = self.canvas.yview)
self.sbar.place(relx = 0.98,width = 14 ,relheight = 0.5 )
self.canvas.configure(yscrollcommand=self.sbar.set)
self.rframe = Frame(self.canvas)
self.rframe.pack()
self.canvas.create_window((0,0), window=self.rframe, anchor="nw")
self.show_results()
def create_rcanvas(self,name,y) :
name = Canvas(self.rframe, bg = '#4da6ff')
name.place(relx=0.25,rely = y, relwidth = 0.55,height = 100)
def show_results(self):
y = 0.1
for i in range(0,10):
name = 'can'+str(i)
name = Canvas(self.canvas, bg = '#4da6ff')
name.place(relx=0.25,rely = y, relwidth = 0.55,height = 100)
y = y + 0.2
if __name__ == '__main__':
root = Tk()
root.geometry('600x600')
Results(root)
root.mainloop()
Kindly provide me solution and please try to run and check it first.

Related

Im having troubles with python(tkinter) gui with the layout

# Import module
from tkinter import *
import pyautogui, time
# Create object
root = Tk()
# Adjust size
root.geometry("350x350")
root.title("SycoBak's SpamBot")
# Add image file
bg = PhotoImage(file = "Slogo.png")
# Create Canvas
canvas1 = Canvas( root, width = 350,
height = 350)
canvas1.pack(fill = "both", expand = True)
# Display image
canvas1.create_image( 0, 0, image = bg,
anchor = "nw")
canvas1.create_text(250,250, text="SycoSpamBot")
L1 = Label(canvas1, text="Word")
L1.pack( side = LEFT)
E1 = Entry(canvas1)
E1.pack(side = RIGHT)
canvas1.create_window(100, 100, window=L1)
L2 = Label(canvas1, text="Amount")
L2.pack( side = LEFT)
E2 = Entry(canvas1)
E2.pack(side = RIGHT)
canvas1.create_window(100, 150, window=L2)
def Spammer ():
time.sleep(5)
x = 0
amount = int(E2.get())
word = E1.get()
while (amount > x):
pyautogui.typewrite(word)
pyautogui.press("enter")
x=x+1
button1 = Button(root, text = "Start", command=Spammer, bg="green")
button1_canvas = canvas1.create_window( 100, 10,
anchor = "nw",
window = button1)
root.mainloop()
Im wondering if I could make it so that the start button is at the bottom, and the word and amount labels are on the left side of a text input box.
This is how my GUI layout currently looks like. (Very Messy)
[1]: https://i.stack.imgur.com/UYvtU.png

Tkinker cursor that impacts a graph

I am not good at all at informatics.
I don't find anything on the website that explains how to change a value on a cursor that will impact a specific variable in a model that is represented in a graph. With X depending on the time (that is a loop).
We have the following easy model : X= L + Z + H and the 3 variable that are cursors.
Here is our code for a first cursor with tkinter:
from tkinter import *
def sel():
selection = "Value = " + str(var.get())
label.config(text = selection)
print(var.get())
root = Tk()
var = DoubleVar()
root = Tk()
var = DoubleVar()
scale = Scale( root, length = 150, from_=-3, to=5, variable = var)
scale.pack(anchor = CENTER)
button = Button(root, text = "Get Scale Value", command = sel)
button.pack(anchor = CENTER)
label = Label(root)
label.pack()
root.mainloop()
Thank you very much !

Python 2 tkinter, a loan window appears when it has not been called for

I have come across an issue with using the tkinter message box, when a user of my application presses the English flag and then goes to Log-out in the top right hand corner a message box appears but also another box appears with the window title 'tk', I have not made or called any such window so my theory is that the window is coming from some place with the message box or maybe its something I have mistakenly done in my code which I cant see.
here is my code below;
import tkinter
from tkinter import *
from tkinter import messagebox as box
Title_Text = 25
Title_Font = "Courier"
Font = 'Ariel'
Rest_Text = 16
Background_Colour = 'Light blue'
def EngFlag():
print('Hello world')
def LogOut1():
response = box.askquestion ('?', 'Are You Sure?')
if response == 'yes':
try:
window.destroy()
except:
Eng_window.destroy()
def back1():
Home_Screen()
def Home_Screen():
global window
window = Tk()
window.geometry('1366x768')
window.configure(background = Background_Colour)
window.title('Local Languages Learning System')
window.resizable(width=False, height=False)
try:
Eng_window.destroy()
except:
pass
Title1 = Label(window, text = 'Local Languages Home Screen', bg = Background_Colour)
Title1.config(font=("Courier", Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Question_Label = Label(window, text = 'Please Pick The Language You Wish To Learn', bg = Background_Colour)
Question_Label.config(font=(Font, Rest_Text))
Question_Label.pack()
Question_Label.place(y = 200, x = 495)
Log_Out = Button(window, text = 'Log-Out', height = 1, width = 8, command = LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
help_btn = Button(window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
English_Flag = PhotoImage(file = 'EnglishFlag.gif')
English_Flag_btn = Button(window, image = English_Flag, command = English_Home_Screen)
English_Flag_btn.pack(side = LEFT, padx = 10)
English_Flag_btn.place(y = 350, x = 300)
Polish_Flag = PhotoImage(file = 'PolishFlag.gif')
Polish_Flag_btn = Button(window, image = Polish_Flag, command = EngFlag)
Polish_Flag_btn.pack(side = LEFT, padx = 10)
Polish_Flag_btn.place(y = 350, x = 600)
Italian_Flag = PhotoImage(file = 'ItalianFlag.gif')
Italian_Flag_btn = Button(window, image = Italian_Flag, command = None)
Italian_Flag_btn.pack(side = LEFT, padx = 10)
Italian_Flag_btn.place(y = 350, x = 900)
window.mainloop()
def English_Home_Screen():
global Eng_window
Eng_window = Tk()
Eng_window.geometry('1366x768')
Eng_window.configure(background = Background_Colour)
Eng_window.title('Local Languages Learning System')
Eng_window.resizable(width=False, height=False)
window.destroy()
Title1 = Label(Eng_window, text = 'Local Languages\nEnglish Home Screen', bg = Background_Colour)
Title1.config(font=("Courier", Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Log_Out = Button(Eng_window, text = 'Log-Out', height = 1, width = 8, command = LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
Back = Button(Eng_window, text = 'Back', height = 1, width = 8, command = back1)
Back.pack()
Back.place(y = 5, x = 1210)
help_btn = Button(Eng_window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
Play_all = Button(Eng_window, text = 'Play All Games', height = 2, width = 20, command = None)
Play_all.pack()
Play_all.place(y = 100, x = 320)
Multiple_Choice = Button(Eng_window, text = 'Play Multiple Choice Game', height = 2, width = 20, command = None)
Multiple_Choice.pack()
Multiple_Choice.place(y = 100, x = 510)
Picture = Button(Eng_window, text = 'Play Picture Game', height = 2, width = 20, command = None)
Picture.pack()
Picture.place(y = 100, x = 700)
Memory = Button(Eng_window, text = 'Play Memory Game', height = 2, width = 20, command = None)
Memory.pack()
Memory.place(y = 100, x = 890)
LeaderBoard = Button(Eng_window, text = 'LeaderBoard', height = 2, width = 20, command = None)
LeaderBoard.pack()
LeaderBoard.place(y = 160, x = 600)
Home_Screen()
Apologies for it being so long but to actually see the problem you have to have all the code. Any help or fixies would be great.
Now there are several issues with your code and some I will address.
First off what you are trying to do is very complicated when using a Non-OOP method. I have re-written your code as OOP to provide some ease of use and readability.
For the most part you should avoid using global the easiest way to do this is to use class attributes instead. This allows for you to have a variable that can be seen by any method within the class.
Some helpful tips:
Do not import tkinter twice.
Instead of doing:
import tkinter
from tkinter import *
from tkinter import messagebox as box
Do this instead:
import tkinter as tk
from tkinter import messagebox
Your Try/Except function will not work as you expect as Eng_window.destroy() will not return an error regardless of if the window is there or not. So it will always attempt to destroy Eng_window and never window
Instead do this:
# This will check if the instance of Eng_self_window exist first.
if tk.Toplevel.winfo_exists(self.Eng_self_window):
self.Eng_self_window.destroy()
else:
self.window.destroy()
Let me know if you have any questions on the class set up.
It can be done using global's but its not as clean and harder to deal with.
Here I have moved your code into a class and rearranged some stuff.
import tkinter as tk
from tkinter import messagebox
class Home_Screen(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.Title_Text = 25
self.Title_Font = "Courier"
self.Font = 'Ariel'
self.Rest_Text = 16
self.Background_Colour = 'Light blue'
self.window = parent
self.window.geometry('1366x768')
self.window.configure(background = self.Background_Colour)
self.window.title('Local Languages Learning System')
#self.window.resizable(width=False, height=False)
Title1 = tk.Label(self.window, text = 'Local Languages Home Screen', bg = self.Background_Colour)
Title1.config(font=("Courier", self.Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Question_Label = tk.Label(self.window, text = 'Please Pick The Language You Wish To Learn', bg = self.Background_Colour)
Question_Label.config(font=(self.Font, self.Rest_Text))
Question_Label.pack()
Question_Label.place(y = 200, x = 495)
Log_Out = tk.Button(self.window, text = 'Log-Out', height = 1, width = 8, command = self.LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
help_btn = tk.Button(self.window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
self.English_Flag = tk.PhotoImage(file = 'EnglishFlag.gif')
self.English_Flag_btn = tk.Button(self.window, image = self.English_Flag, command = self.English_Home_Screen)
self.English_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.English_Flag_btn.place(y = 350, x = 300)
self.Polish_Flag = tk.PhotoImage(file = 'PolishFlag.gif')
self.Polish_Flag_btn = tk.Button(self.window, image = self.Polish_Flag, command = self.EngFlag)
self.Polish_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.Polish_Flag_btn.place(y = 350, x = 600)
self.Italian_Flag = tk.PhotoImage(file = 'ItalianFlag.gif')
self.Italian_Flag_btn = tk.Button(self.window, image = self.Italian_Flag, command = None)
self.Italian_Flag_btn.pack(side = tk.LEFT, padx = 10)
self.Italian_Flag_btn.place(y = 350, x = 900)
def English_Home_Screen(self):
self.Eng_self_window = tk.Toplevel(self.window)
self.Eng_self_window.geometry('1366x768')
self.Eng_self_window.configure(background = self.Background_Colour)
self.Eng_self_window.title('Local Languages Learning System')
#Eng_self.window.resizable(width=False, height=False)
Title1 = tk.Label(self.Eng_self_window, text = 'Local Languages\nEnglish Home Screen', bg = self.Background_Colour)
Title1.config(font=("Courier", self.Title_Text))
Title1.pack()
Title1.place(y = 1, x = 450)
Log_Out = tk.Button(self.Eng_self_window, text = 'Log-Out', height = 1, width = 8, command = self.LogOut1)
Log_Out.pack()
Log_Out.place(y = 5, x = 1290)
Back = tk.Button(self.Eng_self_window, text = 'Back', height = 1, width = 8, command = self.back1)
Back.pack()
Back.place(y = 5, x = 1210)
help_btn = tk.Button(self.Eng_self_window, text = 'Help', height = 1, width = 8, command = None)
help_btn.pack()
help_btn.place(y = 45, x = 1290)
Play_all = tk.Button(self.Eng_self_window, text = 'Play All Games', height = 2, width = 20, command = None)
Play_all.pack()
Play_all.place(y = 100, x = 320)
Multiple_Choice = tk.Button(self.Eng_self_window, text = 'Play Multiple Choice Game', height = 2, width = 20, command = None)
Multiple_Choice.pack()
Multiple_Choice.place(y = 100, x = 510)
Picture = tk.Button(self.Eng_self_window, text = 'Play Picture Game', height = 2, width = 20, command = None)
Picture.pack()
Picture.place(y = 100, x = 700)
Memory = tk.Button(self.Eng_self_window, text = 'Play Memory Game', height = 2, width = 20, command = None)
Memory.pack()
Memory.place(y = 100, x = 890)
LeaderBoard = tk.Button(self.Eng_self_window, text = 'LeaderBoard', height = 2, width = 20, command = None)
LeaderBoard.pack()
LeaderBoard.place(y = 160, x = 600)
def EngFlag(self):
print('Hello world')
def LogOut1(self):
response = messagebox.askquestion ('?', 'Are You Sure?')
if response == 'yes':
if tk.Toplevel.winfo_exists(self.Eng_self_window):
self.Eng_self_window.destroy()
else:
self.window.destroy()
def back1(self):
print("Go back")
self.Eng_self_window.destroy()
root = tk.Tk()
Home_Screen(root)
root.mainloop()
Quick fix; Don't use multiple instances of Tk. Instead, use Toplevel and hide & show the root window. Add:
...
Background_Colour = 'Light blue'
root = Tk()
root.withdraw()
...
and replace:
...
if response == 'yes':
try:
window.destroy()
except:
Eng_window.destroy()
...
global window
window = Tk()
...
global Eng_window
Eng_window = Tk()
with:
...
if response == 'yes':
root.destroy()
...
global window
window = Toplevel()
...
global Eng_window
Eng_window = Toplevel()

Cell formatting in Grid Geometry manager

I have this code:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)#input question here
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)#FIX THE FORMATTING OF QUESTION, GRID CELL TO LEFT, NOT BIG ENOUGTH?
self.AnswerEntry = ttk.Entry(self.frame_Interact, width = 10)#do later
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__": main()
I dont know why, but the Answer box and label on the right side of my tkinter GUI is on the left side of its frame. I want it in the center. Does anyone know a way to frix it, or any improvements for the code so far. Thanks :)
There are two ways you can do this, first way will to be to use .pack() instead of .grid() since pack is very easy to use and does the aligning for you automatically.
So you can just replace:
self.QuestionLabel.grid(column = 0, row = 0)
# and
self.QuestionShow.grid(column = 0, row = 1)
With:
self.QuestionLabel.pack()
# and
self.QuestionLShow.pack()
This way isn't recommended for your situation whatsoever, since that will involve mixing pack and grid together which could cause future errors in your code.
As Bryan Oakley said:
it will cause errors immediately, if the widgets share the same parent. It won't ever cause problems if the widgets have different parents.
You should instead do this:
from tkinter import *
from tkinter import ttk
class Application:
def __init__(self, master):#Change to game class when combining code
self.master = master#remove when combining code
self.frame_Canvas = ttk.Frame(self.master, width = 600, height = 600)
self.frame_Canvas.pack(side = 'left')
self.frame_Canvas.pack_propagate(False)
self.frame_Canvas.grid_propagate(False)
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
self.FullName = ttk.Label(self.frame_Canvas, text = "Full Name", background = 'white')#full name will be entered here
self.FullName.config(font=("TkDefaultFont", 20))
self.FullName.place(x = 10, y = 10)
self.frame_Interact = ttk.Frame(self.master, width = 200, height = 600)
self.frame_Interact.pack(side = 'right')
self.frame_Interact.pack_propagate(False)
self.frame_Interact.grid_propagate(False)
Grid.columnconfigure(self.frame_Interact, 0, weight=1) # NOTE, THIS CHANGED
self.QuestionLabel = ttk.Label(self.frame_Interact, text = "Question:")
self.QuestionLabel.config(font=("TkDefaultFont", 20))
self.QuestionLabel.grid(column = 0, row = 0)
self.QuestionShow = Text(self.frame_Interact, height=1, width=8)
self.QuestionShow.config(font=("TkDefaultFont", 20))
self.QuestionShow.grid(column = 0, row = 1)
def main():
root = Tk()
root.wm_title("Hangman")
Menu = Application(root)
root.resizable(width=False, height=False)
root.iconbitmap("windowicon.ico")
root.mainloop()
if __name__ == "__main__":
main()
By adding Grid.columnconfigure(self.frame_Interact, 0, weight=1) it will help grid know how to allocate extra space. so that the label will try to take up the whole column. The same goes for rows if you're wondering, you can add Grid.rowconfigure(self.frame_Interact, 0, weight=1) to make the widgets fill the whole row.
And for some improvements to your code, you should change this line:
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600,
background = 'white').pack()
# to
self.hangman = Canvas(self.frame_Canvas, width = 600, height = 600, background = 'white')
self.hangman.pack()
Or else self.hangman will be None, as it is in your code.

Error: Attribute error in TCL

I am trying to create an application in Python GUI using tkinter. Here is the code I'm using for the GUI part. Whenever I try to access my Entry Widget I get error.
Ex:Sin_put.get() should give me the text in the Entry widget but it gives me an error
AttributeError: 'NoneType' object has no attribute 'get'
I'm relatively new to Python. So if you guys have any suggestions to improve the functionality you're most welcome.
from tkinter import *
from tkinter import ttk
sys.path.insert(0, 'home/ashwin/')
import portscanner
class App:
def __init__(self, master):
master.option_add('*tearOff', False)
master.resizable(False,False)
self.nb = ttk.Notebook(master)
self.nb.pack()
self.nb.config(width=720,height=480)
self.zipframe = ttk.Frame(self.nb)
self.scanframe = ttk.Frame(self.nb)
self.botframe = ttk.Frame(self.nb)
self.mb = Menu(master)
master.config(menu = self.mb)
file = Menu(self.mb)
info = Menu(self.mb)
self.mb.add_cascade(menu = file, label = 'Tools')
self.mb.add_cascade(menu = info, label = 'Help')
file.add_command(label='Zip Cracker', command = self.zipframe_create)
file.add_command(label='Port Scanner', command = self.scanframe_create)
file.add_command(label='Bot net', command =self.botframe_create)
info.add_command(label='Usage', command=(lambda:print('Usage')))
info.add_command(label='About', command=(lambda:print('About')))
def zipframe_create(self):
self.nb.add(self.zipframe,text='Zip')
self.zipframe.config(height=480,width=720)
zlabel1 = ttk.Label(self.zipframe, text='Select the zip file').grid(row=0,column=0, padx=5, pady=10)
zlabel2 = ttk.Label(self.zipframe, text='Select the dictionary file').grid(row=2,column=0, padx=5)
ztext1 = ttk.Entry(self.zipframe, width = 50).grid(row=0,column=1,padx=5,pady=10)
ztext2 = ttk.Entry(self.zipframe, width = 50).grid(row=2,column=1,padx=5)
zoutput = Text(self.zipframe, width=80, height=20).grid(row=3,column=0,columnspan = 3,padx=5,pady=10)
zb1 = ttk.Button(self.zipframe, text='Crack', width=10).grid(row=0,column=2,padx=5,pady=10)
def scanframe_create(self):
self.nb.add(self.scanframe,text='Scan')
self.scanframe.config(height=480,width=720)
slabel1 = ttk.Label(self.scanframe, text='IP address').grid(row=0,column=0, padx=5, pady=10)
sin_put = ttk.Entry(self.scanframe, width = 50).grid(row=0,column=1,padx=5,pady=10)
soutput = Text(self.scanframe, width=80, height=20).grid(row=3,column=0,columnspan = 3,padx=5,pady=10)
sb1 = ttk.Button(self.scanframe, text='Scan', width=6,command= print('Content: {}'.format(sin_put.get()))).grid(row=0,column=2,padx=5,pady=10)
def botframe_create(self):
self.nb.add(self.botframe,text='Bot')
self.botframe.config(height=480,width=720)
blabel1 = ttk.Label(self.botframe, text='IP address').grid(row=0,column=0, padx=5, pady=10)
blabel2 = ttk.Label(self.botframe, text='Username').grid(row=1,column=0, padx=2)
blabel3 = ttk.Label(self.botframe, text='password').grid(row=2,column=0, padx=2)
btext1 = ttk.Entry(self.botframe, width = 30).grid(row=0,column=1,padx=5,pady=10)
btext2 = ttk.Entry(self.botframe, width = 30).grid(row=1,column=1)
btext2 = ttk.Entry(self.botframe, width = 30).grid(row=2,column=1)
boutput = Text(self.botframe, width=80, height=20).grid(row=3,column=0,columnspan = 3,padx=5,pady=10)
bb1 = ttk.Button(self.botframe, text='Connect', width=8).grid(row=2,column=2,padx=5,pady=10)
def main():
root = Tk()
feedback = App(root)
root.mainloop()
if __name__ == "__main__": main()
grid() returns None so sin_put will always equal None. Instead of passing the Tkinter ID to grid() you have to store it first if you want to reference it later. Note that for the Buttons, putting it all on one line is fine as you don't use the button's ID later.
sin_put=ttk.Entry(self.scanframe, width = 50) ## stores the return ID from Entry
sin_put.grid(row=0,column=1,padx=5,pady=10) ## don't catch return from grid as it is None

Resources