Any way to get rid of Tk window while using Snack? - python

I'm trying to use Snack to make a simple mp3 player. It works together with Tkinter. Here is what documentation says about its usage:
The beginning of a program that uses Snack might look like:
from Tkinter import *
root = Tk()
import tkSnack
tkSnack.initializeSnack(root)
# Now you can use tkSnack commands and objects
# ...
The root = Tk() line opens an empty window, which could be closed after the initialization of Snack and Snack will continue to work the same (paying, pausing, resuming, loading audios and so on).
Is there any way to avoid the opening of this window? May you explain why such a library needs a graphical window in order to work?

If you use root = Tk().withdraw() then the Tk window will be created but not displayed. Hopefully it will not even flash on screen.
The Tcl snack package is a Tk extension and has a number of commands that call Tk functions. So the original design just didn't break it into windowing and non-windowing sections. However Tk is not required to use snack, but you must run an event loop at some point. For instance in a Tcl script (no Tk) you can do:
package require snack
snack::sound snd -file $filename
snd play -blocking 0
after 5000 {set waiting 1}
vwait waiting
This will setup a snd command with the file data configured and then tell it to play. However, nothing will happen until we start the event loop (vwait waiting) and in this case we schedule something to happen in 5 seconds to time the wait out.
Looking at the tkSnack sources can probably help you translate the above into something pythonic. They are just a wrapper around the Tcl/Tk package. But I suspect running the Tk window will help in getting the music playing.

You can use root.withdraw() method to hide your window.
Optionally, if you are ever planing to use it again, use root.deiconify()

Related

Importing and using mp3s on button press

So I have coded a "copy" of the game 2048 after following a Kite youtube tutorial. I want to add a small mp3 to play anytime you click an arrow key(to move stuff around in the game) but I'm not entirely sure what i'm doing right or wrong here. How do I do this?
I've snipped the important stuff out(import music is a folder for my mp3s)
import tkinter as tk
import mp3play
import music
The two errors I'm getting are down below, the Tk in Tk() is underlined and the root in left(root...)
when i attempt to run the code like this, it highlights "import mp3play" and says there is a Syntax error. Not sure why, I have in fact installed mp3play via pip installer as well
root = Tk()
f = mp3play.load('beep.mp3'); play = lambda: f.play()
button = left(root, text = "Play", command = play)
button.pack()
root.mainloop()
in between the 2 middle sections is the def for up, down, left, and right but that would just clutter this question
Here is the stackoverflow I've referenced for it, to be honest I dont understand half of it. How can I play a sound when a tkinter button is pushed?
Take a look at this simple example using winsound which is easier to handle for small beeps.
from tkinter import *
import winsound
root = Tk()
def play():
winsound.Beep(1000, 100)
b = Button(root,text='Play',command=play)
b.pack()
root.mainloop()
winsound.Beep(1000, 100) takes two positional arguemnts, 1000 is the frequency and 100 is the duration in milliseconds.
Do let me know if any errors or doubts.
Cheers

How to add Tkinter button that allows the user to play their own music?

Just a quick question: In a game, I'm making, I want the player to be able to pick an audio file from his/her computer and play it in the game and I'm not all that sure how to do it. I want them to be able to open a browse files screen (default file explorer) and then select a music file and play it as bgm, all by the click of a button.
Now I know Tkinter doesn't support sound but I don't care how the program runs. As long as I can fit it into my code. If you need my code, it's here: https://github.com/SeaPuppy2006/FruitClicker (I'm using my windows build at the moment). Thanks!
You could use playsound module and use a thread to prevent block:
from playsound import playsound
import tkinter
from tkinter import filedialog
import threading
def f():
def play():
pathname = filedialog.askopenfilename()
playsound(pathname)
threading.Thread(target=play).start()
root = tkinter.Tk()
tkinter.Button(root,text="playsound",command=f).grid()
root.mainloop()

How can i avoid Tkinter GUI freezing in Python3?

