Can you make a functional invisible button in tkinter? - python

Can I make a button that is functional yet isn't visible? I've looked into a bunch of Tkinter threads, but when I tested the codes, they all led to the button completely disappearing and being disabled. Here is what I've got so far:
import tkinter as tk
import time
app=tk.Tk()
app.minsize(500, 500)
#button function
def move():
button.config(state='disabled')
for i in range(50):
frame.place(x=250+i)
frame.update()
time.sleep(0.01)
frame.place(x=250, y=250)
button.config(state='normal')
block=tk.Frame(app, height=50, width=50, bg='red')
frame=tk.Frame(app, height=400, width=400, bg='blue')
#button I wish to be invisible
button=tk.Button(app, text='clickme', command=move)
button.place(x=40, y=40)
frame.place(x=250, y=250, anchor='center')
block.place(x=50, y=50)
app.mainloop()

No, you cannot make an invisible button in tkinter. It must be on the screen for the user to be able to click it.
You can, however, react to clicks anywhere in the window without the need to create a button.

You can set buttons bg and fg same as the frame/root color and set borderwidth=0. This will create a invisible button.
For example refer this
from tkinter import *
root = Tk()
masterFrame = Frame(root, bg='orange', height=300, width=600)
masterFrame.grid(row=0, column=0, sticky='nsew')
Button(masterFrame, text="Invisible button", bg='orange', fg='orange', borderwidth=0).pack()
root.mainloop()

There's a little more to it than just seting the fg and bg, but yeah it can be done.
#! /usr/bin/env python3
from tkinter import *
color = 'SlateGray4'
width, height = 300, 150
desiredX, desiredY = width *0.5, height *0.75
root = Tk() ; root .title( 'Snozberries' )
root .geometry( f'{width}x{height}' )
root .bind( '<Escape>', lambda e: root .destroy() )
root .configure( bg = color )
def one(): ## takes many parameters during construction
print( 'Found a button!' )
def two( event ):
## print( f'x: {event .x}, y: {event.y}' )
if event .x >= desiredX -25 and event .x <= desiredX +25 \
and event .y >= desiredY -25 and event .y <= desiredY +25:
print( 'Found another button!' )
Label( root, bg=color, text='We are the musicmakers,' ) .pack()
Label( root, bg=color, text='and we are the dreamers of the dreams.' ) .pack()
Button( root, bg=color, fg=color, activebackground=color, activeforeground=color,
highlightbackground=color, borderwidth=0, command=one ) .pack()
Label( root, bg=color, text='Button, button' ) .pack()
Label( root, bg=color, text="who's got the button?" ) .pack()
root .bind( '<Button-1>', two )
root .mainloop()

Related

Pack 4 frames inside the window (tkinter)

Good day everyone!
I need to place four frames inside the window as shown in the picture, and using the .pack() method.
Now I have 3 frames placed in the window (picture before), and I want to add another one by moving frame f11 to the right. I also attach a picture with how it should look as a result (picture after).
Current part of code:
f11 = LabelFrame(current_tab, borderwidth=2, pady=5, relief=GROOVE, labelwidget=lbl_frm_wdgt_founder)
f11.pack(side=BOTTOM, fill=BOTH)
frame_left = Frame(current_tab, borderwidth=0, relief=GROOVE)
frame_left.pack(side=LEFT, fill=BOTH)
frame_right = LabelFrame(current_tab, labelwidget=lbl_frm_wdgt_arb, borderwidth=2, relief=GROOVE)
frame_right.pack(side=RIGHT, fill=BOTH)
frame_bottom_left = Frame(current_tab, borderwidth=2, relief=GROOVE)
# frame_bottom_left.pack(???)
If you don't want to / can't use grid(), you can use tk.Frame() widgets as generic containers
import tkinter as tk # don't use star imports!
from tkinter import ttk
top_container = tk.Frame(current_tab)
top_container.pack(expand=True, fill=tk.X, side=tk.TOP)
# top container children
frame_left = Frame(
top_container,
borderwidth=0,
relief=tk.GROOVE
)
frame_left.pack(side=tk.LEFT, fill=tk.BOTH)
frame_right = LabelFrame(
top_container,
labelwidget=lbl_frm_wdgt_arb,
borderwidth=2,
relief=tk.GROOVE
)
frame_right.pack(side=tk.RIGHT, fill=tk.BOTH)
bottom_container = tk.Frame(current_tab)
bottom_container.pack(expand=True, fill=tk.X, side=tk.BOTTOM)
# bottom container children
frame_bottom_left = tk.Frame(
bottom_container,
borderwidth=2,
relief=tk.GROOVE
)
frame_bottom_left.pack(side=tk.LEFT, fill=tk.BOTH)
f11 = ttk.LabelFrame(
bottom_container,
borderwidth=2,
pady=5,
relief=tk.GROOVE,
labelwidget=lbl_frm_wdgt_founder
)
f11.pack(side=tk.RIGHT, fill=tk.BOTH)
Since the container frames are packed separately, you can use one on top and another on the bottom
P.S.: Try to avoid * star imports - make sure to properly namespace all constants e.g. tk.LEFT and classes e.g. ttk.LabelFrame

