I'm trying to create a dropdown menu using the button with images and I will put some functions on each button, but on the drop-down menu that I use the only button that is available to use is a check button. this is the program that I'm currently using.
from tkinter import *
root = Tk()
mbtn = Menubutton(root, text="Options", relief=RAISED)
mbtn.menu = Menu(mbtn, tearoff = 0)
mbtn["menu"] = mbtn.menu
mbtn.menu.add_checkbutton(label="Outing")
mbtn.menu.add_checkbutton(label="Sleep")
mbtn.menu.add_checkbutton(label="Tour")
mbtn.pack()
root.mainloop()
Does this solve Your issue?
from tkinter import *
root = Tk()
mbtn = Menubutton(root, text="Options", relief=RAISED)
mbtn.pack()
mbtn.menu = Menu(mbtn, tearoff = 0)
mbtn["menu"] = mbtn.menu
mbtn.menu.add_checkbutton(label="Outing")
mbtn.menu.add_checkbutton(label="Sleep")
mbtn.menu.add_checkbutton(label="Tour")
root.mainloop()
instead of mbtn.pack() You can obviously also use mbtn.grid() or mbtn.place()(not suggested - .place())
#TheLizzard added: You can use root.config(menu=mbtn.menu) (instead of mbtn.pack()) to make the menu part of the window.
Related
I want to use the listbox in tkinter in order to open a new window with a button, but when I'm pressing a message it only opens the window, without the button.
from tkinter import *
from playsound import playsound
import os
# create a window as root using Tk() function
root = Tk()
root.geometry("200x200")
# create a changecolor function
# to change background color of window
def new_win():
top2 = Toplevel(root)
top2.geometry('200x200')
top2.title("display Window")
# photo2 = PhotoImage(file=r"hearing.png")
button = Button(text='wtf')
def changecolor(event):
# get selected list box color item
new_win()
# create listbox
listbox = Listbox(root , font=('times 20 bold'), height=5,width=10)
# insert color items into listbox
listbox.insert(1, 'first')
listbox.insert(2, 'second')
listbox.insert(3, 'third')
listbox.insert(4, 'forth')
listbox.pack(pady=20)
# bind the click event with listbox and
# call changecolor() function
listbox.bind('<<ListboxSelect>>', changecolor)
root.mainloop()
Any suggestion would be very helpful.
You can change the line 16
button = Button(text='wtf')
to
button = Button(top2,text='wtf')
button.pack()
I have a following question. I want to make a button in tkinter that will delete existing changes and the window will looks like the initial window.
This is my initial Window 1:
This is how the window looks like when I click on the first two buttons, Window 2:
Now I would like to click on the "Zpět" button and I want to see Window 1 again.
Here is my code:
import tkinter as tk
root = tk.Tk()
home_frame = tk.Frame(root)
home_frame.grid(row=0, column=0, sticky="news")
def raise_new_payment():
tk.Label(text=f"Stav bilance k 2021-09-09").grid()
def back():
"""I would like to this function to clean everything."""
tk.Label().destroy()
platba = tk.Button(
home_frame,
text="Zadej novou platbu",
command=lambda: raise_new_payment(),
)
platba.pack(pady=10)
zpet = tk.Button(
home_frame,
text="Zpět",
command=back,
)
zpet.pack(pady=10)
I don't know how to use the back() function. I tried to delete the tk.Label as created in raise_new_payment(), but it did not work. Can you help me please? Thanks a lot.
I would suggest you create the label once and don't call .pack() on it first, i.e. it is not visible initially.
Then update it inside raise_new_payment() and call .pack() to show it.
You can call .pack_forget() to hide it again inside back().
import tkinter as tk
root = tk.Tk()
home_frame = tk.Frame(root)
home_frame.grid(row=0, column=0, sticky="news")
def raise_new_payment():
# update label and show it
lbl.config(text=f"Stav bilance k 2021-09-09")
lbl.pack()
def back():
# hide the label
lbl.pack_forget()
platba = tk.Button(
home_frame,
text="Zadej novou platbu",
command=lambda: raise_new_payment(),
)
platba.pack(pady=10)
zpet = tk.Button(
home_frame,
text="Zpět",
command=back,
)
zpet.pack(pady=10)
# create the label and initially hide it
lbl = tk.Label(home_frame)
root.mainloop()
I think most of us must have seen the command prompt(windows) and how when we open it and click on it's icon and it shows a menu. Can we do a similar thing with tkinter? This is not the normal menubar.
Here is an illustration of the command prompt one.
This is just an exampel of a work around without the need of doing all your window management by your own. Of course it will need improvements but as a start: Popup stolen from
import tkinter as tk
from PIL import Image, ImageTk
def popup(event):
popup_menu.tk_popup(event.x_root, event.y_root, 0)
def set_icon():
global top, popup
top = tk.Toplevel(root)
top.overrideredirect(1)
top.attributes('-topmost',True)
offset = 30
x,y = root.winfo_rootx(),root.winfo_rooty()-offset
width, height = offset,offset
top.geometry("%dx%d+%d+%d" % (width,height, x,y))
my_label = tk.Label(top, image=photo)
my_label.pack(fill='both')
global popup_menu
popup_menu = tk.Menu(top, tearoff=0)
popup_menu.add_command(label="Delete",
command=lambda :print('del'))
popup_menu.add_command(label="Select All",
command=lambda :print('sel'))
top.bind("<Button-1>", popup)
def grab(event):
top.geometry(f'+{event.x+10}+{event.y+2}')
root=tk.Tk()
ico = Image.open('prac_img/p2.png')
photo = ImageTk.PhotoImage(ico)
root.iconphoto(False,photo)
#root.wm_iconphoto(False,photo)
root.bind('<Configure>',grab)
root.update_idletasks()
set_icon()
root.mainloop()
Another way would be to code your own titlebar and the use of overrideredirecr(1) which will undecorate your window by the window manager of your system.
I am using Tix to automatically create a scroll bar as the content changes. I want to keep a button or two in the user's view while they scroll through the contents of the application.
I haven't seen this question for Tkinter/Tix yet so I thought I'd ask.
The following code will create a sample of the problem where the button is at a fixed point in the window, and is subject to being scrolled.
from Tkinter import *
import Tix
class some_GUI:
def __init__(self, root):
sw= Tix.ScrolledWindow(root, scrollbar=Tix.AUTO)
sw.pack(fill=Tix.BOTH, expand=1)
frame1 = Frame(sw.window)
frame1.grid(row = 0, column = 1)
frame2 = Frame(sw.window)
frame2.grid(row = 0, column = 2)
def quit():
root.quit()
for i in range(0,300):
label1 = Label(frame1, text = "foo")
label1.grid(row = i, column = 0)
button = Button(frame2, text = "Quit", command = quit)
button.pack()
root = Tix.Tk()
display = some_GUI(root)
root.mainloop()
I want the button(s) to be in "frame2" and centered vertically relative to the application's window. I tried using winfo_height/winfo_width to find the frame's height/ width to work with update, but these values didn't change with the addition of the labels and button.
Attempted/possible solutions:
I put frame2 in sw.subwidgets_all[1] by doing the following:
frame1.pack(side = LEFT)
frame2 = Frame(sw.subwidgets_all()[1])
frame2.pack(side = RIGHT)
button = Button(frame2, text = "Quit", command = quit)
button.pack(side = RIGHT)
This allows the fixed position relative to the application, but the window resizes relative to the button's parent instead of frame1. Another drawback is that the horizontal scrollbar is only relative to frame1.
Find the midpoint of the scrollbar and update the position of the buttons relative to those coordinates using place(maybe?) not sure how to accomplish this, and seeing SO solutions in general I think this might be an inefficient way of doing this.
EDIT: Although this isn't exactly what I had in mind, the following code works as per falsetru's suggestion in the comments:
from Tkinter import *
import Tix
class some_GUI:
def __init__(self, root):
def quit():
root.quit()
frame2 = Frame(root)
frame2.pack(side = RIGHT)
button = Button(frame2, text = "Quit", command = quit)
button.pack()
frame1 = Frame(root)
frame1.pack(side = LEFT)
sw= Tix.ScrolledWindow(frame1, scrollbar=Tix.AUTO)
sw.pack(fill=Tix.BOTH, expand=1)
for widget in sw.subwidgets_all():
print widget
for i in range(0,300):
label1 = Label(sw.window, text = "foo")
label1.grid(row = i, column = i)
print root.winfo_toplevel()
for widget in sw.subwidgets_all():
print widget
root = Tix.Tk()
display = some_GUI(root)
root.mainloop()
You can put the button out of ScrollWindows:
import Tix
from Tkinter import *
def build_ui(root):
sw = Tix.ScrolledWindow(root, scrollbar=Tix.AUTO)
sw.pack(side=LEFT, fill=Tix.BOTH, expand=1)
for i in range(300):
label1 = Label(sw.window, text="foo")
label1.grid(row=i, column=0)
button = Button(root, text="Quit", command=root.quit)
button.pack(side=RIGHT)
root = Tix.Tk()
build_ui(root)
root.mainloop()
The second option you mentioned could be the one that satisfies your situation, however that is computationally expensive as you will need to delete the button(s) and redraw them over and over relatively to the scrollbar up/down motion. Not only this is ugly by design but it can be an obstacle for any further scalability of your application or even lead to unexpected bugs if your application runs some serious operations.
The only realistic solution I see for your problem is to fix the button(s) on (for example the bottom of) the upper canvas (or whatever region you want to set) and outside the scrollable region as #falsetru commented you.
I've been working on a text editor using Tkinter in Python 2.7.
A feature that I'm trying to implement is the Night Mode, where the user can toggle between a black background and a light one, that switches from light to dark with a click of the toggle button.
from Tkinter import *
from tkSimpleDialog import askstring
from tkFileDialog import asksaveasfilename
from tkFileDialog import askopenfilename
from tkMessageBox import askokcancel
Window = Tk()
Window.title("TekstEDIT")
index = 0
class Editor(ScrolledText):
Button(frm, text='Night-Mode', command=self.onNightMode).pack(side=LEFT)
def onNightMode(self):
if index:
self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')
else:
self.text.config(font=('courier', 12, 'normal'))
index = not index
However, on running the code, it is always in the night mode and the toggle doesn't work. Help.
Source Code: http://ideone.com/IVJuxX
You can import tkinter library (Use capital letter for python 2.7):
import Tkinter
Create tkinter objects...
root = tk.Tk()
...and tkinter button
toggle_btn = tk.Button(text="Toggle", width=12, relief="raised")
toggle_btn.pack(pady=5)
root.mainloop()
Now create a new command button called "toggle" in order to create the effect of "toggle" when you press playing on the relief property (sunken or raised) :
def toggle():
if toggle_btn.config('relief')[-1] == 'sunken':
toggle_btn.config(relief="raised")
else:
toggle_btn.config(relief="sunken")
At the end apply this behaviour on your button:
toggle_btn = tk.Button(text="Toggle", width=12, relief="raised", command=toggle)
The background and fg are set only in the if-clause. You need to set them also in the else clause:
def onNightMode(self):
if index:
self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')
else:
self.text.config(font=('courier', 12, 'normal'))
index = not index
i.e.,
else:
self.text.config(font=('courier', 12, 'normal'), background='green', fg='black')
Here's a code snippet that will help you with the toggle button animation if you would like to. You only need to add the functions that you want to execute when clicking of course, that's up to you.
'''
import tkinter as tk
# --- functions ---
def move(steps=10, distance=0.1):
if steps > 0:
# get current position
relx = float(frame.place_info()['relx'])
# set new position
frame.place_configure(relx=relx+distance)
# repeate it after 10ms
root.after(10, move, steps-1, distance)
def toggle(event):
if button["text"] == "Yes":
move(25, 0.02) # 50*0.02 = 1
button["text"] = "No"
print("Clicked on yes")
elif button["text"] == "No":
move(25, -0.02)
button["text"] = "Yes"
print("Clicked on no")
# --- main --
root = tk.Tk()
frame = tk.Frame(root, background='red')
frame.place(relx=0, rely=0, relwidth=0.5, relheight=1)
# to center label and button
#frame.grid_columnconfigure(0, weight=1)
#frame.grid_rowconfigure(0, weight=1)
#frame.grid_rowconfigure(3, weight=1)
button = tk.Button(frame, text='Yes',width=5,height=1)
button.place(relx=0.25,rely=0.5,relwidth=0.5, relheight=0.1)
button.bind("<Button-1>",toggle)
root.mainloop()
Albe's answer is good but it has some bad coding practices.
Following the same steps:
Import Tkinter as tk
top = tk.TK()
Define your function here and make it work for any button, not hard coded to the specific button you might use.
def toggle(button: tk.Button):
if button.config('relief')[-1] == 'sunken':
button.config(relief="raised")
else:
button.config(relief="sunken")
Then create and pack all the toggle buttons you want.
toggleButton = tk.Button(text="Toggle", width=12, relief="sunken",
command =lambda:toggle(toggleButton))
toggleButton.pack(pady=5)
top.mainloop()
This is better for two reasons. Creating the button object twice is redundant and will lead to buggy code. Hard coding the button to a specific toggle function is unscalable. This solution makes the code reusable and simple to add to. For example, replace that last block with:
for _ in range(4):
b = tk.Button(text="Toggle", width=12, relief="sunken")
b['command']= lambda a=b:toggle(a)
b.pack(pady=5)
And now you get 4 toggling buttons without any additional functions or copy/paste