I am quite new in python and made a Tkinter application that will execute all python files existing in the directory when pressed the start button. My GUI also has progressbar to see the current progress.
so here is my code
import os
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
directory = dir_path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(directory)
root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')
v = 0
def begin():
global v
for x in files:
os.system('pyinstaller '+x)
v=v+1
p['value']=v
p = Progressbar(root,length=200,max=len(files))
b = Button(root,text="Start",command=lambda: begin())
p.place(x=0,y=0)
b.place(x=62,y=30)
root.mainloop()
but my problem is, Whenever i press start button, The GUI freezes and codes start getting compiled and when completed, the GUI unfreezes and the Progressbar fills itself full at once...
So i want the GUI not to freeze while processing and show correct progress on the Progressbar.
Example code and Explanation will be better for me.
Thanks for your valuable time...
This worked.No need to use .after() to check the thread is finished.
import os
from tkinter import *
from tkinter.ttk import *
import threading
def use_pyinstaller(): # this function is to execute pyinstaller command and add value to progressbar.
v = 0
for x in files:
os.system('pyinstaller '+x)
v+=1
p['value'] = v
def begin():
threading.Thread(target=use_pyinstaller).start() # create a non-block thread to start the function.
directory = dir_path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(directory)
root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')
p = Progressbar(root,length=200,max=len(files))
b = Button(root,text="Start",command=begin)
p.place(x=0,y=0)
b.place(x=62,y=30)
root.mainloop()
First off, the command argument for the button can just be: command=begin.
GUI toolkits like tkinter are event-driven. They depend on a smooth flow of keyboard and mouse events to work properly.
Callbacks (like the command from a button) are called from witin the event loop (root.mainloop).
So a callback should only take a short time (say 50 ms) as to not freeze the GUI. You should therefore never run a long-running loop in a callback. You have to program in a different style.
The above link takes you to an article on my website where I compare a simple command-line program with an equivalent GUI program. While that program doesn't use external processes, it illustrates the principle.
The proper way to do this in a GUI, is to start a multiprocessing.Process from the button callback.
Then use the root.after method to periodically run a callback that checks if the Process is finished, and then start a new process.

Is possible to have the console active only on certain times after compiling the py to exe using pyinstaller or anything else?

I’m building a program in python that will copy large files using robocopy. Since the gui freezes while the copy is done i only have two options:
1. Learn how to do multithreading and design the gui to show the progress and not freeze.
2. Keep the console on after compiling with pyinstaller as an alternative to show robocopy progress while the gui freezes.
I am open to doing multithreading but i’m a beginner and is pretty hard to understand how to make another subprocess for robocopy and from there extract the progress into a label from gui. The option i thought about is to have the cmd console active only while the copy is done. Is it possible? The scenario will be like this:
Open the program (the console will be hidden)
Press the copy button (console pops up and shows the copy progress while the gui freezes)
After the copy is done hide the console again
As i said above. I’m not totally excluding adding multithreading but for that i will need some help.
Thanks!
Please try this code, should be working, please let me know if something wrong:
import tkinter as tk
import os
import subprocess
import threading
main = tk.Tk()
main.title('Title')
frame_main = tk.Frame(main)
frame_main.grid(columnspan=1)
src = 'D:/path/to/the/folder'
dest = 'D:/path/to/the/folder2'
selection_platf = len(os.name)
def copy_build_button():
if selection_platf < 11:
subprocess.call(["robocopy", src, dest, r"/XF", 'BT V_SyncPackage.zip', "/S"])
else: #for linux
subprocess.call(["robocopy", src, dest, "/S"])
def copy_thread():
thread_1 = threading.Thread(target=copy_build_button)
thread_1.start()
button_main1 = tk.Button(frame_main, text="copy_build_button", width=50, height=5, fg="green", command=copy_thread)
button_main1.grid(column=0, sticky='N'+'S'+'E'+'W')
main.mainloop()

How to bring Tkinter window in front of other windows?

I'm working with some Tkinter Python code (Python 3.4), and I've come across a problem. When I create my Tkinter window it doesn't show up in front. I do it currently with the following code:
from tkinter import *
win = Tk()
win.minsize(width=1440, height=828)
win.maxsize(width=1440, height=828)
The minsize() and maxsize() make the window cover my entire screen, but the original python running window (The one that wouldprint("Hello, World!")) ends up on top. Is there a way to fix this? I'm running OS X 10.10.1.
Set it as the topmost (but it will always stay in front of the others):
win.attributes('-topmost', True) # note - before topmost
To not make it always in front of the others, insert this code before the mainloop:
win.lift()
win.attributes('-topmost', True)
win.attributes('-topmost', False)
Don't forget win.mainloop() at the end of your code (even if in some cases it's not explicitly required)
Other discussions on the same problem:
How to put a Tkinter window on top of the others
How to make a Tkinter window jump to the front?

Categories