serial output not display in tkinter label - python

from cgitb import text
from distutils.cmd import Command
import tkinter as tk
from socket import timeout
import time
import pyfirmata
import time
from time import sleep, strftime
from tkinter import Tk, Label
from tkinter import Tk, Label
import random
import os
import tkinter.font as tkFont
ports="COM4"
board = pyfirmata.Arduino('COM4')
analog_pin0 = board.get_pin('a:1:i')
x=0
it = pyfirmata.util.Iterator(board)
it.start()
pin=4
analog_pin0.enable_reporting()
board.digital[7].write(0)
voltage0 = ""
def main():
print("this is maoin")
def on():
global voltage0
root = tk.Tk()
root.geometry("600x500")
w = tk.Label(root, text="Hello, world!")
w.pack(pady=20)
# B = tk.Button(root, text ="Hello", command = main)
# B.pack()
w.config(text=voltage0)
w['text'] = "intial voltage"
B = tk.Button(root, text ="Hello", command = main)
B.pack()
root.mainloop()
def main ():
while True:
global voltage0
reading0 = analog_pin0.read()
if reading0 != None:
voltage0 = reading0 * 22.3
voltage0 = round(voltage0,2)
time.sleep(0.1)
print(voltage0)
w.config(text=voltage0)
w['text'] = voltage0
else:
voltage0 = float('nan')
string = strftime('%H:%M:%S %p')
if (voltage0>7.3):
time.sleep(0.1)
board.digital[pin].write(1)
board.digital[6].write(0)
if(voltage0<6.5):
time.sleep(0.1)
board.digital[pin].write(0)
board.digital[6].write(1)
if (voltage0==7.3):
print()
print(voltage0)
print(string)
w.config(text=voltage0)
w['text'] = voltage0
if (voltage0==6.5):
print()
print(voltage0)
print(string)
w.config(text=voltage0)
w['text'] = voltage0
main()
on()

Related

How return result of a function with tkinter messagebox

I am trying to write code that will return either head or tails and show it in a separate window (message box). How can I show the result of my function in a separate window (message box)?
import tkinter
import numpy as np
from tkinter import messagebox
result = []
def hola():
coin = np.random.randint(0,2)
if coin == 0:
result.append("heads")
else:
result.append("tails")
messagebox.showinfo( "Lucky you !", result )
top = tkinter.Tk()
B = tkinter.Button(top, text ="flip da coin", command = hola)
B.pack()
top.mainloop()
I think you want to do something like this;
import tkinter
import numpy as np
from tkinter import messagebox
def hola():
coin = np.random.randint(0,2)
if coin == 0:
result = "heads"
else:
result = "tails"
messagebox.showinfo( "Lucky you !", result )
top = tkinter.Tk()
B = tkinter.Button(top, text ="flip da coin", command = hola)
B.pack()
top.mainloop()

Tkinter: Updating GUI from subprocess output in realtime

