I haven't figured out how to set the focus on a specific tab of a ttk.Notebook. focus_set does not work. Is there any possibility?
Thanks in advance
I was having the same problem. What I found is the 'select' method for notebooks (ttk.Notebook.select(someTabFrame)) solves this problem:
import ttk, Tkinter
mainWindow = Tkinter.Tk()
mainFrame = Tkinter.Frame(mainWindow, name = 'main-frame')
mainFrame.pack(fill = Tkinter.BOTH) # fill both sides of the parent
nb = ttk.Notebook(mainFrame, name = 'nb')
nb.pack(fill = Tkinter.BOTH, padx=2, pady=3) # fill "master" but pad sides
tab1Frame = Tkinter.Frame(nb, name = 'tab1')
Tkinter.Label(tab1Frame, text = 'this is tab 1').pack(side = Tkinter.LEFT)
nb.add(tab1Frame, text = 'tab 1')
tab2Frame = Tkinter.Frame(nb, name = 'tab2')
Tkinter.Label(tab2Frame, text = 'this is tab 2').pack(side = Tkinter.LEFT)
nb.add(tab2Frame, text = 'tab 2')
nb.select(tab2Frame) # <-- here's what you're looking for
mainWindow.mainloop()
python docs for ttk.Notebook:
https://docs.python.org/2/library/ttk.html#ttk.Notebook
I also used this blog post as a model for my code:
http://poquitopicante.blogspot.com/2013/06/blog-post.html
This code based on wordsforthewise's answer to this question. Here you can find example of using select as get and set function, it shown by button that switch between 2 tabs.
small improvement:
import ttk, Tkinter
from pango import Weight
from Tkinter import Button
tab2Frame = None
tab1Frame = None
def switchTab():
if nb.select()[-1] == "1":
nb.select(tab2Frame)
elif nb.select()[-1] == "2":
nb.select(tab1Frame)
mainWindow = Tkinter.Tk()
mainWindow.geometry("%dx%d+0+0" % (200, 200))
mainFrame = Tkinter.Frame(mainWindow, name = 'main-frame')
mainFrame.pack(fill = Tkinter.BOTH) # fill both sides of the parent
button = Button(mainWindow, text = "Switch", command = switchTab)
button.configure(width = 15, activebackground = "#6f6Fff")
button.pack()
nb = ttk.Notebook(mainFrame, name = 'nb')
nb.pack(fill = Tkinter.BOTH, padx=2, pady=3) # fill "master" but pad sides
tab1Frame = Tkinter.Frame(nb, name = 'tab1')
Tkinter.Label(tab1Frame, text = 'this is tab 1').pack(side = Tkinter.LEFT)
nb.add(tab1Frame, text = 'tab 1')
tab2Frame = Tkinter.Frame(nb, name = 'tab2')
Tkinter.Label(tab2Frame, text = 'this is tab 2').pack(side = Tkinter.LEFT)
nb.add(tab2Frame, text = 'tab 2')
mainWindow.mainloop()
Related
I am trying to connect my tkinter code with another program. That is, I am trying to call the GUI file from the the other program and receive input from the GUI program, but I am having issues.
Here is the GUI code called BayeGUI
from tkinter import *
import tkinter.simpledialog
class BayeGUI:
def __init__(self):
window = Tk()
window.title('Graphical User Interface Designed by Gideon')
self.input = 'I am fine Thank you'
frame1 = Frame(window)
frame1.pack()
self.v1 = StringVar()
scrollbar = Scrollbar(frame1)
scrollbar.pack(side = RIGHT, fill = Y)
self.text = Text(frame1, width = 100, height = 30,wrap = WORD, yscrollcommand = scrollbar.set)
scrollbar.config(command = self.text.yview)
self.text.pack()
frame2 = Frame(window)
frame2.pack()
testbtn = Button(frame2,text = 'Test Algorithm',command = self.testAlgorithm)
testbtn.grid(row = 1, column = 1)
return self.input
window.mainloop()
def testAlgorithm(self):
isYes = tkinter.messagebox.askyesno('askyesno', 'Do you want to Test the Algorithm?')
if isYes == True:
self.input = self.text.get("1.0",'end-1c') #This is the input I need
BayeGUI()
This is the main code where I am trying to get value fron Baye GUI.
from BayeGUI import BayeGUI
emails = BayeGUI()
print(emails)
I'm wondering if I got my if else statement wrong or if its a tkinter issue. I want it so that if a 0 is left in any or all boxes, it gives an error message. But after the error message is closed, it opens a random blank window. This is my code. The specific area is the if else statement within the function valueget()
import tkinter as tk
def mainwindow():
mainwindow = tk.Tk()
mainwindow.title('Enter values')
mainwindow.geometry('160x110')
mainwindow.config(bg='#aaf0d1')
tk.Label(mainwindow, text = 'Enter a', font = ('verdana'), bg='#aaf0d1').grid(row=0)
tk.Label(mainwindow, text = 'Enter b', font = ('verdana'), bg='#aaf0d1').grid(row=1)
tk.Label(mainwindow, text = 'Enter c', font = ('verdana'), bg='#aaf0d1').grid(row=2)
getA = tk.IntVar()
aBox = tk.Entry(mainwindow, textvariable = getA, width=3, bg='#aaf0d1')
aBox.grid(row=0, column=1)
aBox.config(highlightbackground='#aaf0d1')
getB = tk.IntVar()
bBox = tk.Entry(mainwindow, textvariable = getB, width=3, bg='#aaf0d1')
bBox.grid(row=1, column=1)
bBox.config(highlightbackground='#aaf0d1')
getC = tk.IntVar()
cBox = tk.Entry(mainwindow, textvariable = getC, width=3, bg='#aaf0d1')
cBox.grid(row=2, column=1)
cBox.config(highlightbackground='#aaf0d1')
button = tk.Button(mainwindow, text='Obtain roots', command = lambda: valueget(), font = ('verdana'), highlightbackground='#aaf0d1')
button.grid(row=4)
button.config(bg='#aaf0d1')
def valueget():
readA = getA.get()
readB = getB.get()
readC = getC.get()
intA = int(readA)
intB = int(readB)
intC = int(readC)
negroot = (readB**2)-(4*readA*readC)
quadformulaplus = (-readB + (pow(negroot,0.5)))/(2*readA) #quad forumla
quadformulaminus = (-readB - (pow(negroot,0.5)))/(2*readA) #quad forumla
messagewindow = tk.Tk()
messagewindow.geometry('290x50')
messagewindow.title('Roots of the equation')
messagewindow.config(bg='#aaf0d1')
if readA == 0 or readB==0 or readC==0 or (readA==0 and readB==0 and readC==0):
errorwindow = tk.messagebox.showerror(message='none').pack()
else:
label = tk.Label(messagewindow, text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}', bg='#aaf0d1', font = ('verdana'))
label.grid(row=1)
closebutton = tk.Button(messagewindow, text='Close', command = lambda: messagewindow.destroy(), font = ('verdana'), highlightbackground='#aaf0d1')
closebutton.grid(row=2)
closebutton.config(bg='#aaf0d1')
messagewindow.mainloop()
# print(f'the roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}')
mainwindow.mainloop()
def startup():
startpage = tk.Tk()
startpage.title('Solver')
photo = tk.PhotoImage(file = r"/Users/isa/Desktop/DiffEqns/cover.png") #image load
coverbutton = tk.Button(startpage, image = photo, command = lambda: [startpage.destroy(), mainwindow()])
coverbutton.pack()
coverbutton.configure(highlightbackground='#aaf0d1')
startpage.mainloop()
startup()
Here's a basic idea of what I would do:
import tkinter as tk
from tkinter import messagebox
def mainwindow(root):
# Creates a toplevel window
mainwindow = tk.Toplevel()
mainwindow.protocol("WM_DELETE_WINDOW", root.destroy) # This overrides the "X" being clicked to also destroy the root window.
root.withdraw() # "Hides" the root window, leaving it (and mainloop) running in the background.
mainwindow.title('Enter values')
mainwindow.geometry('160x110')
mainwindow.config(bg='#aaf0d1')
# Since all three of the labels/entries are the same
# we can save space by generating them in a loop
entry_items = ('Enter a', 'Enter b', 'Enter c')
values = []
for x, item in enumerate(entry_items): # Using enumerate and x to assign rows
tk.Label(mainwindow, text = item,
font = ('verdana'), bg='#aaf0d1').grid(row=x) # Row assigned to x.
values.append(tk.StringVar()) # Appended StringVar to list.
tk.Entry(mainwindow,
textvariable = values[-1], # Uses the last value appended to the values list.
highlightbackground='#aaf0d1',
width=3,
bg='#aaf0d1').grid(row=x, column=1) # Row assigned to x.
tk.Button(mainwindow,
text='Obtain roots',
command = lambda vals = values: valueget(vals), # Here the button command is assigned with the values list
font = ('verdana'), bg='#aaf0d1',
highlightbackground='#aaf0d1').grid(row=3) # we know there are 3 items before this.
mainwindow.lift() # This is a method of bringing a window to the front
def valueget(vals):
# This line gets the values from the StringVars, converts them to ints,
# and returns them to their respective variables.
try:
readA, readB, readC = [int(val.get()) for val in vals]
except ValueError:
messagebox.showerror(title="Number Error", message='Values must be numbers')
return
# Here the variables are checked to see if they are 0
# Since each one is being checked if it is 0, there is no need to check if they are all 0.
for val in (readA, readB, readC):
if val == 0:
# If they are 0, shows an error message
messagebox.showerror(title="Zero Error", message='Values must not be zero')
return
# Creates a toplevel to display the results
messagewindow = tk.Toplevel()
messagewindow.title('Roots of the equation')
messagewindow.config(bg='#aaf0d1')
negroot = (readB**2)-(4*readA*readC)
quadformulaplus = (-readB + (pow(negroot,0.5)))/(2*readA) #quad forumla
quadformulaminus = (-readB - (pow(negroot,0.5)))/(2*readA) #quad forumla
tk.Label(messagewindow,
text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}',
bg='#aaf0d1',
font = ('verdana')).pack(padx = 5, pady = 2)
tk.Button(messagewindow,
text='Close',
command = messagewindow.destroy, # There is no need for a lambda for this.
font = ('verdana'),
bg = '#aaf0d1',
highlightbackground='#aaf0d1').pack(padx = 5, pady = 2)
# print(f'the roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}')
messagewindow.lift() # This is a method of bringing a window to the front
def startup():
startpage = tk.Tk()
startpage.title('Solver')
# COMMENTED OUT FOR TESTING
#photo = tk.PhotoImage(file = r"/Users/isa/Desktop/DiffEqns/cover.png") #image load
coverbutton = tk.Button(startpage,
# COMMENTED OUT FOR TESTING
#image = photo,
text = "TESTING", # HERE FOR TESTING
highlightbackground='#aaf0d1',
command = lambda root = startpage: mainwindow(root)).pack() # Passes the startpage to the mainwindow function.
startpage.mainloop() # The only mainloop you need.
startup()
I would recommend to improve the readability of the if-else statement for a start.
coefficients = [readA, readB, readC]
if sum(coefficients): # If they all are all zeros this will be False
if min(coefficients): # If any one is zero, this will be False
label = tk.Label(messagewindow, text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}', bg='#aaf0d1', font = ('verdana'))
label.grid(row=1)
closebutton = tk.Button(messagewindow, text='Close', command = lambda: messagewindow.destroy(), font = ('verdana'), highlightbackground='#aaf0d1')
closebutton.grid(row=2)
closebutton.config(bg='#aaf0d1')
else:
errorwindow = tk.messagebox.showerror(message='none').pack()
else:
errorwindow = tk.messagebox.showerror(message='none').pack()
I was creating a youtube manager for my personal use, and it was going decently well, until I hit a brick wall with the UI.
Here's the code:
class Application(ttk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.create_widgets()
def create_widgets(self):
nb = ttk.Notebook(self)
page1 = ttk.Frame(nb, width= 300)
#page1 = ttk.Frame(self, width= 300)
nb.add(page1, text='One')
#page1.grid()
nb.grid()
frames = {}
labels = {}
lk_btns = {}
cmt_btns = {}
mk_wch_btns = {}
dwld_btns = {}
i = 0
scrollbar = ttk.Scrollbar(page1)
#scrollbar.grid(row = 0,column = 1,sticky = "ns")
scrollbar.pack(side = "right",fill = "y")
listbox = tk.Canvas(page1,yscrollcommand = scrollbar.set,)
#listbox.grid(row = 0,column = 0,sticky = "nsew")
listbox.pack(side = "left",fill = "both")
for v in test.getLatestVids():
frm = ttk.Frame(listbox)
frm.grid(row=i, column=1,sticky = "E")
lb = ttk.Label(frm, text=convert65536(v["snippet"]["title"]))
lb.grid(row = 0,rowspan = 4,column=0,sticky = "E")
labels[i] = lb
download = ttk.Button(frm, text="Download")
download.grid(row = 1,column=1,sticky = "W")
dwld_btns[i] = download
mwatched = ttk.Button(frm, text="Mark Watched")
mwatched.grid(row = 2,column=1,sticky = "W")
mk_wch_btns[i] = mwatched
like = ttk.Button(frm, text="Like")
like.grid(row = 1,column=2,sticky = "W")
lk_btns[i] = like
comment = ttk.Button(frm, text="Comment")
comment.grid(row = 2,column=2,sticky = "W")
cmt_btns[i] = comment
frames[i] = frm
i += 1
scrollbar.config(command=listbox.yview)
listbox.configure(scrollregion=(-400, -400, 400, 400))
#self.quit = tk.Button(self, text="QUIT", fg="red",
# command=root.destroy)
root = tk.Tk()
app = Application(master=root)
app.mainloop()
PS1: The "convert65536" method is a method for handling the emojis in youtube titles. I found it here.
PS2: The "test.getLatestVids" method is an external method I made that returns a list of dictionaries.
The problem here is that the code thinks there is a lot of space, and does'nt use the scrollbar instead. I tried to make this work by limiting the size of "page1", but I failed to do so.
Here are some screenshots:
In fullscreen
Seeing the entire list thanks to multiple desktops
Items added to a canvas with pack, place or grid will not scroll. The only things that will scroll on a canvas are windows added with create_window.
The most common solution is to add one frame to the canvas, and then pack, place, or grid widgets inside the frame. See http://stackoverflow.com/a/3092341/7432.
If you're creating a vertical list of text and widgets, an even simpler solution is to use a text widget, which allows you to embed widgets with the window_create method.
I am trying to create a simple hangman game using tkinter with python. While creating the GUI, the first thing I put in were the dashes.lbl = tkinter.Label(window, text= xhash). When I put in my buttons, the label disappeared. I have tried making the window bigger, but it still didn't come back.
Here is my full code:
#importing modules
import tkinter
import random
#creating the dashes
f = open(r'C:\Users\Gareth\Documents\hangman\words.txt', 'r')
word = f.readlines()
guess = random.choice(word)
hash = []
xhash = ""
while len(hash) < len(str(guess)):
hash.append('_ ')
def rejoin():
xhash = "".join(hash)
xhash.strip("[]")
xhash.strip(",")
xhash.strip("'")
#creating the window
window = tkinter.Tk()
window.minsize(300, 300)
#commands for buttons a-z
def acmd():
for i in list(guess):
if i == 'a':
hash[guess.index(i)] = 'a'
rejoin()
lbl.configure(text= xhash)
abtn.configure(bg = 'red')
#label
lbl = tkinter.Label(window, text= xhash)
#buttons for letters a-z
abtn = tkinter.Button(window, text = 'a', command = acmd)
bbtn = tkinter.Button(window, text = 'b')
cbtn = tkinter.Button(window, text = 'c')
dbtn = tkinter.Button(window, text = 'd')...
#placing lbl and buttons
lbl.grid(row = 1, column = 1)
abtn.grid(row = 3 , column = 1)
bbtn.grid(row = 3 , column = 2)
cbtn.grid(row = 3 , column = 3)...
window.mainloop()
You would need to position them correctly, most probably either you are not positioning them or positioning them on top of each other. You would need to use grid() to position them
Example -
lbl = tkinter.Label(window, text= xhash)
lbl.grid(row=0,column=1)
abtn = tkinter.Button(window, text = 'a', command = acmd)
abtn.grid(row=0,column=2)
The problem did not lie within the label, but within the text.
def rejoin():
xhash = "".join(hash)
xhash.strip("[]")
xhash.strip(",")
xhash.strip("'")
the only adjustment needed was a global statement...
without that, whatever was done in the function had nothing to do with anything else, so, the previously assigned xhash = '', was simply left blank...
I have a string 'currentMessage' and a Label to display it.
I have a Toplevel widget, which contains a Text widget to provide new value for 'currentMessage':
from tkinter import *
from tkinter import ttk
root = Tk()
mainFrame = ttk.Frame(root)
mainFrame.grid()
currentMessage = 'current Message'
ttk.Label(mainFrame, text = currentMessage).grid(padx = 10, pady = 10)
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.textBox.get(0.0, END)
def changeValues():
popup = Toplevel(mainFrame)
popup.grid()
textBox = Text(popup, width = 20, height = 5)
textBox.grid(column = 0, row = 0)
textBox.insert(END, 'new message here')
b = ttk.Button(popup, command = lambda: updateCurrentMessage(popup))
b.grid(column = 0, row = 1, padx = 5, pady = 5)
b['text'] = 'Update'
theButton = ttk.Button(mainFrame, command = changeValues, text = 'Click')
theButton.grid(padx = 10, pady = 10)
mainFrame.mainloop()
I tried to get the content of 'textBox' Text widget of the Toplevel by using this function:
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.textBox.get(0.0, END)
But I got an error
'Toplevel' object has no attribute 'textBox'
So how do I access content of the widget 'textBox', which is a child widget of 'popup' (this Toplevel widget is only created when function changeValues() is called)?
I think probably this is what you are looking for -- although I'm just guessing, because you are asking for a solution for a specific problem you think you have, however if I were you I would rethink what exactly do I want to do:
from tkinter import *
from tkinter import ttk
# Create Tk Interface root
root = Tk()
# Initialize mainFrame
mainFrame = ttk.Frame( root )
mainFrame.grid()
# Initialize label of mainframe
theLabel = ttk.Label( mainFrame, text='Current Message' )
theLabel.grid( padx=10, pady=10 )
def createPopup():
# Initialize popup window
popup = Toplevel( mainFrame )
popup.grid()
# Initialize text box of popup window
textBox = Text( popup, width=20, height=5 )
textBox.grid( column = 0, row = 0 )
textBox.insert( END, 'New Message Here' )
# Initialize button of popup window
button = ttk.Button( master = popup,
command = lambda: theLabel.config(text=textBox.get(0.0, END)),
text = 'Update')
button.grid( column=0, row=1, padx=5, pady=5 )
# Initialize button of main frame
theButton = ttk.Button( mainFrame, command=createPopup, text='Click' )
theButton.grid( padx=10, pady=10 )
# Enter event loop
mainFrame.mainloop()
There is a way indeed, like this:
def updateCurrentMessage(popupWindow):
currentMessage = popupWindow.nametowidget('textBox').get(0.0, END)
def changeValues():
popup = Toplevel(mainFrame)
popup.grid()
textBox = Text(popup, width = 20, height = 5, name = 'textBox')
textBox.grid(column = 0, row = 0)
textBox.insert(END, 'new message here')
b = ttk.Button(popup, command = lambda: updateCurrentMessage(popup))
b.grid(column = 0, row = 1, padx = 5, pady = 5)
b['text'] = 'Update'
You can choose whatever you want for the 'name'.