I am making a GUI that will control a robot.
This is my code so far:
from Tkinter import * #Importing TKinter
class Application(Frame): #Making a frame
def __init__(self, master=None):
Frame.__init__(self, master)
self.master.title("Vinny's Myro Controller Version 0.1") #Setting the name of the program/window
self.master.geometry("550x365+300+300") #Window dimensions
self.master.rowconfigure(0, weight=2) #how much space the rows take
self.master.columnconfigure(0, weight=1) #how much space the columns take
''' \/ BOTTOM BUTTONS \/ '''
self.master.button1 = Button(master, text = "Take a Picture") #Bottom button that is supposed to take a pic.
self.master.button1.grid(row=6, column=0, sticky=W+E)
self.master.button2 = Button(master, text = "Honk the Horn") #Bottom button that is supposed to honk the horn.
self.master.button2.grid(row=6, column=1, sticky=W+E)
self.master.button3 = Button(master, text = "Get Sensor Data") #Bottom button that is supposed to get data from the sensors.
self.master.button3.grid(row=6, column=2, sticky=W+E)
''' /\ BOTTOM BUTTONS /\ '''
''' \/ LEFT RED FRAME THAT CONTAINS THE ARROWS THAT WILL MOVE THE ROBOT \/ '''
self.frame1 = Frame(master, bg="red") #Background color
self.frame1.grid(row = 0, column = 0, rowspan = 1, columnspan = 1, sticky = W+E+N+S, padx=10, pady=10)
self.frame1.forward = Button(self.frame1, text = "Forward", width=30, height=3) #Forward Button
self.frame1.forward.place(x=63, y=75) #Button Position
self.frame1.right = Button(self.frame1, text = "Right", width=12, height=3) #Right Button
self.frame1.right.place(x=189, y=131) #Button Position
self.frame1.backward = Button(self.frame1, text = "Backward", width=30, height=3) #Backward Button
self.frame1.backward.place(x=63, y=187) #Button Position
self.frame1.left = Button(self.frame1, text = "Left", width=12, height=3) #Left Button
self.frame1.left.place(x=63, y=131) #Button Position
''' /\ LEFT RED FRAME THAT CONTAINS THE ARROWS THAT WILL MOVE THE ROBOT /\ '''
self.frame2 = Frame(master, bg="green")
self.frame2.grid(row = 0, column = 1, rowspan = 3, columnspan = 3, sticky = W+E+N+S, padx=10, pady=10)
self.frame2.button5 = Button(self.frame2, text = "test")
self.frame2.button5.grid(row=6, column=2)
self.frame2.light = BooleanVar()
self.frame2.chk1 = Checkbutton(self, text = "Lights", variable = self.frame2.light, command = 1+1)
self.frame2.chk1.grid(row = 0, column = 3, padx=10, pady = 10)
root = Tk()
app = Application(master=root)
app.mainloop()
Note this piece of code:
self.frame2.light = BooleanVar()
self.frame2.chk1 = Checkbutton(self, text = "Lights", variable = self.frame2.light, command = 1+1)
self.frame2.chk1.grid(row = 0, column = 3, padx=10, pady = 10)
Somehow, I can place a button inside my frame, but not a checkbox. I need this checkbox in order to get data from the robot's sensors.
I've tried using grid and place.
Could anybody help me?
Screenshot:
http://d.pr/i/iRX4
Thanks
The problem is that you are creating the checkbutton as a child of self rather than as a child of self.frame2. Change the checkbutton to be:
self.frame2.chk1 = Checkbutton(self.frame2, ...)
Related
I know how to add a scrollbar on a tkinter window, frame, canvas.
I also know how to do it on a listbox.
Problem is, I have a window that doesn't have any of those, and only use Label and Button:
from tkinter import *
test1 = 100
test2 = 100
test3 = 100
test4 = 100
root = Tk()
root.title("Program")
root.geometry('350x250')
# first group of labels & buttons
label = Label(root, text="test1")
label.grid(row=0, column=0, columnspan=2)
label = Label(root, text=test1)
label.grid(row=1, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=2, column=0)
button = Button(root, text="Down")
button.grid(row=2, column=1)
#
label = Label(root, text="test2")
label.grid(row=3, column=0, columnspan=2)
label = Label(root, text=test2)
label.grid(row=4, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=5, column=0)
button = Button(root, text="Down")
button.grid(row=5, column=1)
#
label = Label(root, text="test3")
label.grid(row=6, column=0, columnspan=2)
label = Label(root, text=test3)
label.grid(row=7, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=8, column=0)
button = Button(root, text="Down")
button.grid(row=8, column=1)
#
label = Label(root, text="test4")
label.grid(row=9, column=0, columnspan=2)
label = Label(root, text=test4)
label.grid(row=10, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=11, column=0)
button = Button(root, text="Down")
button.grid(row=11, column=1)
root.mainloop()
The above has a small window resolution on purpose, because, while it may work in maximizing the window, once there are too many Label's text or Button, then a Scrollbar will be needed. This is intended to test that.
How can I add a scrollbar to the above code?
You need a scrollable frame. See example here: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
And for buttons and labels, instead of using root as parent, use the scrollable frame as parent. For example:
from tkinter import *
c1 = "#999999"
c2 = "#000000"
class ScrollFrame(Frame):
"""
A simple scrollable frame class for tkinter
Source: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
"""
def __init__(self, parent):
# create a frame (self)
super().__init__(parent, background=c1)
# place canvas on self
self.canvas = Canvas(
self, bd=0, bg=c1, relief="flat", highlightthickness=0
)
# place a frame on the canvas, this frame will hold the child widgets
self.viewPort = Frame(self.canvas, background=c1)
self.viewPort.grid_columnconfigure(0, weight=1)
# place a scrollbar on self
self.vsb = Scrollbar(self, orient="vertical", command=self.canvas.yview)
# attach scrollbar action to scroll of canvas
self.canvas.configure(yscrollcommand=self.vsb.set)
# pack scrollbar to right of self
self.vsb.pack(side="right", fill="y")
# pack canvas to left of self and expand to fil
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas_frame = self.canvas.create_window(
(0, 0),
window=self.viewPort,
anchor="nw", # add view port frame to canvas
tags="self.viewPort",
)
# bind an event whenever the size of the viewPort frame changes.
self.viewPort.bind("<Configure>", self.onFrameConfigure)
self.canvas.bind("<Configure>", self.FrameWidth)
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
def _on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def FrameWidth(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width)
def onFrameConfigure(self, event):
"""Reset the scroll region to encompass the inner frame"""
# whenever the size of the frame changes, alter the scroll region respectively.
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
tests = [100, 99, 98, 101]
root = Tk()
root.title("Program")
root.geometry('350x250')
scroll_frame = ScrollFrame(root)
for i, testi in enumerate(tests):
# grouping labels and buttons together in a subframe
# so that the row numbers of the labels and buttons
# are always 0 to 2 within the sub-frame
f1 = Frame(scroll_frame.viewPort)
# first group of labels & buttons
label = Label(f1, text=f"test{i}")
label.grid(row=0, column=0, columnspan=2)
label = Label(f1, text=testi)
label.grid(row=1, column=0, columnspan=2)
button = Button(f1, text="Up")
button.grid(row=2, column=0)
button = Button(f1, text="Down")
button.grid(row=2, column=1)
# defining this group to have 2 columns with equal weight
f1.grid_columnconfigure(0, weight=1)
f1.grid_columnconfigure(1, weight=1)
# expand this sub-frame horizontally to it's parent, sticking to West and East of parent frame
f1.grid(sticky="we", ipadx=2)
# adding a separator
Frame(f1, height=1, background=c2).grid(
sticky="we", pady=5, padx=5, columnspan=2
)
# expand the scroll_frame in all 4 directions to fill the parent frame, sticking to West, East, North and South of parent frame
scroll_frame.grid(sticky="wens", row=0, column=0)
# set root frame only has 1 column (filled by scroll_frame)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
I recently stumbled on an easier way to do that (also use less code to do so):
import tkinter as tk
root = tk.Tk()
text = tk.Text(wrap="none")
vsb = tk.Scrollbar(orient="vertical", command=text.yview)
text.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
text.pack(fill="both", expand=True)
for i in range(30):
test1 = "test" + str(i)
test2 = "Button" + str(i)
c = tk.Label(text=test1)
k = tk.Label(text=i)
b = tk.Button(text=test2)
d = tk.Button(text=test2)
text.window_create("end", window=c)
text.insert("end", "\n")
text.window_create("end", window=k)
text.insert("end", "\n")
text.window_create("end", window=b)
text.window_create("end", window=d)
text.insert("end", "\n")
text.configure(state="disabled")
root.mainloop()
This is based on this answer. It doesn't use a canvas.
There is also another similar answer to the one I accepted on this post, here.
I am trying to create Tabs in python tkinter. I would like the Tab's height to size dynamically based on its content. Below is a sample of my code
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady = 5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady= 5)
nbframe1 = Frame(notebook1, bg = 'white')
nbframe2 = Frame(notebook1, bg = 'grey')
nbframe1.pack(fill ='both', expand=1)
nbframe2.pack(fill ='both', expand=1)
notebook1.add(nbframe1, text= 'A Search')
notebook1.add(nbframe2, text= 'B Search')
a_label = Label(nbframe1, text= 'A_Tag', bg = 'white')
a_label.grid(row = 0, column = 0, sticky=W, padx=5)
b_label = Label(nbframe1, text= 'B_Tag', bg = 'white')
b_label.grid(row = 1, column = 0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable = a_text, width=50)
a_entry.grid(row = 0, column = 1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable = b_text, width=25)
b_entry.grid(row = 1, column = 1, sticky=W, padx=5)
root.mainloop()
From my code, the Tabs created have same height even though one is empty. This is based on the height of the Tab with content. How can i set it so that each Tab's height is based only on the contents.
You can bind a function to the virtual event <<NotebookTabChanged>> to adapt the height of the notebook to the currently selected tab using the height option of the notebook:
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select()) # get selected tab
event.widget.configure(height=tab.winfo_reqheight()) # resize notebook
With your example:
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select())
event.widget.configure(height=tab.winfo_reqheight())
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady=5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady=5)
nbframe1 = Frame(notebook1, bg='white')
nbframe2 = Frame(notebook1, bg='grey')
notebook1.add(nbframe1, text='A Search')
notebook1.add(nbframe2, text='B Search')
a_label = Label(nbframe1, text='A_Tag', bg='white')
a_label.grid(row=0, column=0, sticky=W, padx=5)
b_label = Label(nbframe1, text='B_Tag', bg='white')
b_label.grid(row=1, column=0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable=a_text, width=50)
a_entry.grid(row=0, column=1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable=b_text, width=25)
b_entry.grid(row=1, column=1, sticky=W, padx=5)
root.update_idletasks() # force display update so that the initial tab is displayed correctly
notebook1.bind('<<NotebookTabChanged>>', on_change_tab) # binding to update the height
root.mainloop()
I have tried adding a scrollbar to my GUI but it keeps returning a small canvas which my labels don't fit.
Below is my code using Python.
import tkinter as tk
from tkinter import Canvas, Frame, ttk
from tkinter.constants import ANCHOR, BOTH, LEFT, RIGHT, VERTICAL, Y
root = tk.Tk()
#create a Main Frame
main_frame = tk.Frame(root)
main_frame.grid(row=2, column=0, pady=(5,0), sticky="nw")
main_frame.grid_rowconfigure(0, weight=1)
main_frame.grid_columnconfigure(0, weight=1)
#create a canvas
my_canvas = Canvas(main_frame, bg="yellow")
my_canvas.grid(row=0, column=0, sticky="news")
#Scrollbar
my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.grid(row=0, column=0, sticky="ns")
#configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#create another frame inside canvas
second_frame = Frame(my_canvas)
#add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw")
# Labels
tk.Label(root, text="Decision Support System").grid(
column=0, row=0, sticky="", padx=50)
tk.Label(root, text="""This is a simple application that will help in decision making on whether to adopt a technology based on criteria listed below, you are rate each criteria 1-5
1- not important, 2- slightly important, 3- moderately important, 4-important, 5- very important""").grid(column=0, row=1)
tk.Label(root, text="What type of technology are you trying to invest in?").grid(
column=0, row=2, sticky="w", pady=20, padx=10)
tk.Label(root, text="CA1- Technology Predictors, Group score[35], Coefficient = 0.200").grid(
column=0, row=3, sticky="", pady=10, padx=10)
tk.Label(root, text="Ca1.1-Level of training required : is training of staff going to be thorough?").grid(
column=0, row=4, sticky="w", pady=10, padx=10)
#GUI window
root.mainloop()
And this is what it looks like:
It has a total of 27 rows.
Does this work for you?
I've added a horizontal scrollbar and placed all labels into canvas.
import tkinter as tk
from tkinter import Canvas, Frame, ttk
from tkinter.constants import ANCHOR, BOTH, LEFT, RIGHT, VERTICAL, HORIZONTAL, X, Y
root = tk.Tk()
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
my_canvas = Canvas(root, bg = "yellow")
my_canvas.grid(row = 0, column = 0, sticky = "news")
#Scrollbar
v_scrollbar = ttk.Scrollbar(root, orient = VERTICAL, command = my_canvas.yview)
v_scrollbar.grid(row = 0, column = 1, sticky="ns")
my_canvas.configure(yscrollcommand = v_scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#Scrollbar
h_scrollbar = ttk.Scrollbar(root, orient = HORIZONTAL, command = my_canvas.xview)
h_scrollbar.grid(row = 1, column = 0, sticky="ew")
my_canvas.configure(xscrollcommand = h_scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#create a Main Frame
main_frame = tk.Frame(my_canvas)
main_frame.grid(row = 0, column = 0, sticky = "nsew")
# Labels
tk.Label(main_frame, text = "Decision Support System").grid(
column = 0, row = 0, sticky = "", padx = 50)
tk.Label(main_frame, text="""This is a simple application that will help in decision making on whether to adopt a technology based on criteria listed below, you are rate each criteria 1-5
1- not important, 2- slightly important, 3- moderately important, 4-important, 5- very important""").grid(
column = 0, row = 1)
tk.Label(main_frame, text="What type of technology are you trying to invest in?").grid(
column = 0, row = 2, sticky="w", pady = 20, padx = 10)
tk.Label(main_frame, text="CA1- Technology Predictors, Group score[35], Coefficient = 0.200").grid(
column = 0, row = 3, sticky="", pady = 10, padx = 10)
tk.Label(main_frame, text="Ca1.1-Level of training required : is training of staff going to be thorough?").grid(
column = 0, row = 4, sticky = "w", pady = 10, padx = 10)
my_canvas.create_window((0,0), window = main_frame, anchor = "nw")
root.geometry("836x221")
root.mainloop()
I have 2 different python GUI menus in 2 different scripts.
A dropdown list to select
A menu where numbers can be input and output at the same GUI
I want to merge these 2 together so that both appear in the same GUI menu.
I am having trouble doing it because the structure in both python scripts is different.
Please advice.
Sharing both scripts below:
1st one
from tkinter import *
class Custombox:
def __init__(self, title, text):
self.title = title
self.text = text
def store():
self.new = self.entry.get() # storing data from entry box onto variable
if self.new == '50': # checking
a.change('ACCEPTED') # changing text
elif self.new == '40':
a.change('Increase frequency') # else, changing text
else:
a.change('Decrease frequency') # else, changing text
self.win = Toplevel()
self.win.title(self.title)
# self.win.geometry('400x150')
self.win.wm_attributes('-topmost', True)
self.label = Label(self.win, text=self.text)
self.label.grid(row=0, column=0, pady=(20, 10), columnspan=3, sticky='w', padx=10)
self.l = Label(self.win)
self.entry = Entry(self.win, width=50)
self.entry.grid(row=1, column=1, columnspan=2, padx=10)
self.b1 = Button(self.win, text='Attack', width=10, command=store)
self.b1.grid(row=3, column=1, pady=10)
# self.b2 = Button(self.win, text='Cancel', width=10, command=self.win.destroy)
# self.b2.grid(row=3, column=2, pady=10)
def __str__(self):
return str(self.new)
def change(self, ran_text):
self.l.config(text=ran_text, font=(0, 12))
self.l.grid(row=2, column=1, columnspan=3, sticky='nsew', pady=5)
root = Tk()
root.withdraw()
a = Custombox('User learning platform', 'Select the frequency of the victim sensor.')
root.mainloop()
2nd one
from tkinter import *
root = Tk()
root.title("GUI platform")
# Add a grid
mainframe = Frame(root)
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100, padx = 100)
# Create a Tkinter variable
tkvar = StringVar(root)
# Dictionary with options
choices = { 'URM37','HC-SR04','SRF05','Parallax PING'}
tkvar.set('') # set the default option
popupMenu = OptionMenu(mainframe, tkvar, *choices)
Label(mainframe, text="Please select the type of Sensor for attack").grid(row = 1, column = 1)
popupMenu.grid(row = 2, column =1)
# on change dropdown value
def change_dropdown(*args):
if tkvar.get() == 'HC-SR04':
print( "Correct" )
else:
print("WRONG")
# link function to change dropdown
tkvar.trace('w', change_dropdown)
root.mainloop()
I have recently been using WxPython to create a GUI Network simulator like Cisco packet tracer but if I am honest it has been extremely difficult trying to find examples of what I need etc etc. Iv resorted back to the old faithful Tk.
My program thus far has a menu bar which consists of a File > Exit. It also has an Exit button at the bottom Right hand side of the application. As well as this it has a canvas of a set size and a variety of buttons which when clicked produce a small image of the hardware on the canvas. This was done using PIL
What I need next is to be able to drag these images around the canvas and this is proving a little difficult. I have looked at the following example of how it has been broken down and I kind of understand how you need an on click definition, motion (going from a to b) and on release definition, but how do I apply it to my code that I already have?
Here is the link to what I referenced above:
http://www.python-forum.org/pythonforum/viewtopic.php?f=4&p=75789
Finally Here is the code I have already. I can appreciate that the layout and structure of my code isn't great as I am fairly new to programming but any guidance / examples / visual representations would be amazing.
from Tkinter import*
from PIL import Image, ImageTk
class AllTkinterWidgets:
def __init__(self, master):
frame= Frame(master, width=900, height=600)
frame.pack()
iframe5 = Frame (frame, bd=2, relief=RAISED)
iframe5.pack(expand=1, fill=X, pady=10, padx=5)
c = Canvas(iframe5, bg='white', width=600, height=500)
c.pack()
# definitions to print hardware images to the canvas
# -----------------------------------------------------------------------
def show_imageRouter():
c.create_image(30,30, image=image1)
def show_imageSwitch():
c.create_image(30,60, image=image2)
def show_imageServer():
c.create_image(30,100, image=image3)
def show_imageIpPhone():
c.create_image(30,140, image=image4)
def show_imageWirelessRouter():
c.create_image(30,180, image=image5)
def show_imageHost():
c.create_image(30, 220, image=image6)
# Network hardware buttons created
# ----------------------------------------------------
self.button = Button(frame, text = "Router", height= 1, width= 8, padx=2, pady=2,command=show_imageRouter)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Switch",height= 1, width= 8, padx=2, pady=2, command=show_imageSwitch)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Server",height= 1, width= 8, padx=2, pady=2, command=show_imageServer)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "IP Phone",height= 1, width= 8, padx=2, pady=2, command=show_imageIpPhone)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Wireless Router",height= 1, width= 12, padx=2, pady=2, command=show_imageWirelessRouter)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Host",height= 1, width= 8, padx=2, pady=2, command=show_imageHost)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Cabling",height= 1, width= 8, padx=2, pady=2)
self.button.pack(side = LEFT)
self.button = Button(frame, text = "Square",height= 1, width= 8, padx=2, pady=2)
self.button.pack(side = LEFT)
# Create the image objects for the hardware Images
# ----------------------------------------------------------------------
imageFile = "router.png"
image1 = ImageTk.PhotoImage(Image.open(imageFile))
imageFile = "switch.png"
image2 = ImageTk.PhotoImage(Image.open(imageFile))
imageFile = "Server.png"
image3 = ImageTk.PhotoImage(Image.open(imageFile))
imageFile = "ipPhone.png"
image4 = ImageTk.PhotoImage(Image.open(imageFile))
imageFile = "WirelessRouter.png"
image5 = ImageTk.PhotoImage(Image.open(imageFile))
imageFile = "Host.png"
image6 = ImageTk.PhotoImage(Image.open(imageFile))
root = Tk()
all = AllTkinterWidgets(root)
def Exit():
print "Exit"
# Create an Exit Button
toolbar = Frame(root)
b = Button(toolbar, text="Exit", width=6, height=3, command=Exit)
b.pack(side=RIGHT, padx=2, pady=2)
toolbar.pack(side=BOTTOM, fill=X)
# Press Esc to quit
root.bind("<Escape>", exit)
# Creation of a menu File > Exit
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Exit", command=Exit)
root.mainloop()
Sorry if the indentation is a bit strange. I've adjusted it to make it block together here.
This answer to the question "board drawing code to move an oval" shows how to drag an object on a canvas.