I've searched the whole internet to answer my problem, but nobody seems to have the same one: I'm trying to update my tkinter GUI dynamically from a subprocess output, which works fine, if I'm starting my GUI inside eclipse. BUT if I'm running it in the file explorer or in visual studio, the 'stdout.readline' command waits, until the subprocess is finished. Only then the complete output is printed to my textarea... I am working with a thread and I've tried 2 ways: one is shown in 'App.py', the other one is threading the 'read_update' method instead (and not using 'reader_thread' and 'update' methods).
Interesting sidenote: the sys.argv command in Test.py does not return my string "var_test". Can anyone tell me why?
My Classes are:
GUI.py
import Tkinter as tk
from App import App
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
root.protocol("WM_DELETE_WINDOW", app.quit)
root.mainloop()
App.py
#App.py
import Tkinter as tk
import tkFont as tkfont
import subprocess
from subprocess import Popen
from subprocess import PIPE
from itertools import islice
from threading import Thread
from ttk import Scrollbar
from Tkinter import *
from Queue import Queue, Empty
class App():
def __init__(self, root):
self.root = root
self.root.title_font = tkfont.Font(family = "Helvetica", size = 18, weight = "bold", slant = "italic")
Grid.columnconfigure(self.root, 5, weight = 1)
button_ok = tk.Button(self.root, text = "OK", width = 10, command = lambda: self.on_okay())
button_ok.grid(row = 7, column = 0, padx = (20,0), pady = 10, sticky = W)
xscrollbar = Scrollbar(self.root, orient=HORIZONTAL)
xscrollbar.grid(row=8, column=1, columnspan=4, sticky=E + W)
yscrollbar = Scrollbar(self.root, orient=VERTICAL)
yscrollbar.grid(row=8, column=5, sticky=N + S)
self.textarea = Text(self.root, wrap=NONE, bd=0,
xscrollcommand=xscrollbar.set,
yscrollcommand=yscrollbar.set)
self.textarea.grid(row=8, column=1, columnspan=4, rowspan=1,
padx=0, sticky=E + W + S + N)
def on_okay(self):
self.textarea.delete("1.0", END)
exec_path = r"\Test.py" #insert location of Test.py
self.process = subprocess.Popen([exec_path, 'var_test'], shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
self.q = Queue(maxsize = 1024)
t = Thread(target=self.reader_thread, args=[self.q])
t.daemon = True
t.start()
self.update(self.q)
def reader_thread(self, q):
try:
with self.process.stdout as pipe:
for line in iter(pipe.readline, b''):
q.put(line)
finally:
q.put(None)
def update(self, q):
for line in self.iter_except(q.get_nowait, Empty):
if line is None:
#self.quit()
return
else:
self.textarea.insert(INSERT, line)
self.textarea.yview(END)
break
self.root.after(40, self.update, q)
def iter_except(self, function, exception):
try:
while True:
yield function()
except exception:
return
def read_update(self):
while True:
line = self.process.stdout.readline()
if line == "" and self.process.poll() != None:
break
elif line == "":
pass
else:
self.textarea.insert(INSERT, line)
self.textarea.yview(END)
self.textarea.update_idletasks()
def quit(self):
try:
self.process.kill()
except AttributeError:
pass
finally:
self.root.destroy()
Test.py
import sys
from time import sleep
var = sys.argv
print var
for i in range(1, 10):
print i
print "finished printing numbers"
sleep(10)
print "finished"
Thank you for your help! I'm pretty desperate 'cause I've been trying to solve this problems for many hours now...
use sys.stdout.flush() after print

How kill or destroy the either root window or child window

import tkinter as tk
from tkinter import messagebox
import xlrd as rd
class Example():
def __init__(self,master):
self.frameExample =tk.Frame(master,width =600,height = 200)
self.frameExample.pack()
self.loadButton = tk.Button(self.frameExample,text = "Load",command =self.loadFile)
self.loadButton.pack()
def loadFile(self):
sheetWindow = tk.Toplevel()
sheetFrame = tk.Frame(sheetWindow, width = 600,height = 400,bg = "alice blue")
sheetFrame.pack()
try:
print("entered")
self.workbook = rd.open_workbook("tiger.jpg")
except:
print("entered 1")
messagebox.showinfo(title = "Load error",message = "Error")
self.master.destroy()
root = tk.Tk()
Example(root)
root.mainloop()
I have tried self.masterdestroy(), not sure how to kill main window
Just add self.master = master to your __init__ method and then your code should work.

Print letter by letter using Tkinter

Is there a way to print letter by letter (redraw between frame update) in Python 3.4.1 using Tkinter?
This is doable in the normal IDLE window using this piece of code:
import time
string = "hello world"
for char in string:
print(char, end='')
time.sleep(.25)
But I can't do this in GUI Tkinter window. In my opinion, I could display a label on to the tkinter window, add a letter from a string into it, and wait for a period of time before adding another letter (about 0.25 secs), with the same idea as the code above.
Any solutions?
For example:
String To Display = 'abc'
First frame : 'a'
Second frame : 'ab'
Third Frame : 'abc'
Thanks in advance!
You didn't specify much so I just guessed you'd like something like this:
import time
import tkinter as tk
def printString(string):
for char in string:
Label.configure(text=Label.cget('text') + char)
Label.update()
time.sleep(.25)
root = tk.Tk()
text = "Hello world!"
Label = tk.Label(root)
Label.pack()
printString(text)
root.mainloop()
UPDATE:
Same principle but for a canvas:
import time
import tkinter as tk
def printString(item, string):
if item:
for char in string:
idx = c.index(item, tk.END)
c.insert(item, idx, char)
c.update()
time.sleep(.25)
root = tk.Tk()
text = "Hello world!"
c = tk.Canvas(root)
c_txt = c.create_text(50,50)
c.pack()
c.update()
printString(c_txt, text)
root.mainloop()
You can do this using after to call a method periodically to update the GUI. time.sleep is not as easy to work with as it blocks main-thread which the GUI runs on.
You could periodically replace the label's single character text with next letter in the string:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letter():
global label
label['text'] = label.string[label.current_char_index]
label.current_char_index += 1
label.current_char_index %= len(label.string)
label.after(250, update_label_letter)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root)
label.string = "Hello World!"
label.current_char_index = 0
root.after(250, update_label_letter)
label.pack()
root.mainloop()
One way would be to periodically append the letters of a single label.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global label
_no_of_space_replacements = label['text'].count('\n')
_last_char_index = len(label['text']) - _no_of_space_replacements
if _last_char_index < len(label.string):
label['text'] += label.string[_last_char_index].replace(" ", " \n")
else:
label['text'] = ""
label.after(250, update_label_letters)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, wraplength=1)
label.string = "Hello World!"
root.after(250, update_label_letters)
label.pack()
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global label
_last_char_index = len(label['text'])
if _last_char_index < len(label.string):
label['text'] += label.string[_last_char_index]
else:
label['text'] = ""
label.after(250, update_label_letters)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root)
label.string = "Hello World!"
root.after(250, update_label_letters)
label.pack()
root.mainloop()
Another way would be to write the letters periodically to empty but shown letter_labels.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
_current_char = my_string[current_char_index]
letter_labels[current_char_index]['text'] = _current_char
letter_labels[current_char_index].after(250, update_label_letters)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for index, value in enumerate(my_string):
letter_labels.append(tk.Label(root))
letter_labels[index].pack()
current_char_index = 0
root.after(250, update_label_letters)
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
_current_char = my_string[current_char_index]
letter_labels[current_char_index]['text'] = _current_char
letter_labels[current_char_index].after(250, update_label_letters)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for index, value in enumerate(my_string):
letter_labels.append(tk.Label(root))
letter_labels[index].pack(side='left')
current_char_index = 0
root.after(250, update_label_letters)
root.mainloop()
Another way would be to display the letter_labels periodically.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def show_label():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
letter_labels[current_char_index].pack()
letter_labels[current_char_index].after(250, show_label)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for _char in my_string:
letter_labels.append(tk.Label(root, text=_char))
current_char_index = 0
root.after(250, show_label)
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def show_label():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
letter_labels[current_char_index].pack(side='left')
letter_labels[current_char_index].after(250, show_label)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for _char in my_string:
letter_labels.append(tk.Label(root, text=_char))
current_char_index = 0
root.after(250, show_label)
root.mainloop()

