from tkinter import *
from tkinter import ttk
def DOTEST_GUI():
GUI = Tk()
w = 1920
h = 1080
ws = GUI.winfo_screenwidth()
hs = GUI.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
GUI.geometry(f'{w}x{h}+{x:.0f}+{y:.0f}')
def start_p():
progress.start(5)
def stop_P():
progress.stop()
def print_cf(event = None):
import time
print('s')
start_p()
time.sleep(5)
stop_P()
B_TEST = ttk.Button(GUI, text = "test", width = 15, command = print_cf)
B_TEST.pack()
progress = ttk.Progressbar(GUI, orient = HORIZONTAL, length = 100, mode = 'indeterminate')
progress.pack(pady = 10)
GUI.bind("<Return>", print_cf)
GUI.focus()
GUI.mainloop()
DOTEST_GUI()
follow this code progress bar is not running properly.
I tried to remove stop_P(), it's work after 5 second of time.sleep(5).
I would like it to start running progress 5 second until the stop_P() code.
If you want to run a Progressbar for a set amount of time and then stop it, you could do something like this. Consolidate the print_cf function to start and stop the progress and set a range of 5, sleep for 1 second in between and then stop the Progressbar. Placing it on a thread would allow you to do something more time consuming than sleeping one second and printing something.
from tkinter import *
from tkinter import ttk
import time
import threading
def DOTEST_GUI():
GUI = Tk()
w = 1920
h = 1080
ws = GUI.winfo_screenwidth()
hs = GUI.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
GUI.geometry(f'{w}x{h}+{x:.0f}+{y:.0f}')
def run_thread():
execute_thread = threading.Thread(target=print_cf)
execute_thread.start()
def print_cf(event = None):
progress.start()
print('s')
for i in range(5):
print(i)
time.sleep(1)
if i ==4:
progress.stop()
B_TEST = ttk.Button(GUI, text = "test", width = 15, command = run_thread)
B_TEST.pack()
progress = ttk.Progressbar(GUI, orient = HORIZONTAL, length = 100, mode = 'indeterminate')
progress.pack(pady = 10)
GUI.bind("<Return>", print_cf)
GUI.focus()
GUI.mainloop()
DOTEST_GUI()
Related
I am programming a minesweeper and I am stuck because I still have to add a timer. I was able to program one but I can only see it in my console. But i want it to be in my game so that someone who is playong can see the time.
Now how do I add my programmed timer to the game? Down here is my code the first one is for the cell with all the definitions the second one is the main part and the last part is my time. I still have two files called settings and utils but these aren‘t important for the problem…
from tkinter import Button, Label
import random
import settings
import ctypes
import sys
import time
import elapsed
class Cell:
all = []
cell_count = settings.CELL_COUNT
cell_count_label_object = None
def __init__(self,x, y, is_mine=False):
self.is_mine = is_mine
self.is_opened = False
self.is_mine_candidate = False
self.cell_btn_object = False
self.x = x
self.y = y
self.done = False
# Append the object to the Cell.all list
Cell.all.append(self)
def create_btn_object(self, location):
btn = Button(
location,
width=10,
height=3,
)
btn.bind('<Button-1>', self.left_click_actions ) # Left Click
btn.bind('<Button-3>', self.right_click_actions ) # Right Click
self.cell_btn_object = btn
#staticmethod
def create_cell_count_label(location):
lbl = Label(
location,
bg='aquamarine3',
fg='white',
text=f"Cells Left:{Cell.cell_count}",
font=("", 30)
)
Cell.cell_count_label_object = lbl
def left_click_actions(self, event):
if self.is_mine:
self.show_mine()
else:
if self.surrounded_cells_mines_length == 0:
for cell_obj in self.surrounded_cells:
cell_obj.show_cell()
self.show_cell()
# If Mines count is equal to the cells left count, player won
if Cell.cell_count == settings.MINES_COUNT:
ctypes.windll.user32.MessageBoxW(0, 'Congratulations! You won the game!', 'Game Over', 0)
# Cancel Left and Right click events if cell is already opened:
self.cell_btn_object.unbind('<Button-1>')
self.cell_btn_object.unbind('<Button-3>')
def get_cell_by_axis(self, x,y):
# Return a cell object based on the value of x,y
for cell in Cell.all:
if cell.x == x and cell.y == y:
return cell
#property
def surrounded_cells(self):
cells = [
self.get_cell_by_axis(self.x - 1, self.y -1),
self.get_cell_by_axis(self.x - 1, self.y),
self.get_cell_by_axis(self.x - 1, self.y + 1),
self.get_cell_by_axis(self.x, self.y - 1),
self.get_cell_by_axis(self.x + 1, self.y - 1),
self.get_cell_by_axis(self.x + 1, self.y),
self.get_cell_by_axis(self.x + 1, self.y + 1),
self.get_cell_by_axis(self.x, self.y + 1)
]
cells = [cell for cell in cells if cell is not None]
return cells
#property
def surrounded_cells_mines_length(self):
counter = 0
for cell in self.surrounded_cells:
if cell.is_mine:
counter += 1
return counter
def show_cell(self):
if not self.is_opened:
Cell.cell_count -= 1
self.cell_btn_object.configure(text=self.surrounded_cells_mines_length)
# Replace the text of cell count label with the newer count
if Cell.cell_count_label_object:
Cell.cell_count_label_object.configure(
text=f"Cells Left:{Cell.cell_count}"
)
# If this was a mine candidate, then for safety, we should
# configure the background color to SystemButtonFace
self.cell_btn_object.configure(
bg='SystemButtonFace'
)
# Mark the cell as opened (Use is as the last line of this method)
self.is_opened = True
def show_mine(self):
self.cell_btn_object.configure(bg='red')
ctypes.windll.user32.MessageBoxW(0, 'You clicked on a mine', 'Game Over', 0)
sys.exit()
def right_click_actions(self, event):
if not self.is_mine_candidate:
self.cell_btn_object.configure(
text = '🌸',
fg = 'red'
)
self.is_mine_candidate = True
else:
self.cell_btn_object.configure(
bg='SystemButtonFace'
)
self.is_mine_candidate = False
def time():
start_time = time.time()
while True:
if not self.is_opened:
elapsed_time = time.time() - start_time
print(int(elapsed_time))
#staticmethod
def randomize_mines():
picked_cells = random.sample(
Cell.all, settings.MINES_COUNT
)
for picked_cell in picked_cells:
picked_cell.is_mine = True
def __repr__(self):
return f"Cell({self.x}, {self.y})"
from tkinter import *
from cell import Cell
import settings
import utils
import elapsed
import time
root = Tk()
# Override the settings of the window
root.configure(bg="aquamarine3")
root.geometry(f'{settings.WIDTH}x{settings.HEIGHT}')
root.title("Minesweeper Game")
root.resizable(False, False)
top_frame = Frame(
root,
bg='aquamarine3',
width=settings.WIDTH,
height=utils.height_prct(15)
)
top_frame.place(x=0, y=0)
game_title = Label(
top_frame,
bg='aquamarine3',
fg='white',
text='Minesweeper Game',
font=('', 48)
)
game_title.place(
x=utils.width_prct(30), y=0
)
left_frame = Frame(
root,
bg='aquamarine3',
width=utils.width_prct(75),
height=utils.height_prct(75)
)
left_frame.place(x=0, y=utils.height_prct(25))
timer_title = Label(
left_frame,
bg = 'aquamarine3',
fg = 'white',
text = ('time:', command = cell.time)
)
timer_title.place(
x = 0, y = 100
)
center_frame = Frame(
root,
bg='aquamarine3',
width=utils.width_prct(75),
height=utils.height_prct(75)
)
center_frame.place(
x=utils.width_prct(25),
y=utils.height_prct(15),
)
for x in range(settings.GRID_SIZE):
for y in range(settings.GRID_SIZE):
c = Cell(x, y)
c.create_btn_object(center_frame)
c.cell_btn_object.grid(
column=x, row=y
)
# Call the label from the Cell class
Cell.create_cell_count_label(left_frame)
Cell.cell_count_label_object.place(
x=0, y=0
)
Cell.randomize_mines()
# Run the window
root.mainloop()
import time
time.gmtime(0)
start_time = time.time()
def timer():
while True:
elapsed_time = time.time()-start_time
print(int(elapsed_time))
enter image description here
As you can see in the screenshot, my program has white lines on the left and top, how can I remove them? I would like them not to be there at all.
import ctypes as ct
from tkinter import *
def dark_title_bar(window):
window.update()
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
set_window_attribute = ct.windll.dwmapi.DwmSetWindowAttribute
get_parent = ct.windll.user32.GetParent
hwnd = get_parent(window.winfo_id())
rendering_policy = DWMWA_USE_IMMERSIVE_DARK_MODE
value = 2
value = ct.c_int(value)
set_window_attribute(hwnd, rendering_policy, ct.byref(value), ct.sizeof(value))
win = Tk()
background_menu = PhotoImage(file="background-menu.png")
canvas_authorization = Canvas(win, width=1280, height=720)
canvas_authorization.grid()
canvas_authorization.create_image(640, 360, image=background_menu)
dark_title_bar(win)
win.geometry("1280x720")
win.geometry(str(win.winfo_width()+1) + "x" + str(win.winfo_height()+1))
#Returns to original size
win.geometry(str(win.winfo_width()-1) + "x" + str(win.winfo_height()-1))
win.geometry("1280x720")
win.mainloop()
I'm trying to animate a "round" explosion with the colors in colors but whenever I run it, it freezes and does nothing.
Thank you!
from tkinter import *
from random import *
from time import *
from math import *
space = Tk()
s = Canvas(space, height = 1000, width = 1000, background = "light blue")
s.pack()
##EXPLOSION
xE = 375
yE = 475
x = []
y = []
r = []
rSpd = []
eAngle = []
xAr = []
yAr = []
colors = []
drawing = []
sleep(1)
cakeE = 500
colors = ["#EA7FF0","#E44FEE","#87078F","#F9DBFB","#F7B8FB","gray76","grey","white"]
for i in range( cakeE ):
x.append( xE )
y.append( yE )
xAr.append( randint(1, 3) )
yAr.append( randint(1, 3) )
r.append( 0 )
rSpd.append(0)
eAngle.append( uniform(1,15) )
eAngle.append( uniform(0, 2*pi) )
drawing.append(0)
colors.append( choice(colors) )
for f in range(400):
for i in range(cakeE):
drawing[i] = s.create_rectangle( x[i], y[i], x[i] + xAr[i], y[i]\
+ yAr[i], fill = colors[i] )
x[i] = xE + r[i] * cos( eAngle[i] )
y[i] = yE - r[i] * sin( eAngle[i] )
r[i] = r[i] + rSpd[i]
eAngle[i] = eAngle[i]+0.01
With the code you have provided (not a MCVE) its hard to help with the matter.
However here is an example use of after() to show you how it is used. This example should be enough for you to replace sleep() with after() keep in mind you will likely need to move some of your code into a function for this to work correctly.
from tkinter import *
space = Tk()
lbl = Label(space, text="Before timed event.")
lbl.pack()
def do_something():
global lbl
lbl.config(text="After timed event.")
# execute some code here
# set a 3 second timer to activate the do something function.
space.after(3000, do_something)
space.mainloop()
I am a beginner programmer. I have a task to make a GUI with a linear equation y=mx+b and a set of parameters where I can change the m and b values. I have both matplotlib and numpy. I also have tkinter for the GUI. This is what i have so far i edited my friends code on a coordinate GUI.
def onButtonValChange():
if X1.get() != '':
x[0] = float(X1.get())
if Y1.get() != '':
y[0] = float(Y1.get()
def createGraph(x,y):
graphRoot = Tk.Tk()
graphRoot.wm_title("Your Graph")
graphRoot.resizable(0,0)
f = Figure(figsize=(5, 4), dpi=100)
a = f.add_subplot(111)
a.plot(x, y)
canvas = FigureCanvasTkAgg(f, master=graphRoot)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
x = [1]
y = [1]
ButtonChangeValues = Tk.Button(root, text="Submit Change", command=onButtonValChange)
ButtonChangeValues.grid(row=11, columnspan=3)
ButtonCreateGraph = Tk.Button(root, text="Create This Graph", command=lambda: createGraph(x, y))
ButtonCreateGraph.grid(row="15", columnspan=3)
Tk.mainloop()
So here is some code that i use its a moving line graph but you could adapt the code to move only when you change the equation. all you would have to do is populate the lists of x0Coords y0Coords and xy0Coords with the right mx+b formula
# Run from IDLE or LXTerminal not IDLE 3
# for import spidev to work, must run as python (v2) not python3
from Tkinter import * #to run on python 2, use Tkinter, for python3 use tkinter
import math
from datetime import datetime, timedelta
import numpy as np
import spidev
#--------------------- variables -------------------------
#---user defined settings
screenWidth = 450
resolution = 5 #number of pixels between data points, for visual purposes only
samplePeriod = 100 #milliseconds, time between data points written to txt file
timeRange = .5 #minutes
#---end user settings
baseTime = int(timeRange*60*1000/screenWidth)
startTime = datetime.now()
nl = "\n"
root = Tk()
root.title("Simple GUI")
root.geometry("500x300") #widthxheight
C = Canvas(root, bg = "gray", height = 250, width = screenWidth)
x0Coords = []
y0Coords = []
xy0Coords = []
coordLength = int(screenWidth/resolution)
#---initiation of lists
for i in range(0,coordLength):
x0Coords.append(i*resolution)
y0Coords.append(125)
xy0Coords.append(0)
xy0Coords.append(0)
#putting X and Y corrdinites in a list
def coordinate():
global x0Coords, y0Coords, xy0Coords
for i in range(0,coordLength*2,2):
xy0Coords[i] = x0Coords[i/2]
xy0Coords[i+1] = y0Coords[i/2]
#print(xy0Coords)
#---End initiation of lists
c0 = C.create_rectangle(0,0,20,50)
cl0 = C.create_line(xy0Coords)
pressure = Label(root, text="test")
pressure.pack()
spi_0 = spidev.SpiDev()
spi_0.open(0, 0)
#--------------------------- End of Variables -------------------------
#--------------------------- Definitions ------------------------------
#shifts y values down in index in array to represent time moved forward
def shiftCoords(nextValue):
global y0Coords, xy0Coords
y0Coords.pop(0)
y0Coords.append(nextValue)
coordinate()
#updates the GUI based on the new time
def move_time():
global c0,cl0,xy0Coords, resolution, baseTime
C.delete(c0)
C.delete(cl0)
c0 = C.create_rectangle(0,0,20,int(float(readadc_0(0))/1023*250))
shiftCoords(125-int(float(readadc_0(0))/1023*125))
cl0 = C.create_line(xy0Coords)
#print(float(readadc_0(0))/1023*250)
root.title("V= " + str(round(3.3*float(readadc_0(0))/1023,2)))
root.after(baseTime*resolution,move_time)
C.pack()
root.after(baseTime,move_time)
root.after(samplePeriod,writeData)
root.mainloop()
Trying to animate a sequence of PIL images using tkinter. The graph of my frame durations (ms) looks like this:
Anyone have any idea what could be causing this spiky sawtooth pattern?
Here's a script to reproduce:
from PIL import Image, ImageTk
import Tkinter
import time
import sys
def generate_frames(n):
"""
keep n under 101 * 101
"""
out = []
last_pil = None
for i in range(n):
if last_pil:
pil_image = last_pil.copy()
else:
pil_image = Image.new('L', (101, 101), 255)
x = i / 101
y = i % 101
pil_image.load()[x, y] = 0
out.append(ImageTk.PhotoImage(pil_image))
last_pil = pil_image
return out
def draw():
FRAME_COUNT =5000
master = Tkinter.Tk()
w = Tkinter.Canvas(master, width=302, height=302)
w.create_rectangle(49, 49, 252, 252)
w.pack()
frames = generate_frames(FRAME_COUNT)
def draw_frame(f, canvas_image):
print repr(time.time())
frame = frames[f]
if canvas_image is None:
canvas_image = w.create_image((151, 151), image=frame, anchor='center')
else:
w.itemconfigure(canvas_image, image=frame)
w.current_frame = frame # save a reference
next_frame = f + 1
if next_frame < FRAME_COUNT:
master.after(1, draw_frame, next_frame, canvas_image)
else:
sys.exit(0)
master.after(10, draw_frame, 0, None)
master.mainloop()
draw()
To see the plot, pipe output through
import sys
last = None
for line in sys.stdin:
value = float(line.strip()) * 1000
if last is None:
pass
else:
print (value - last)
last = value
then through
from matplotlib import pyplot
import sys
X = []
Y = []
for index, line in enumerate(sys.stdin):
line = line.strip()
X.append(index)
Y.append(float(line))
pyplot.plot(X, Y, '-')
pyplot.show()
Making it multi-threaded doesn't help:
class AnimationThread(threading.Thread):
FRAME_COUNT = 5000
def __init__(self, canvas):
threading.Thread.__init__(self)
self.canvas = canvas
self.frames = generate_frames(self.FRAME_COUNT)
def run(self):
w = self.canvas
frames = self.frames
canvas_image = None
for i in range(self.FRAME_COUNT):
print repr(time.time())
frame = frames[i]
if canvas_image is None:
canvas_image = w.create_image((151, 151), image=frame, anchor='center')
else:
w.itemconfigure(canvas_image, image=frame)
w.current_frame = frame
time.sleep(1 * .001)
def draw_threaded():
FRAME_COUNT = 5000
master = Tkinter.Tk()
w = Tkinter.Canvas(master, width=302, height=302)
w.create_rectangle(49, 49, 252, 252)
w.pack()
animation_thread = AnimationThread(w)
animation_thread.start()
master.mainloop()
animation_thread.join()
draw_threaded()
That closely resembles this kind of interference pattern when competing 60 and 50 Hz samples mingle:
(Original Wolfram|Alpha plot)
This is likely caused by having two things at different (but close) refresh rates. It's the same type of thing that happens when you try to film a TV screen and it looks like a black bar keeps moving down the image, or when car wheels appear to rotate backwards around their axles in car commercials. It is essentially an extension of the Moiré Effect.
I don't know whether or not it is caused by video drivers and/or hardware, but it is almost certainly caused by interfering cyclical patterns. It looks a lot like it should be the GC cycle interfering with your for loop (hence the sudden drop in the sawtooth-like wave as memory is freed up and can be allocated)