How can I make events based on the active window? (python)

How can I make it so that when a certain window is active, the resolution is 1440x1080, but if any other window is active the resolution is 1920x1080 in Python?
(the comments are on purpose)
I'm using tkinter and I've tried:
import subprocess
import tkinter as tk
window = tk.Tk()
if tk.ACTIVE('notepad.exe') *res changing command*
else *res changing command*
# def setresEvent(event):
def startwinexpEvent(event):
subprocess.call(['C:\\Users\\VBucks\\Workspaces\\winexp\\winexp.exe'])
#setRes = tk.Button(
# text='Click me!',
# height=28,
# width=32,
# bg='black',
# fg='white',
#)
# setRes.bind('<Button-1>', setresEvent)
#setRes.pack()
startwinExp = tk.Button(
text='Start winexp',
height=28,
width=32,
bg='black',
fg='white',
)
startwinExp.bind('<Button-WinExp>', startwinexpEvent)
startwinExp.pack()
window.mainloop()

How do I adjust this frame with scrollbar inside the black space?

I want to fit this frame with scrollbar(refer the provided image) in the black space present in the provided image. How do I do that. The frame should totally cover the black space.
The code for program.The image
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand="false", padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y")
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(side=RIGHT,expand="false", padx=0, pady=200)
for i in range(50):
Button(myframe, image=ML,bg="gray6",bd=0).pack()
mainloop()
EDIT:
Music_Label
Mainscreen bg
So after trying to understand the underlying problem for a while I have reached the conclusion, that the problem is with the fact that the button are being drawn in the myframe and the myframe is outside the mycanvas which contains the scrollbar. So by changing the master widget for the button from myframe to mycanvas, the problem gets fixed now the scrollbar is adjacent to the buttons. BUT, Also now the button r shifted the side since while packing the wrapper1, you did side = RIGHT, so I would also suggest that you use place here instead of pack, since pack depends on the space available and is not reliable if you are using a Background for your GUI and want the buttons within a portion of it.
I have changed the following lines -:
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Changed to mycanvas from myframe
and
wrapper1.place(x = {YOUR X, WHERE THE BOX STARTS}, y = {YOUR Y, WHERE THE BOX STARTS}) # Use place instead..
You can use pack also, and change the padx and pady arguments but it will be tricky to get it to work always as expected.
The fixed code is this -:
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand=False, padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y", expand = False)
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(expand=True, padx=0, pady=200) # Use place instead
for i in range(50):
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Change this to mycanvas from myframe
mainloop()

How to use the same button to generate and remove specific text label from Tkinter Canvas?