Trouble with combining threading and progressbar with a function

I have some code which asks the user to import a file and then it will be encrypted using a translator. When I try this the program hangs a lot with large files or any files in general. I've tried to solve this using threading and a progressbar but I've sort of hit a dead end - I don't know how to update the progressbar which will correspond with the amount of time it will take to encrypt the file. This is what I have so far:
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from tkinter.filedialog import askopenfile
from tkinter.filedialog import askopenfilename
from tkinter.scrolledtext import *
import threading
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
encryption_code = 'LFWOAYUISVZMNXPBDCRJTQEGHK'
letters += letters.lower()
encryption_code += encryption_code.lower()
enc = dict(zip(letters,encryption_code))
window = tkinter.Tk()
style = ttk.Style(window)
style.configure("BW.TLabel")
import_frame = tkinter.Frame(window)
def import_txt():
global import_list
file_name = askopenfilename(filetypes=[("Text files","*.txt")])
import_list = []
with open(file_name, 'r') as f:
import_list = f.readlines()
progressbar.pack()
but1.pack()
encrypttxt.pack()
f.close()
def encrypt_txt():
global letters
global encryption_code
global import_list
global translated
progressbar.start()
pre = "".join(import_list)
translated = "".join([i.translate(str.maketrans(letters, encryption_code)) for i in import_list])
display_txt.insert('insert', translated)
precrypt.insert('insert', pre)
display_txt.pack(side=RIGHT)
precrypt.pack(side=LEFT)
def end():
if t.isAlive() == False:
progressbar.stop()
t.join()
toplevel = tkinter.Toplevel(window)
progressbar = ttk.Progressbar(toplevel, orient = HORIZONTAL, mode = "determinate")
t = threading.Thread(target=encrypt_txt)
but1 = ttk.Button(window, text= "Stop", command=end)
display_txt = tkinter.scrolledtext.ScrolledText(import_frame)
encrypttxt = ttk.Button(import_frame, text="Encrypt", command=encrypt_txt)
precrypt = tkinter.scrolledtext.ScrolledText(import_frame)
start = ttk.Button(window, text="Start", command=import_txt)
start.pack()
import_frame.pack()
window.mainloop()

Categories

Resources