I want to know, how to pop-up messages while processing/executing a program/function. I mean,
def Select():
path=tkFileDialog.askopenfilename(filetypes=[("Image File",'.jpg')])
im = skimage.io.imread(path, as_grey=True)
im = skimage.img_as_ubyte(im)
im /= 32
g = skimage.feature.greycomatrix(im, [1], [0], levels=8, symmetric=False, normed=True)
cont = skimage.feature.greycoprops(g, 'contrast')[0][0]
cont_list1.append(cont)
ene = skimage.feature.greycoprops(g, 'energy')[0][0]
ene_list1.append(ene)
homo = skimage.feature.greycoprops(g, 'homogeneity')[0][0]
homo_list1.append(homo)
cor = skimage.feature.greycoprops(g, 'correlation')[0][0]
cor_list1.append(cor)
dis = skimage.feature.greycoprops(g, 'dissimilarity')[0][0]
dis_list1.append(dis)
I want to display a message stating Features are being calculated, and once it calculates, the message should disappear.
But I don't need the ok button.I don't know how to achieve this.The result of these calculations will be displayed in separate Entry box. Any suggestions are welcome.
Have a look at this. It opens a window with the text and when the computation is done the text is changed to the result.
>>> import time
>>> def processingPleaseWait(text, function):
import Tkinter, time, threading
window = Tkinter.Toplevel() # or tkinter.Tk()
# code before computation starts
label = Tkinter.Label(window, text = text)
label.pack()
done = []
def call():
result = function()
done.append(result)
thread = threading.Thread(target = call)
thread.start() # start parallel computation
while thread.is_alive():
# code while computing
window.update()
time.sleep(0.001)
# code when computation is done
label['text'] = str(done)
>>> processingPleaseWait('waiting 2 seconds...', lambda: time.sleep(2))
Related
I have designed an marine engine simulator - it's a program that sends some serial DATA using a certain protocol called "BlueVision". The data is encoded based on a header, a block number, a block type, actual data (indexed), a checksum and a footer. Due to the fact that if you want to change a value in the actual data - then the checksum changes - I designed an recalculation of the block with the correct checksum when the data is changed. I made a GUI that allows me to change the value of 2 data points in order to be able to test live. The problem is that I don't know how to use threads or subprocesses correctly and the window keeps on freezing. The application works - but works badly and I kept on searching for a similar issue - and did find some suggestions but I haven't been able to implement it. Can someone help? PS: the code is awkward at best - please don't judge - I know I could of made it way better - but this is the best I could do with the time I had. The issue might not be clear to you if you don't have a COM port where the program writes to.
# Blue Vision is a MTU serial communication protocol - based on HEX values grouped in BLOCKS
import tkinter as tk
from tkinter import ttk
import time
import serial
def split_by_n(seq, n):
while seq:
yield seq[:n]
seq= seq[n:]
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""
win = tk.Tk()
win.title("GUI - TEST VERSION")
win.geometry("750x250")
label = tk.Label(win, text = "Main Engine Overspeed")
label.pack()
v = tk.StringVar()
v.set('00')
c = tk.StringVar()
c.set("00")
def setText(word):
v.set(word)
a = ttk.Button(win, text ="01", command =lambda:setText("01"))
a.pack()
b = ttk.Button(win, text="00", command = lambda:setText("00"))
b.pack()
label1 = tk.Label(win, text ="Main Engine Speed")
label1.pack()
name_entry = tk.Entry(win, textvariable=c)
name_entry.pack()
def task():
MyVar = v.get()
priEngSp =c.get()
if len(priEngSp) == 0:
priEngSp = '00'
block_3 = 'FAF500030002000000290100000001000100000001000001000000000000000000000000000222AF5F'
block_4 = 'FAF500040003000001A000004650000047E00000000000000000000000000007EF4000083D6000000000000000000000000000000000000000000000012C000006D600000000000000000000278D00000000000000007FFFFFFF000000000001991500000000000000000016E36000000000000923D8000971F8000001F40000059F000026AC00002774000005800000251C00000580000027740000283C0000056200001D4C00001F400000061800000000000060FB00004650000036B000007D0000008CA0000006180000251C0000000000000000000000000000284800192D500017A6B00000051B0000251CFFFFFFA8000002580000044C000000FA0000000000000000000006770000CB200000D6D8000006770000CB200000D6D80000060600005DC000000000000027100000000000000000000000000000000000000000000003C2000061A8000000000000000000000000000000000000000000000000000000000000000000000000000000000000363300000EA6000249F0FFFFFB1E000F42400000000000000000000000000000000000000000000032D9AF5F'
block_5 = 'FAF5000500020000005600000000000000000000000000000000000000000000007F7F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034AAF5F'
block_6 = 'FAF5000600020000003D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000234AF5F'
block_7 = 'FAF5000700030000008C000006280000064A0000064A0000068D0000066B0000068D0000068D000006AE0000000000000000000006AE000006070000060700000607000005E5000005A2000006070000064A00000000000000000000062A000006AE000005A20000350EFFFFF07C00003CDEFFFFE8AC00000000000000000000000000000000000012DEAF5F'
block_8 = 'FAF50008000300000070000000000000112900000000000000000000059C000027740000283C000047E000000000000000000000000000000000000000000000000000000000000000007FFFFFFF7FFFFFFF0000055100002CEC0000000000000000000000000000000000000DD1AF5F'
block_9 = 'FAF50009000200000020000000000000000000000000000000000000021AAF5F'
block_10 = 'FAF5000A0002000000260000000000000000000000000000000000000000000000000221AF5F'
block_11 = 'FAF5000B0003000000EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E9AF5F'
block_12 = 'FAF5000C000200000045000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000242AF5F'
block_2 = 'FAF50002000200000074010001000000000000000000000000000000000000000000007F0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E9AF5F'
checksum = hex(0x00)
block_2split = list(split_by_n(block_2,2))
block_2split[10] = MyVar.upper() #Overspeed Alarm Position
for i in range(len(block_2split)-6):
checksum = hex(int(checksum, 16) + int(block_2split[i], 16))
checksum_string = str(checksum)
checksum_actvalue = checksum_string[2:]
checksum_long = checksum_actvalue.rjust(8,'0').upper()
checksum_split = list(split_by_n(checksum_long,2))
block_2split[len(block_2split)-3] = checksum_split[3]
block_2split[len(block_2split)-4] = checksum_split[2]
block_2split[len(block_2split)-5] = checksum_split[1]
block_2split[len(block_2split)-6] = checksum_split[0]
Block_2Output = ''.join(str(item) for item in block_2split)
iEngineSpeed = int(priEngSp,10)
hEngineSpeed = hex(iEngineSpeed * 10)
sEngineSpeed = str(hEngineSpeed)[2:].upper()
while (len(sEngineSpeed)<8):
sEngineSpeed = '0' + sEngineSpeed
block_4split = list(split_by_n(block_4,4))
sEngineSpeed_split = list(split_by_n(sEngineSpeed,4))
block_4split[5] = sEngineSpeed_split[0]
block_4split[6] = sEngineSpeed_split[1]
Block_4joint = ''.join(str(item) for item in block_4split)
Block_4joint_sp = list(split_by_n(Block_4joint,2))
checksumb4 = hex(0x00)
for i in range(len(Block_4joint_sp)-6):
checksumb4 = hex(int(checksumb4, 16) + int(Block_4joint_sp[i], 16))
checksumb4_string = str(checksumb4)
checksumb4_actvalue = checksumb4_string[2:]
checksumb4_long = checksumb4_actvalue.rjust(8,'0').upper()
checksumb4_split = list(split_by_n(checksumb4_long,2))
Block_4joint_sp[len(Block_4joint_sp)-3] = checksumb4_split[3]
Block_4joint_sp[len(Block_4joint_sp)-4] = checksumb4_split[2]
Block_4joint_sp[len(Block_4joint_sp)-5] = checksumb4_split[1]
Block_4joint_sp[len(Block_4joint_sp)-6] = checksumb4_split[0]
Block_4Output = ''.join(str(item) for item in Block_4joint_sp)
blocks = [Block_2Output, block_3, Block_4Output, block_5, block_6, block_7, block_8, block_9, block_10, block_11, block_12]
with serial.Serial('COM5', '9600') as ser: #you might wanna comment this part out
for block in blocks:
print(block)
ser.write(bytes.fromhex(block.strip())) #you might wanna comment this part out
time.sleep(1)
win.after(200, task)
win.after(200, task)
win.mainloop()
To avoid freezing, one of the way is to use thread:
from threading import Thread
...
def task():
while True:
MyVar = v.get()
...
blocks = [Block_2Output, block_3, Block_4Output, block_5, block_6, block_7, block_8, block_9, block_10, block_11, block_12]
with serial.Serial('COM5', '9600') as ser: #you might wanna comment this part out
for block in blocks:
print(block)
ser.write(bytes.fromhex(block.strip())) #you might wanna comment this part out
time.sleep(1)
time.sleep(0.2)
# run task() in a thread
Thread(target=task, daemon=1).start()
win.mainloop()
I want to make a kind of chat box, and I would like the letters to be word by word, I did that function but it stays loading until the loop ends, and it gives me the final result, i see in other pages and questions, and i saw that the "after" funtion works, maybe i did something wrong when implementing it, sorry for my english
import tkinter as tk
from tkinter import ttk
import os
from PIL import ImageTk
import PIL.Image
# parent window where is an image of the chatbox
def Ventana_Text_Box(event):
#Ventana De Text box
global ventana_BT
ventana_BT = tk.Tk()
ventana_BT.geometry("300x300+"+str(200)+"+"+str(100))
ventana_BT.configure(background="gray")
I_Text_Box_Image = ImageTk.PhotoImage(I_Text_Box)
Box_Texto = tk.Label(ventana_BT, image = I_Text_Box_Image, bg="gray")
Box_Texto.pack()
Box_Texto.bind("<Button-1>", Ventana_Texto)
Box_Texto.bind("<Button-3>", escribir_texto)
#ventana_BT.wm_attributes("-topmost", 1)
ventana_BT.wm_attributes("-transparentcolor", "gray")
ventana_BT.overrideredirect(1)
ventana_BT.mainloop()
# window where the text will be
def Ventana_Texto(event):
# Ventana hija para el texto
global ventana_T
global W_texto
ventana_T = tk.Toplevel()
ventana_T.geometry("300x300+"+str(ventana_BT.winfo_rootx()-70)+"+"+str(ventana_BT.winfo_rooty()+140))
ventana_T.configure(background="gray")
W_texto = tk.Label(ventana_T, text="", bg="pink")
W_texto.config(fg="black", font=("Consola", 15))
W_texto.pack()
#escribir_texto("Hola")
#ventana_T.wm_attributes("-topmost", 1)
ventana_T.wm_attributes("-transparentcolor", "gray")
ventana_T.overrideredirect(1)
ventana_T.mainloop()
# Function that changes the text from letter to letter
def mecanografiar(texto):
for i in range(len(texto)+1):
return W_texto.config(text=texto[0:i])
# test function to see if it works write "HOLA"
def escribir_texto(event):
texto = "hola"
W_texto.after(400, mecanografiar(texto))
scriptpath = os.path.abspath(__file__)
scriptdir = os.path.dirname(scriptpath)
Text_Box = os.path.join(scriptdir, "Dialogo", "text_box.png")
#800x712
I_Text_Box = PIL.Image.open(Text_Box)
W_I = 350
H_I = W_I*712/800
I_Text_Box = I_Text_Box.resize((W_I,int(H_I)), PIL.Image.ANTIALIAS)
if __name__ == "__main__":
Ventana_Text_Box(None)
import tkinter as tk
root = tk.Tk()
root.geometry('200x200')
# this is whatever string you want to type out slowly
chat_str = 'Hello, friend!'
# storing text in a StringVar will update the label automatically
# whenever the value of the variable is changed (see 'textvariable' below)
text_var = tk.StringVar()
label = tk.Label(textvariable=text_var)
label.pack()
# index represents the character index in 'chat_str'
index = 0
# we need an empty string to store the typed out string as it updates
placeholder = ''
def type_text():
# use 'global' to allow the function to access these variables
global index
global placeholder
try:
# concat the placeholder with the next character in 'chat_str'
placeholder += chat_str[index]
# set 'text_var' to update the label automatically
text_var.set(placeholder)
# go to the next index (character) in 'chat_str'
index += 1
# call this function again after 150mS
# (change this number to modify the typing speed)
root.after(150, type_text)
except IndexError: # when you run out of characters...
return # bail
# NOTE:
# using a 'try:except' block above avoids issues stopping 'root.after()'
type_text()
root.mainloop()
i have less than 3 months of python programming under my belt but basically, i have a program that pulls values from the CoinGecko API indefinitely and creates processes so the functions that pull the data can run independently from one another, but id like for it to break its loop after i press the specified hotkey which is set to 'q'. whenever i press the hotkey, nothing happens and the loop just keeps running. i've tried using the keyboard.read_key() function, but that just stops my program from running until i press the q button, which causes the program to run the loop once and then close. i have no idea why the is_pressed() function refuses to work and id like some help from more advanced people
Piece of Code in question:
from multiprocessing.dummy import freeze_support
from pycoingecko import CoinGeckoAPI
import time
from multiprocessing import Process
from multiprocessing import Pool
import multiprocessing
import keyboard as kb
import psutil
cg = CoinGeckoAPI()
class CGCoin:
def __init__(self, coinname, coinid):
self.coinname = coinname
self.coinid = coinid
def pulldata(self):
while True:
wishtoquit = False
if kb.is_pressed('Q'):
print('ending after this loop')
wishtoquit = True
timestarted = time.asctime()
self.prices = []
self.daychanges = []
self.volumes = []
self.marketcaps = []
self.weekchanges = []
self.highs = []
self.lows = []
self.times = []
print(f'starting {self.coinname} reading at {timestarted}')
loops = 0
maxloops = 2
while loops < maxloops:
time.sleep(15)
coin = cg.get_coin_by_id(f'{self.coinid}')
time.sleep(5)
coinvalues = coin.get('market_data')
coinprices = coinvalues.get('current_price')
coinvolumes = coinvalues.get('total_volume')
mrktcaps = coinvalues.get('market_cap')
dayhigh = coinvalues.get('high_24h')
daylow = coinvalues.get('low_24h')
daychangepercentage = coinvalues.get('price_change_percentage_24h')
weekchangepercentage = coinvalues.get('price_change_percentage_7d')
coinprice = coinprices.get('usd')
coinvolume = coinvolumes.get('usd')
coincap = mrktcaps.get('usd')
coindayhigh = dayhigh.get('usd')
coindaylow = daylow.get('usd')
timepulled = time.asctime()
self.prices.append(coinprice)
self.daychanges.append(daychangepercentage)
self.volumes.append(coinvolume)
self.marketcaps.append(coincap)
self.weekchanges.append(weekchangepercentage)
self.highs.append(coindayhigh)
self.lows.append(coindaylow)
self.times.append(timepulled)
loops = loops + 1
print(loops)
timeended = time.asctime()
})
print(f'stopping {self.coinname} reading at {timeended}')
if wishtoquit:
print('ending loops')
break
time.sleep(5)
bitcoin = CGCoin('Bitcoin', 'bitcoin')
ethereum = CGCoin('Ethereum', 'ethereum')
if __name__ == '__main__':
freeze_support()
btcpul = Process(target=bitcoin.pulldata, name=bitcoin.coinname)
btcpul.start()
if anyone has any ideas or fully-functional workarounds id really like to hear them. id be extremely grateful for any help recieved
It looks like PyPi keyboard needs root permissions on linux.
You could just do kb.on_press_key("p", lambda _: sys.exit(0)) and just do a sys.exit(0) to end the script.
If you're running this in the terminal you should just be able to press ctrl+c to interrupt its execution.
ref: How to detect key presses?
I want an experiment that displays a bunch of random dots, then asks the user to input the correct number of dots they saw. I want the experiment to loop. I can get this to work for 1 iteration, but something is wrong with the looping because the window and the dialogue are colliding, or the window isn't properly closing. When running this script Psychopy currently, the gui freezes. I've tried both python3 and python2 with my code.
import random
import psychopy.visual
import psychopy.event
import psychopy.core
from psychopy import gui
import time
while True:
win = psychopy.visual.Window(
size=[500, 500],
units="pix",
fullscr=False
)
myDlg = gui.Dlg(title="Response")
n_dots = random.randint(5, 200)
dot_xys = []
for dot in range(n_dots):
dot_x = random.uniform(-250, 250)
dot_y = random.uniform(-250, 250)
dot_xys.append([dot_x, dot_y])
dot_stim = psychopy.visual.ElementArrayStim(
win=win,
units="pix",
nElements=n_dots,
elementTex=None,
elementMask="circle",
xys=dot_xys,
sizes=10,
contrs=random.random(),
)
dot_stim.draw()
win.flip()
psychopy.event.clearEvents()
time.sleep(4)
win.close()
myDlg.addField('How many dots did you see?')
number = myDlg.show()
if myDlg.OK:
print(number)
myDlg.close()
psychopy.core.quit()
I'm using the latest version of Psychopy. Please let me know if you have any suggestions. Thanks!
Generally, you would not use a dialogue box to collect responses. Rather, you'd make something that works inside the window using psychopy stimuli. Here's a solution:
# Tidy 1: just import from psychopy
import random
from psychopy import visual, event, core
# Tidy 2: create a window once. Don't close it.
win = visual.Window(
size=[500, 500],
units="pix",
fullscr=False
)
instruction_text = visual.TextStim(win, text = u'How many dots did you see?', pos=(0, 100))
answer_text = visual.TextStim(win)
# Solution: a function to collect written responses
def get_typed_answer():
answer_text.text = ''
while True:
key = event.waitKeys()[0]
# Add a new number
if key in '1234567890':
answer_text.text += key
# Delete last character, if there are any chars at all
elif key == 'backspace' and len(answer_text.text) > 0:
answer_text.text = answer_text.text[:-1]
# Stop collecting response and return it
elif key == 'return':
return(answer_text.text)
# Show current answer state
instruction_text.draw()
answer_text.draw()
win.flip()
while True:
# Prepare dot specifications
n_dots = random.randint(5, 200)
dot_xys = []
for dot in range(n_dots):
dot_x = random.uniform(-250, 250)
dot_y = random.uniform(-250, 250)
dot_xys.append([dot_x, dot_y])
# This is extremely ugly! You should generally never create a new stimulus,
# but rather update an existing one. However, ElementArrayStim currently
# does not support changing the number of elements on the go.
dot_stim = visual.ElementArrayStim(
win=win,
units="pix",
elementTex=None,
elementMask="circle",
sizes=10,
contrs=random.random(),
nElements = n_dots,
xys = dot_xys,
)
# Show it
dot_stim.draw()
win.flip()
core.wait(4)
# Collect response
print(get_typed_answer())
I am trying to display some data from /proc/stat file. Since this data constantly changes, I would like to update the values after every Interval (3 sec) on my screen. How do i achieve the same using poll() function?
Edit: I tried to achieve the same using threads and after. But I am not happy with the way it updates on my GUI. Below is my code for the same..
def displayTab1(self):
self.slabel1=ttk.Label(self.page1,text=" User Mode : ")
self.slabel1.grid(row=1,column=1,sticky=E,pady=15,padx=5)
self.slabel2=ttk.Label(self.page1,text=" System Mode : ")
self.slabel2.grid(row=2,column=1,sticky=E,pady=15,padx=5)
self.slabel3=ttk.Label(self.page1,text=" Total CPU utilization : ")
self.slabel3.grid(row=3,column=1,sticky=E,pady=15,padx=5)
self.slabel31=ttk.Label(self.page1,text="%")
self.slabel31.grid(row=3,column=3,sticky=N+W,pady=15,padx=5)
self.slabel4=ttk.Label(self.page1,text=" No: of Interrupts : ")
self.slabel4.grid(row=4,column=1,sticky=E,pady=15,padx=5)
self.slabel5=ttk.Label(self.page1,text=" Context Switches : ")
self.slabel5.grid(row=5,column=1,sticky=E,pady=15,padx=5)
self.slabel6=ttk.Label(self.page1,text=" Total Memory : ")
self.slabel6.grid(row=6,column=1,sticky=E,pady=15,padx=5)
self.slabel7=ttk.Label(self.page1,text=" Available Memory : ")
self.slabel7.grid(row=7,column=1,sticky=E,pady=15,padx=5)
self.slabel8=ttk.Label(self.page1,text=" Memory Utilization: ")
self.slabel8.grid(row=8,column=1,sticky=E,pady=15,padx=5)
self.book.grid()
t1 = threading.Thread(target=self.tab1_Layout, args = ())
t1.daemon = True
t1.start()
def tab1_Layout(self):
self.MemFile = open('/proc/meminfo','r').readlines()
for line in self.MemFile:
if line.startswith('MemTotal:'):
self.MemTotal = int(line.split()[1])
if line.startswith('MemAvailable:'):
self.MemAvail = int(line.split()[1])
break
MemTotal=self.MemTotal
MemAvail=self.MemAvail
VarS=System.SystemInfo(self.usr_prev,self.sys_prev,self.idle_prev)
self.usr_cur,self.sys_cur,self.idle_cur,usermode,sysmode,totalcpu,intr,ctxt,MemUtil= VarS.deltaTime()
self.usrmodeVal = ttk.Label(self.page1,text = usermode)
self.sysmodeVal = ttk.Label(self.page1,text = sysmode)
self.totcpuVal = ttk.Label(self.page1,text = totalcpu)
self.intrVal = ttk.Label(self.page1,text = intr)
self.ctxtVal = ttk.Label(self.page1,text = ctxt)
self.MemTotalVal = ttk.Label(self.page1,text = MemTotal)
self.MemAvailVal = ttk.Label(self.page1,text = MemAvail)
self.MemUtilVal = ttk.Label(self.page1,text = MemUtil)
self.usrmodeVal.grid(row=1,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.sysmodeVal.grid(row=2,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.totcpuVal.grid(row=3,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.intrVal.grid(row=4,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.ctxtVal.grid(row=5,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.MemTotalVal.grid(row=6,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.MemAvailVal.grid(row=7,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.MemUtilVal.grid(row=8,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.page1.after(I,self.tab1_Layout)
The main problem with your code is that you keep creating more and more widgets. Don't do that. Create the widgets once, and then update them.
You also have the problem that you're using threads, and trying to use widget commands in more than one thread. Tkinter isn't thread safe, and interacting with widgets in two separate threads will yield unpredictable results.
Here's a working example, though I've removed a bunch of widgets to make the code easier to grasp:
from Tkinter import *
import ttk
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.page1 = Frame(self)
self.page1.pack(fill="both", expand=True)
self.tab1_Layout()
self.tab1_Update()
def tab1_Update(self):
self.MemFile = open('/proc/meminfo','r').readlines()
self.MemTotal = self.MemAvail = 0
for line in self.MemFile:
if line.startswith('MemTotal:'):
self.MemTotal = int(line.split()[1])
if line.startswith('MemAvailable:'):
self.MemAvail = int(line.split()[1])
self.MemTotalVal.configure(text=self.MemTotal)
self.MemAvailVal.configure(text=self.MemAvail)
self.after(1000, self.tab1_Update)
def tab1_Layout(self):
self.MemTotalVal = ttk.Label(self.page1, width=10)
self.MemAvailVal = ttk.Label(self.page1, width=10)
self.MemTotalVal.grid(row=6,column=2,sticky=W+E+N+S,padx=5,pady=5)
self.MemAvailVal.grid(row=7,column=2,sticky=W+E+N+S,padx=5,pady=5)
if __name__ == "__main__":
root = Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()