Here is a minimum working example of my code.
I am trying to plot a live graph using matplotlib by taking some inputs from the user via gui. For building the gui, I used the library easygui
However, there is one problem:
the graph stops building while taking an update from the user and I wish it to continue. Is there something that I'm missing here.
#!/usr/bin/env python
from easygui import *
from matplotlib.pylab import *
import numpy
import random
n = 0
fig=plt.figure()
x=list()
y=list()
plt.title("live-plot generation")
plt.xlabel('Time(s)')
plt.ylabel('Power(mw)')
plt.ion()
plt.show()
calculated=[random.random() for a in range(40)]
recorded=[random.random() for a in range(40)]
possible=[random.random() for a in range(5)]
plt.axis([0,40,0,10000])
for a in range(0, len(recorded)):
temp_y= recorded[a]
x.append(a)
y.append(temp_y)
plt.scatter(a,temp_y)
plt.draw()
msg = "Change"
title = "knob"
choices = possible
if a>9:
b = (a/10) - numpy.fix(a/10)
if b==0:
choice = choicebox(msg, title, choices)
print "change:", choice
here is the download link for easygui
sudo python setup.py install
based on your version of linux or OS. use the following link
Thanks to J.F. Sebastian
import easygui
from Tkinter import Tk
from contextlib import contextmanager
#contextmanager
def tk(timeout=5):
root = Tk() # default root
root.withdraw() # remove from the screen
# destroy all widgets in `timeout` seconds
func_id = root.after(int(1000*timeout), root.quit)
try:
yield root
finally: # cleanup
root.after_cancel(func_id) # cancel callback
root.destroy()
with tk(timeout=1.5):
easygui.msgbox('message') # it blocks for at most `timeout` seconds
Related
My project said to "Implement the class for the display of the amplitude of the wave file or frequency entered and create the method that will extract a portion of the waveform to display." I am having trouble passing the user input from one file to another without importing the entire file (tried that gave me errors)
Here's some of my main file:
import tkinter as tk
import winsound
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog``
from tkinter import simpledialog
import Create_Account
import Login_file
import Display_Waveform_Amplitude
class audioFrequencyGUI:
#...... (skipping unimportant code)
def Play(self, Hz):
self.play_frequency.config(command = lambda: winsound.Beep(Hz, 500))
#MAIN LOOP
tk.mainloop()
def Display_Waveform(self):
DisplayWindow = Display_Waveform_Amplitude.Display_Waveform_AmplitudeGUI()
DisplayWindow.amplitude_window.wait_window()
Heres Display Waveform File:
import tkinter as tk
from tkinter import*
import numpy as np
import matplotlib.pyplot as plt
class Display_Waveform_AmplitudeGUI:
def __init__(math):
math.amplitude_window = tk.Tk()
math.amplitude_window.title("Amplitude Display")
math.amplitude_window.minsize(width = 500, height = 500)
def plot_graph(math):
time = 1/frequency
x = np.arrange(0, time, 0.1)
y = frequency - 1
plt.title('Amplitude Waveform: Entering Frequencies')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude')
plt.plot(x, y)
plt.show()
I know in my code I haven't passed anything because I simply don't know what to do. I've been moving things around and trying out different things for days. I just need to know how to pass the frequency from my main file to another file that contains another class and function. Thank you I appreciate the help!
If files are in same folder
I think you can solve this just importing the class in the main.py file into display file:
from main import audioFrequencyGUI
Now you can use funcs from main.py file inside display.py
#!/usr/bin/env python
# # myGUI7.py # use pywinauto to start Wireshark
# Visual Studio Code is Run as Administrator
import os
import sys
import pywinauto
from pywinauto.application import Application
# which PyQt5 is needed to be imported?
#from PyQt5 import QtCore, QtWidgets
#from PyQt5.QtGui import *
#from PyQt5.QtWidgets import QAbstractSlider
def process_GUI(pname, fname):
# start Wireshark -- it uses Qt5, ergo backend = uia
app = Application(backend="uia").start(r"C:\\Program Files\\Wireshark\\Wireshark.exe ")
if app.SoftwareUpdate.exists(timeout=5):
app.SoftwareUpdate.SkipThisVersion.click()
app.SoftwareUpdate.Wait_Not('visible') #make sure it is closed
##app['The Wireshark Network Analyzer'].print_control_identifiers()
# open any pcapng file
win = app["The Wireshark Network Analyzer"]
win.wait('ready', timeout=5)
win.type_keys('%F{ENTER}') # Alt+F, Enter (it calls "&File->&Open" menu)
app.Dialog2.FilenameEdit.set_edit_text(pname + fname)
app.Dialog2.Open4.click()
win = app[fname]
win.wait('ready', timeout=5)
##win.print_control_identifiers()
# get the Packet list window
PL = win["Packet list"] # it is a TreeView object
# how do I get the POINT in middle of Down arrow of vScroll on PL?
# = = = = = = =
if __name__ == '__main__':
# use path/file of any pcapng that has been saved
path_name = "C:\\H_Paul\\ws\\"
file_name = "ws-aug22a_SOsample.pcapng"
guiReturn = process_GUI(path_name, file_name)
sys.exit(0)
If your goal is to scroll down Packet List, you can use
# workaround for set_focus() failure on uia backend
app_win32 = Application(backend="win32").connect(path=r"wireshark.exe")
app_win32.window(best_match='Qt5QWindowIcon').set_focus()
PL.wheel_mouse_input(wheel_dist=-10) # negative wheel_dist means scroll down
or try PL.type_keys('{VK_DOWN}') to scroll Packet List.
The value of IsScrollPatternAvailable property of Packet List (QTreeView widget) is false, for this reason PL.scroll("down", "line", 1) cause error message "tree "Packet list" is not scrollable". Also inspect.exe doesn't show scrollbar among PacketList's children.
Also, you can try another approach: get bottom right coordinates of the Packet List, subtract (5,5) or other delta from them and click to this point. Something like (this code just demonstrates idea, because sends click to wrong coordinates on latest Wireshark version, which may be a Qt-related problem):
arrow_coords = (PL.rectangle().right - 5, PL.rectangle().bottom - 5)
for i in range(N):
PL.click_input(coords=arrow_coords)
I want to create a progress bar (GUI) in python. I am not sure how to do this in graphical version
I want it to print status in the output box too.
I am using progressbar2 right now
So here is my code:
import time
import progressbar
for i in progressbar.progressbar(range(100)):
time.sleep(0.02)
Here is a small example for you to add progress bar in gui with status
from tkinter import *
from tkinter.ttk import *
import time
root=Tk()
root.title("hi")
root.geometry("600x400")
a=IntVar()
prog=Progressbar(root,orient=HORIZONTAL,length= 300,mode = 'determinate' )
def step():
for x in range(5):
prog['value']+=20
a.set(prog['value'])
root.update_idletasks()
time.sleep(1)
prog.pack(pady=20)
butn=Button(root,text='Progress',command=step).pack(pady=20)
lb=Entry(root,textvar=a).pack(pady=20)
root.mainloop()
It think it may help you
I'm mainly working in Spyder, building scripts that required a pop-up folder or file Browse window.
The code below works perfect in spyder.
In Pycharm, the askopenfilename working well, while askdirectory do nothing (stuck).
But, if running in debug mode - the script works well.
I tried to run the script from SAS jsl - same issue.
Any Idea what should I do?
Python 3.6
Pycharm 2017.2
Thanks.
The Code I'm using includes:
import clr #pythonnet 2.3.0
import os
import tkinter as tk
from tkinter.filedialog import (askdirectory,askopenfilename)
root = tk.Tk()
root.withdraw()
PPath=askdirectory(title="Please select your installation folder location", initialdir=r"C:\Program Files\\")
t="Please select jdk file"
if os.path.exists(os.path.expanduser('~\Documents')):
FFile = askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t, initialdir=os.path.expanduser('~\Documents'))
else:
FFile= askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t)
sys.path.append(marsDllPath)
a = clr.AddReference('MatlabFunctions')
aObj = a.CreateInstance('Example.MatlabFunctions.MatLabFunctions')
edit: seems like issue related to the pythonnet "imoprt clr", but I do need it in the code.
Similar question asked here: https://github.com/pythonnet/pythonnet/issues/648
Your problem is rather mediocre, although not so obvious. The problem is not in tinker or pythonnet, it stems from the COM threading model.
To begin with, since you're using the clr, let's try to use dialogs directly with it (it's not absolutely necessary to import the tinker module):
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
# clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# creating instances of dialogs
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
# try to show any of them
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
As you can see, it hangs just like in your case. The reason, as was mentioned above, stems from the threading's apartment state([1], [2]).
Therefore the clr implicilty sets this state to MTA (Multi-threaded apartment), which can be tested via CoGetApartmentType function:
# importing ctypes stuff
import ctypes
get_apartment = ctypes.windll.ole32.CoGetApartmentType
# comment/uncomment this import to see the difference
# import clr
apt_type = ctypes.c_uint(0)
apt_qualifier = ctypes.c_uint(0)
if get_apartment(ctypes.byref(apt_type), ctypes.byref(apt_qualifier)) == 0:
# APPTYPE enum: https://msdn.microsoft.com/en-us/library/windows/desktop/ms693793(v=vs.85).aspx
# APTTYPEQUALIFIER enum: https://msdn.microsoft.com/en-us/library/windows/desktop/dd542638(v=vs.85).aspx
print('APTTYPE = %d\tAPTTYPEQUALIFIER = %d' % (apt_type.value, apt_qualifier.value))
else:
print('COM model not initialized!')
However, many older COM objects, such as shell dialogs, require STA mode.
Good explanation about the difference between those two states can be found here or there.
Finally, the solutions:
1) Use STA thread for dialogs:
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
#clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# adding reference (if necessary) to Threading and importing Thread functionality
#clr.AddReference('System.Threading')
from System.Threading import Thread, ThreadStart, ApartmentState
# WinForms thread function example
def dialog_thread():
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
# Tk thread function example
def tk_dialog_thread():
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
# check again apartment state at start
current_state = Thread.CurrentThread.GetApartmentState()
if current_state == ApartmentState.STA:
print('Current state: STA')
elif current_state == ApartmentState.MTA:
print('Current state: MTA')
# start dialogs via CLR
thread = Thread(ThreadStart(dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
# start dialogs via Tkinter
thread = Thread(ThreadStart(tk_dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
2) Force STA mode via CoInitialize/CoInitializeEx before CLR does so for MTA:
# importing ctypes stuff
import ctypes
co_initialize = ctypes.windll.ole32.CoInitialize
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# Force STA mode
co_initialize(None)
# importing pythonnet
import clr
# dialogs test
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
I have tested the code which you pasted on Pycharm 2018.1.3 with python-3.6.5 installed on win-7 64 bit machine. It works fine without any error. There are few bugs in 2017 version. Try upgrading to latest version of Pycharm
I have located this useful code for Tkinter animations from https://www.daniweb.com/programming/software-development/threads/396918/how-to-use-animated-gifs-with-tkinter ,supplied by "vegaseat".
I have adapted a similar design for displaying gifs animations to a project. I am wishing to implement this as a function to certain areas of a script, e.g. importing modules etc. I have tried a few approaches but when I called this as a function, it first runs the animation and then imports the module (as we would expect).
I guess I am exploring ways to get this to work concurrently...while the script is importing modules( or running another process where I wish to display the animation), the animation would be displayed, and then disappear, until the next call. Suggestions would be appreciated.
Thanks a lot.
# mimic an animated GIF displaying a series of GIFs
# an animated GIF was used to create the series of GIFs
# with a common GIF animator utility
import time
from Tkinter import *
root = Tk()
imagelist = ["dog001.gif","dog002.gif","dog003.gif",
"dog004.gif","dog005.gif","dog006.gif","dog007.gif"]
# extract width and height info
photo = PhotoImage(file=imagelist[0])
width = photo.width()
height = photo.height()
canvas = Canvas(width=width, height=height)
canvas.pack()
# create a list of image objects
giflist = []
for imagefile in imagelist:
photo = PhotoImage(file=imagefile)
giflist.append(photo)
# loop through the gif image objects for a while
for k in range(0, 1000):
for gif in giflist:
canvas.delete(ALL)
canvas.create_image(width/2.0, height/2.0, image=gif)
canvas.update()
time.sleep(0.1)
root.mainloop()
EDIT: I am attempting to implement the code,below, per some helpful suggestions. The goal is to begin the animation, while the application is importing the modules in the "IMPORTS" function, and then have it destroyed after the imports are completed.
# Import modules
from Tkinter import *
from PIL import ImageTk
from PIL import Image
import os,time
from os.path import dirname
from os.path import join
def IMPORTS():
import tkMessageBox
from ttk import Combobox
import csv,datetime
import xlrd,xlwt
import getpass
import traceback
import arcpy
from arcpy import AddMessage
import win32com.client
inGif = #root image (.gif)
FramesFolder = #Folder containing frames of the root image
W=Toplevel()
W.wm_overrideredirect(True) # I wish to only display the widget spinning without the window frame
imagelist = [os.path.join(FramesFolder,s) for s in os.listdir(FramesFolder) if not s.endswith('db')]
# extract width and height info
photo = PhotoImage(file=imagelist[0])
width = photo.width()
height = photo.height()
canvas = Canvas(W,width=width, height=height)
canvas.pack()
# create a list of image objects
giflist = []
for imagefile in imagelist:
photo = PhotoImage(file=imagefile)
giflist.append(photo)
timer_id = None
def start_loading(n=0):
global timer_id
gif = giflist[n%len(giflist)]
canvas.create_image(gif.width()//2, gif.height()//2, image=gif)
timer_id = W.after(100, start_loading, n+1) # call this function every 100ms
def stop_loading():
if timer_id:
W.after_cancel(timer_id)
canvas.delete(ALL)
start_loading()
IMPORTS()
stop_loading()
# The spinning widget should be completely destroyed before moving on...
It is returning
"NameError: name 'tkMessageBox' is not defined"
You can use Tk.after() and Tk.after_cancel() to start and stop the animation:
timer_id = None
def start_loading(n=0):
global timer_id
gif = giflist[n%len(giflist)]
canvas.create_image(gif.width()//2, gif.height()//2, image=gif)
timer_id = root.after(100, start_loading, n+1) # call this function every 100ms
def stop_loading():
if timer_id:
root.after_cancel(timer_id)
canvas.delete(ALL)
Then, you can call start_loading() before the long process and call stop_loading() after the long process:
start_loading()
long_process() # your long process
stop_loading()