How to manipulate tkinter GUI from an imported file - python-3.x

I try to create a small GUI with tkinter. To make my code more readable I want to split the code in 2 files. One for the GUI information and one for the process informations. Or is it a bad idea?
So I create a gui.py where I import my process informations from program.py.
gui.py:
import tkinter as tk
from program import *
root = tk.Tk()
btn_Start = tk.Button(text="Start", command=start_loop)
btn_Stop = tk.Button(text="Stop", command=stop_loop, state=tk.DISABLED)
btn_Start.grid(row=1, column=0)
btn_Stop.grid(row=1, column=1)
root.mainloop()
program.py:
def start_loop():
print('disable Start button and enable Stop button')
# what is the code to disable the start button and enable the stop button?
def stop_loop():
print('disable Stop button and enable Start button')
# what is the code to disable the stop button and enable the start button?
How do I tell the button the disable/enable information in my program.py file? I do not understand how I get the information from the gui to the program and back to the gui?
Thanks for your help

For such a small program, it is overkill.
Looking at the tkinter programs I've written, all of them are between 200−300 lines. This is including headers, comments and blank lines. The number of actual code lines is 100−200.
In my opinion that is small enough to comfortably handle in an editor in one file.
Looking over most of my source code repositories, the longest Python files tend to top out at around 230 lines of actual code.
Keeping all the code in one file has significant advantages for a program when you need to install it. Just copy the file and you're done. No need for modules and a setup.py.

Related

Python Tkinter: Run python script when click button_widget of tkinter and keep value from return variables

I am new with GUI programming in Python 3.x with Tkinter.
I have prepared a GUI where user needs to select options (using OptionMenu widget) and after selection press button to run the final program.
I have saved the user selected data into variables in that GUI program.
But don't know what should I do next...
What I want:
That GUI should be hidden or End after pressing the button.
Run another python script and use those saved variables from that GUI in my script.
How it can be done in python.
You can save your data in another file in order to use it in other script with pickle module.
To save you can do a list with all the variables you want:
import pickle
with open('doc_name.txt','wb') as a:
pickle.dump(saved_variable_list,a)
And in another python script you can use that list of variables:
import pickle
with open('doc_name.txt','rb') as a:
saved_variable_list = pickle.load(a)
Finally to close your GUI you can use the 'destroy' command:
root.destroy()

Multithreaded Music Playing with Pygame in Terminal

I am attempting to make a text game and add some music to it and maybe sounds too, however, the "Big and Greatest" answer was Pygame. After testing with it, I found that when you use ANY Pygame function, it stops the current terminal session from printing any more output, this stops the game from continuing.
I first tried the usual...
from pygame import *
def some_function():
mixer.load("music.mp3")
mixer.music.play(0)
clock = time.Clock()
clock.tick(10)
while mixer.music.get_busy():
clock.tick(10)
Rest_of_function
And of course this does not work because it is a loop and is doing it in order so I next tried...
from file_with_music import * #added threading to this file
def main():
file_with_music.start()
Rest_of_Function
This however did not work as the annoying "Welcome to pygame" popup blocked terminal output again...
SO the next step was to make a new file and...
from Main import *
from Intro_Sounds import *
if __name__ == '__main__':
Intro_Thread.start() #Intro did not start because pygame popup was somehow called
Music_Thread.start()
Even after putting them both in threads, it still did not work...
As a side note, there is a function built into Main that is meant to execute
Music_Thread.join()
Music_Thread.stop()
After certain input is met.
The expected result is for it to play music in the background while the terminal continues printing out input and accepting input up until the input that would kill the Music thread is input. Of course, it did not work, and I am at a loss...
How can music be played without freezing the terminal.
The pygame.mixer sadly doesn't have this capability (as far as I know). Use winsound instead:
import winsound # only on windows tho...
winsound.PlaySound('sound.wav', winsound.SND_ASYNC) # this will play the sound and...
print('I can still print :D') # this can still print :D
After trying a few things I found...
Pygame is not friendly with sound and terminal output, so it won't work.
WxPython no longer has a functional sound module, making it useless.
Other projects are abandoned or OS specific...
However, I found that PyOpenAL actually works, although it can't understand mp3 files or 32bit float wav. Instead of using multithreading I switched to multiprocessing (making a 2000 line script to properly learn how the module works) and now the sound plays (and loops) while allowing terminal output.
TL:DR
PyOpenAL is the winner.
please try as follow--
from pygame import *
def some_function():
pygame.mixer.music.load("music.mp3")
pygame.mixer.music.play(0)
clock = time.Clock()
clock.tick(10)
while pygame.mixer.music.get_busy():
clock.tick(10)
Rest_of_function

