How to combine tkinter and turtle? - python

I have a part of codes like this
import turtle
turtle.bgcolor("green")
draw = turtle.Turtle()
draw.speed(1000000)
draw.hideturtle()
draw.pensize(3)
draw.color("white")
def Board (a, x, y, size):
draw.pu()
draw.goto(x, y)
draw.pd()
for i in range (0, 4):
draw.forward(size)
draw.right(90)
x =-40
y = -40
size = 40
for i in range (0, 10):
for j in range (0, 10):
Board (draw, x + j*size, y + i*size, size)
turtle.done()
And like this
import tkinter
import tkinter.messagebox
window = tkinter.Tk()
def Button_click ():
tkinter.messagebox.showinfo("Game", "Tic Tac Toe")
button = tkinter.Button(window, text = "Play!", command = Button_click)
button.pack()
window.mainloop()
Since I'm trying to create a window with a button to enter the TicTacToe game (I haven't finished the rest, just only the board). Is there any way that I can do to combine both turtle and tkinter?
Thank you

Yes. Python turtle operates in two modes, standalone and embedded in a larger tkinter program. Instead of Turtle and Screen, when using turtle embedded, you work with RawTurtle, TurtleScreen and optionally ScrolledCanvas. You build your tkinter interface as needed, using a Canvas to contain your turtle graphics. You can find examples of embedding turtle in tkinter by searching SO for RawTurtle.
Here's an example of the same code written both embedded and standalone.

I was playing with your code while cdlane was answering your question! As cdlane said I replaced "turtle" with "RawTurtle" and put your button on the same window as the canvas. I prefer using grid than pack when placing things because I feel like I have more control.
import tkinter
import turtle
import tkinter.messagebox
window = tkinter.Tk()
canvas = tkinter.Canvas(master = window, width = 800, height = 800)
canvas.grid(padx=2, pady=2, row=0, column=0, rowspan=10, columnspan=10) # , sticky='nsew')
#draw = turtle.Turtle()
draw = turtle.RawTurtle(canvas)
def Board(a, x, y, size):
#draw.pu()
draw.penup()
draw.goto(x,y)
#draw.pd()
draw.pendown()
for i in range (0, 4):
draw.forward(size)
draw.right(90)
def Board2():
x =-40
y = -40
size = 40
for i in range (0, 10):
for j in range (0, 10):
Board(draw, x + j*size, y + i*size, size)
def Button_click ():
tkinter.messagebox.showinfo("Game", "Tic Tac Toe")
#button = tkinter.Button(window, text = "Play!", command = Button_click)
#button = Tk.Button(window, text = "Play!", command = Button_click)
#button.pack()
#
Play_Button = tkinter.Button(master = window, text ="Play!", command = Button_click)
Play_Button.config(bg="cyan",fg="black")
Play_Button.grid(padx=2, pady=2, row=0, column=11, sticky='nsew')
Board_Button = tkinter.Button(master = window, text ="Draw_Board", command = Board2)
Board_Button.config(bg="cyan",fg="black")
Board_Button.grid(padx=2, pady=2, row=1, column=11, sticky='nsew')
#
window.mainloop()

Related

Making a window UI scroll down and deleting labels from frame