I just started to learn Tkinter. Going through a beginner project I tripped over this situation where I have to use the same button to generate a string and replace it with a new one as the new ones are overlapping the old ones. Here're the code segments:
def ranQ():
if root.count < len(root.LoQ):
tx=canv.create_text(400, 50, text=root.LoQ[root.count], font=('Jokerman', 15), fill="Purple")
root.count += 1
else:
# l2 = Label(root, text="End of 7 questions! Click to generate again!", fg= "white", bg ="red")
# l2.pack()
canv.create_text(400, 450, text="End of 7 questions! Click to generate again!", font=('Jokerman', 10), fill="Purple")
root.count=0
random.shuffle(root.LoQ)
# defining background image
im = PhotoImage(file="{path}")
# Creating a canvas
canv = Canvas(root, width =800, height=500)
canv.pack(fill ="both", expand= True)
# Putting the image in canvas
canv.create_image(0,0, image=im, anchor='nw')
# adding a text label
canv.create_text(400,450,text ="7 Random Questions!", font=('Jokerman',50), fill="black")
canv.create_text(404,454,text ="7 Random Questions!", font=('Jokerman',50), fill="purple")
# adding the generate button
btn_g = Button(root, text='Press to generate a random question'.upper(),font=('Jokerman',10), padx=60, pady=20, fg="white", bg='Red',
command=ranQ)
b_window = canv.create_window(220,225,anchor="nw", window= btn_g)
Have you tried something like this?:
import tkinter as tk
from random import randint
def callback():
new_text = randint(0, 100)
# Reconfigure the text
canvas.itemconfig(text_id, text=new_text)
root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200)
canvas.pack()
# Save the text id that the canvas gives us
text_id = canvas.create_text(100, 100, text="")
button = tk.Button(root, text="Click me", command=callback)
button.pack(fill="x")
root.mainloop()
Basically you reconfigure the text. You can find more info here

How to call Turtle window from a GUI

I'm trying to open a Turtle window from a GUI to select a position on the image with a mouse click. The x and y coordinates are then returned as an input to the GUI.
Here is a minimal working example:
from tkinter import *
from tkinter import font as tkFont
import turtle
xclick = 0
yclick = 0
def callback3():
getcoordinates()
def getcoordinates():
screen = turtle.Screen()
screen.setup(400, 400)
screen.bgpic("stunden.gif")
screen.onscreenclick(modifyglobalvariables)
def modifyglobalvariables(rawx,rawy):
global xclick
global yclick
xclick = int(rawx//1)
yclick = int(rawy//1)
print(xclick)
print(yclick)
turtle.bye()
root = Tk()
helv30 = tkFont.Font(family='Helvetica', size=30)
button1 = Button(root, text = "1", width=3, font=helv30, borderwidth=0, command=callback3)
button1.grid(row=0, column=0, padx=5, pady=0)
root.mainloop()
Then the error image "pyimage2" doesn't exist shows up. I found out, that it has something to do with two instances of Tk, as there is the root and the turtle window and that I should solve it with Toplevel(). However, after hours of research and try and error I still could not come up with the right solution to make my code work. Any help is greatly appreciated.
Here's how to implement it directly in tkinter — so no turtle module required — as I suggested earlier in a (now-deleted) comment:
from tkinter import *
from tkinter import font as tkFont
CLOCK_IMAGE_PATH = 'clock.png'
xclick, yclick = 0, 0
def callback3():
window = Toplevel()
window.title("Stunden")
img = PhotoImage(file=CLOCK_IMAGE_PATH)
img_width, img_height = img.width(), img.height()
window.minsize(width=img_width, height=img_height)
canvas = Canvas(window, width=img_width, height=img_height)
canvas.pack()
canvas.image = img # Keep reference to avoid image being garbage collected.
canvas.create_image(0, 0, anchor='nw', image=img)
canvas.bind("<Button-1>", get_coordinates) # Set up event-handler callback.
def get_coordinates(event):
global xclick, yclick
xclick = int(event.x // 1)
yclick = int(event.y // 1)
print(f'xclick={xclick}, yclick={yclick}')
root = Tk()
helv30 = tkFont.Font(family='Helvetica', size=30)
button1 = Button(root, text="1", width=3, font=helv30, borderwidth=0, command=callback3)
button1.grid(row=0, column=0, padx=5, pady=0)
root.mainloop()

Categories