Python doesnt respond after calling filedialog.askopenfilename() from TK

this is my first question:
Im looking to implement a interactive way to look for a path and then load the data frame with pandas.
Im using Tk, when i run the code it seems like the terminal is running a infinite loop.
`import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
file_path_to_open = filedialog.askopenfilename()`
where is my error ? any advice? im looking for something similar to uigetfile from MATLAB in python.
I don't know whether this answer is still useful for you, but maybe for those people having the same issue and coming here via google:
The issue is not caused by the piece of code itself, because that is working fine. See also Quick and easy file dialog in Python?
I assume it is caused because of some background tk processes which were not closed cleanly.
My solution was to restart the python kernel (using Jupyter Notebook with python 3.6) and reimporting. Also, it might help to close all background python processes, which might be still running, via the task manager.

Tkinter CPU activity after inserting text from file

If I take a 25MB/190,000 line text file and dump it into a text widget the process finishes quickly but I still see python.exe using 50%CPU for another minute or so afterwards. The bigger the file, the longer it takes for the CPU to drop off to 0% usage. When I start loading multiple files into different text widgets they load into the widget instantly but the CPU stays at 50% and the GUI runs horribly slow until it finishes whatever its doing in the backend. Can someone explain to me why the CPU is still being used and why its impacting performance if the text is already in the widget? What is it needing to do? Any way around this?
from tkinter import *
file = r"C:\path\to\large\file.txt"
def doit():
with open(file, 'r') as f:
txt.insert('end', ''.join(f))
f.close()
main = Tk()
txt = Text(main)
txt.grid(row=0)
btn = Button(main, text="click here", command=doit)
btn.grid(row=1, columnspan=2)
main.mainloop()
I thought maybe it was because im handling the file line by line instead of loading the entire file into RAM. I tried readlines() but I get the same results.
Most likely it is calculating where the line breaks go, for lines past the area currently visible on the screen. With the numbers you gave, the lines average over 130 characters long; if some of them are considerably over that, this is a situation that Tkinter is known to be slow in.
You could perhaps turn off word-wrap (by configuring the Text with wrap=NONE), which would probably require that you add a horizontal scroll bar. If that is unacceptable, it's possible that adding newlines of your own could help, if there's some natural point at which to insert them in your data.
Note that ''.join(f) is a rather inefficient way to read the entire file into a single string - just use f.read() for that.

Copy-Paste In Python

I am new to python. So I wanted to improve my skills. Before posting this question I tried to find some code or an idea that would guide me with what I intend to do. I did see some examples and posts on SO and other sites. But they all(the ones I came across) showed how to do it for single object. Below is what I want to do.
I want to write a utility in python that would allow me to choose from content I want to paste based on what my last 10,say, copy commands were for.
suppose I clicked copy when selecting a folder and then later I selected some text and pressed ctrl+c. Now I want to get option that would let me paste both the folder as well as the text.
Is that possible?
Thanks.
You could save the last 10 text items from a clipboard using tkinter:
#!/usr/bin/env python3
from tkinter import Tk
from collections import deque
def call_repeatedly(root, delay, func, *args):
func(*args)
root.after(delay, call_repeatedly, root, delay, func, *args)
def poll_clipboard(root, items):
text = root.clipboard_get()
if not items or items[-1] != text:
items.append(text)
def main():
root = Tk()
root.withdraw() # hide GUI
clipboard_items = deque(maxlen=10) # save last 10 clipboard items
call_repeatedly(root, 50, poll_clipboard, root, clipboard_items) # ms
call_repeatedly(root, 1000, print, clipboard_items) # print every second
root.after(10000, root.destroy) # exit in 10 seconds
root.mainloop()
main()
It polls clipboard every 50 ms. Polling is bad in general if there is an alternative interface that could allow you to subscribe to the clipboard events to be notified when new item is copied into the clipboard.
will it work for any kind of content, text, images etc. ?
This code works with text only. In general, you could get/set other types e.g., images (gtk, qt might provide a cross-platform way to do it).
Will it allow me to copy-paste text across all the applications ?
You are working with a clipboard so yes, it should work across all applications that can
work with a clipboard.
Can we make it work as normal ctrl+c (copy command)
Copy command can be implemented using a set command e.g., from pyperclip.py:
def gtkSetClipboard(text):
cb = gtk.Clipboard()
cb.set_text(text)
cb.store()
gtkSetClipboard(text) copies text to the clipboard.

Resources