I am making a random generator for my friends and I'm stuck trying to make a scroll down option. So if you generate more the window can show, a scroll down window should be possible. But I can't seem to get any to work. I've tried many online tutorials.
And my second issue with my code is that I can't clear the generated labels from the window. I got it working that it expands the window.
from cProfile import label
from pickle import FRAME
import random
import tkinter as tk
from tkinter import BOTH, DISABLED, LEFT, RIGHT, VERTICAL, Y, Frame, Label, filedialog, Text
import os
from tkinter import ttk
from tkinter.font import NORMAL
from tkinter.messagebox import YES
root = tk.Tk()
root.title('guesser')
#Pelin arvonta ohjelma !
def delete():
for child in root.children.values():
info = child.grid_info()
if info['column'] == 0:
child.grid_forget()
def arvonta():
global label
list1 = []
lista = ["Valorant","Rainbow","Vampire: The masquerade","Playerunknown's battlegrounds","Fortnite","Left 4 Dead 2","Counter strike Global offensive","Realm roayale","Black ops 1 zombies/multiplayer","Black ops 2 zombies/multiplayer","Black ops 3 zombies/multiplayer"]
numero = random.randint(0, 10)
hahmo = (lista[numero])
list1.append(hahmo)
for app in list1:
label = tk.Label(frame, text=app, bg="red",font=('Helvetica',20))
label.pack()
def valorant():
list2 = []
lista2 = ["Brimstone","Viper","Omen","Killjoy","Cypher","Sova","Sage","phoenix","Jett","Reyna","Raze","Raze","Breach","Skye","Yoru","Astra","Kay/o","Chamber","Neon","Fade"]
numero = random.randint(0, 19)
randomValorantagent=(lista2[numero])
list2.append(randomValorantagent)
for app in list2:
label = tk.Label(frame, text=app, bg="red",font=('Helvetica',20))
label.pack()
def quitter():
quit()
canvas = tk.Canvas(root,height=700,width=700,bg="#263D42")
canvas.pack(side=LEFT,fill=BOTH,expand=1)
frame = tk.Frame(root,bg="green")
frame.place(relwidth=0.8,relheight=0.8,relx=0.1,rely=0.1)
frame.pack(fill=BOTH,expand=1)
my_scrollbar = ttk.Scrollbar(frame, orient=VERTICAL, command=canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
# Configure The Canvas
canvas.configure(yscrollcommand=my_scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion = canvas.bbox("all")))
# Create ANOTHER Frame INSIDE the Canvas
second_frame = Frame(canvas)
# Add that New frame To a Window In The Canvas
canvas.create_window((0,0), window=second_frame, anchor="nw")
#rlls the game
openfile = tk.Button(second_frame,text="Roll a game",padx=10,pady=5,fg="white",bg="#263D42", command=arvonta)
openfile.pack()
#rolls a valorant agent
valorantA = tk.Button(second_frame,text='Roll valorant agent',padx=10,pady=5,fg="white",bg="#263D42",command=valorant)
valorantA.pack()
# stops program
stop = tk.Button(second_frame,text="Quit",padx=10,pady=5,fg="white",bg="#263D42",command=quitter)
stop.pack()
# deletes all info from screen.
deletor = tk.Button(second_frame,text="delete info",padx=10,pady=5,fg="white",bg="#263D42",command=delete)
deletor.pack()
root.mainloop()```
The following does most of what you want. I wrote it some time ago to test Scrollbars because they are wonky IMHO
from tkinter import *
from functools import partial
class ButtonsTest:
def __init__(self):
self.top = Tk()
self.top.title("Click a button to remove")
self.top.geometry("425x200+50+50")
Label(self.top, text=" Click a button to remove it ",
bg="lightyellow", font=('DejaVuSansMono', 12)
).grid(row=0, sticky="nsew")
Button(self.top, text='Exit', bg="orange", width=9,
command=self.top.quit).grid(row=1,column=0,
sticky="nsew")
self.add_scrollbar()
self.button_dic = {}
self.buttons()
self.top.mainloop()
##-------------------------------------------------------------------
def add_scrollbar(self):
self.canv = Canvas(self.top, relief=SUNKEN)
self.canv.config(width=400, height=200)
self.top_frame = Frame(self.canv, height=100)
##---------- scrollregion has to be larger than canvas size
## otherwise it just stays in the visible canvas
self.canv.config(scrollregion=(0,0, 400, 500))
self.canv.config(highlightthickness=0)
ybar = Scrollbar(self.top, width=15, troughcolor="lightblue")
ybar.config(command=self.canv.yview)
## connect the two widgets together
self.canv.config(yscrollcommand=ybar.set)
ybar.grid(row=3, column=2, sticky="ns")
self.canv.grid(row=3, column=0)
self.canv.create_window(1,0, anchor=NW,
window=self.top_frame)
##-------------------------------------------------------------------
def buttons(self):
b_row=1
b_col=0
for but_num in range(1, 51):
## create a button and send the button's number to
## self.cb_handler when the button is pressed
b = Button(self.top_frame, text = str(but_num), width=5,
command=partial(self.cb_handler, but_num))
b.grid(row=b_row, column=b_col)
## dictionary key=button number --> button instance
self.button_dic[but_num] = b
b_col += 1
if b_col > 4:
b_col = 0
b_row += 1
##----------------------------------------------------------------
def cb_handler( self, cb_number ):
print("\ncb_handler", cb_number)
self.button_dic[cb_number].grid_forget()
##===================================================================
BT=ButtonsTest()

Problems while drawing straight line and dragging in Tkinter canvas

So, I'm trying to draw vertical lines in canvas on the click of the button "line".
These are the problems and my requirements:
When i try click on the line drawn to drag it to a position, it repels away from the mouse cursor but moves in the correct direction. What do i do to prevent this?
On subsequent clicks on the "line" button, i want a new line to be drawn (every time i click) while the original lines stays in the canvas unmoved.
The latest line is the only one which can be dragged. All other lines should be static.
I want coordinates of all these drawn lines. How do i get these?
This is the code i've written:
from tkinter import *
import tkinter
root = Tk()
canvas = tkinter.Canvas(root, width = 480,height = 600)
canvas.pack()
def draw_lines():
canvas.create_line(300, 35, 300, 200, dash=(4, 2))
def drag(event):
event.widget.place(x=event.x_root, y=event.y_root,anchor=CENTER)
canvas.bind("<B1-Motion>", drag)
btn1 = Button(root, text = 'line', bd = '5',command = draw_lines)
btn2 = Button(root, text = 'Close', bd = '5',command = root.destroy)
btn1.pack(side = 'top')
btn2.pack(side = 'top')
canvas.mainloop()
please help!!!!
Using Python 3.11.0rc1.
I added:
geometry. so it will not resize when dragging.
Canvas. You have to play around with height set to 800
I removed bd=5. You can suit yourself. Don't use quote.
I removed Quotes for this btn1.pack(side=TOP)
At last canvas.pack() always next to mainloop()
Here is the code re-worked:
from tkinter import *
root = Tk()
root.geometry('400x650')
canvas = Canvas(root, width=480, height=600)
def draw_lines():
canvas.create_line(300, 35, 300, 200, dash=(4, 2))
def drag(event):
event.widget.place(x=event.x_root, y=event.y_root,anchor=CENTER)
canvas.bind("<B1-Motion>", drag)
btn1 = Button(root, text='line', command=draw_lines)
btn2 = Button(root, text= 'Close', command=root.destroy)
btn1.pack(side=TOP)
btn2.pack(side=TOP)
canvas.pack()
canvas.mainloop()
Result output:

Using Tkinter to draw and track a mouse pointer

im still learning to use Python and Tkinter.
I have created a bit of code which (i thought) should create a canvas with 2 dots on and afterwards continuously printers the position of the mouse curser
from tkinter import *
from win32 import win32gui
win = Tk()
def mouse_pos():
flags, hcursor, (x, y) = win32gui.GetCursorInfo()
return {"x": x, "y": y}
win.geometry("1500x900")
win.configure(background="black")
g_circle = Canvas(win, width=100, height=100, bg="black", bd=1, highlightthickness=0)
g_circle.place(x=100, y=100, in_=win)
g_circle.create_oval(50, 50, 100, 100, fill="green", offset="200,200", outline="white")
b_circle = Canvas(win, width=100, height=100, bg="black", bd=1, highlightthickness=0)
b_circle.place(x=1300, y=700, in_=win)
b_circle.create_oval(50, 50, 100, 100, fill="blue", outline="white")
while True:
print(mouse_pos())
win.mainloop()
I know there is an infinite loop but i am just testing it for now.
This issue is that when i run this code a TK window opens of the canvas with 2 circles and then a cmd displays an single value for x and y coordinate in text. The coordinates do not continue to update unless i close the TK window and i dont know why.
Ill post a screenshot in hopes it helps.
Any help is appreciated.
win.mainloop() will block the while loop until the main window is closed.
You can use .after() to replace the while loop:
...
def mouse_pos():
# no need to use external module to get the mouse position
#flags, hcursor, (x, y) = win32gui.GetCursorInfo()
x, y = win.winfo_pointerxy()
print({"x": x, "y": y})
# run mouse_pos() again 10 microseconds later
win.after(10, mouse_pos)
...
''' don't need the while loop
while True:
print(mouse_pos())
win.mainloop()
'''
# start the "after loop"
mouse_pos()
win.mainloop()

How can I randomize the position of a button with Tkinter?

I would like the buttons to be placed in random points of the root. I do not understand why they all stack in the middle, since I think I am placing them at random x and y
import tkinter as tk
from tkinter import *
from random import randint
num_buttons = int(input("How many buttons do you want?"))
buttons = [0] * num_buttons
root = tk.Tk()
canvas = tk.Canvas(root, height=700, width=700, bg="dark slate grey")
canvas.pack()
frame = tk.Frame(root, bg="red")
frame.place(relheight=0.6, relwidth=0.6, rely=0.2, relx=0.2)
for k in range(num_buttons):
randx = int(randint(-100,100))
randy = int(randint(-100,100))
buttons[k] = tk.Button(frame, text="DO NOT CLICK ME",
fg="Black", highlightbackground="orange",
command=you_clicked)
buttons[k].place(x=randx, y=randy)
buttons[k].pack()
root.mainloop()
You should not be calling both place and pack. Only one geometry manager can control a widget. When you call pack, any effect a previous call to place is thrown away.

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