How do I work around python's global variable problem - python

I am currently making a hangman game and I have a global variable that indicates which part of the hangman to draw. The problem is that I need to change the value of this variable (drawRate) within a function as I will need it in a different function later on but python will not let me do this. Is there any way I can work around this problem?
import tkinter as tk
import turtle
import string
from functools import partial
from draw_hangman import drawHangman
word = 'hello'
shown_text = list('-'*len(word))
draw = drawHangman()
drawRate = 0
def whenPressed(button, text):
button.config(state = 'disabled')
ind = []
local_word = list(word)
for i in local_word :
if i == text:
trash = local_word.index(i)
ind.append(trash)
local_word.pop(trash)
local_word.insert(trash, '-')
if len(ind) != 0:
for i in ind:
shown_text.pop(i)
shown_text.insert(i, text)
lab.config(text = ''.join(shown_text))
for i in shown_text:
if i == '-':
trash = True
if trash != True:
print('You Won!')
else:
trash = draw[drawRate]
exec(trash)
drawRate+=1
root = tk.Tk()
t = turtle.Turtle()
alphabet = list(string.ascii_lowercase)
lab = tk.Label(root, text = '-'*len(word), font = (None, 15), width = 30)
lab.grid(row = 0, columnspan = 13)
for i in alphabet:
btn = tk.Button(root, text=i)
command = partial(whenPressed, btn, i)
btn.config(command=command)
row = (alphabet.index(i) // 13)+1
column = alphabet.index(i) % 13
btn.grid(row=row, column=column, sticky="news")
The variable draw is a list with the commands that draws the hangman figure:
draw = [
'''t.penup()
t.fd(200)
t.rt(90)
t.fd(200)''',
'''t.down()
t.lt(270)
t.fd(400)''',
'''t.rt(90)
t.fd(400)''',
'''t.rt(90)
t.fd(300)''',
'''t.rt(90)
t.fd(75)
t.dot(75)''',
't.fd(100)',
'''t.lt(90)
t.fd(60)''',
'''t.back(120)
t.fd(60)
t.rt(90)''',
'''t.fd(75)
t.lt(30)
t.fd(100)''',
'''t.back(100)
t.rt(60)
t.fd(100)''']

You have to declare this variable as global in the whenPressed() function like this:
def whenPressed(button, text):
global drawRate
...

I am a newbie, forgive me in advance if this is incorrect but can you not declare/bring in your global variable at the start of the function: global drawRate
def whenPressed(button, text):
global drawRate
button.config(state = 'disabled')
ind = []
local_word = list(word)
for i in local_word :
if i == text:
trash = local_word.index(i)
ind.append(trash)
local_word.pop(trash)
local_word.insert(trash, '-')
if len(ind) != 0:
for i in ind:
shown_text.pop(i)
shown_text.insert(i, text)
lab.config(text = ''.join(shown_text))
for i in shown_text:
if i == '-':
trash = True
if trash != True:
print('You Won!')
else:
trash = draw[drawRate]
exec(trash)
drawRate+=1

Try defining drawRate as global at the top of your whenPressed function
like
import turtle
import string
from functools import partial
from draw_hangman import drawHangman
word = 'hello'
shown_text = list('-'*len(word))
draw = drawHangman()
drawRate = 0
def whenPressed(button, text):
global drawRate
button.config(state = 'disabled')
ind = []
local_word = list(word)
for i in local_word :
if i == text:
trash = local_word.index(i)
ind.append(trash)
local_word.pop(trash)
local_word.insert(trash, '-')
if len(ind) != 0:
for i in ind:
shown_text.pop(i)
shown_text.insert(i, text)
lab.config(text = ''.join(shown_text))
for i in shown_text:
if i == '-':
trash = True
if trash != True:
print('You Won!')
else:
trash = draw[drawRate]
exec(trash)
drawRate+=1
root = tk.Tk()
t = turtle.Turtle()
alphabet = list(string.ascii_lowercase)
lab = tk.Label(root, text = '-'*len(word), font = (None, 15), width = 30)
lab.grid(row = 0, columnspan = 13)
for i in alphabet:
btn = tk.Button(root, text=i)
command = partial(whenPressed, btn, i)
btn.config(command=command)
row = (alphabet.index(i) // 13)+1
column = alphabet.index(i) % 13
btn.grid(row=row, column=column, sticky="news"```

Related

Infinite loop due to calling functions

I am attempting to make Minesweeper in python using Tkinter. I have completed all of the initial logic but I am having trouble with the squares with zero surrounding bombs. The program is meant to open all of the surrounding squares when a square with zero surrounding bombs is clicked. The problem here is that it somehow creates an infinite loop. This may be due to the fact that I am calling the function click multiple times using a for loop but I am not sure if this is correct or how to fix it.
My code so far:
import tkinter as tk
from random import choices
from math import floor
##•
def openSurroundings(i):
trash = [i+1, i+8, i+9, i+10, i-1, i-8, i-9, i-10]
for a in trash:
if a<81:
click(floor(a/9), a-((a//9)*9))
def click(row, col):
text = numbers[row][col]
widget = buttons[row][col]
widget.grid_forget()
clickSurrounding = False
if text == 0:
text = ''
clickSurrounding = True
lab = tk.Label(window, text = text, height = 2, width = 5)
lab.grid(row = row, column = col)
if clickSurrounding == True:
openSurroundings((row*9)+col)
def placeBombs():
global widgets, bombs
numOfBombs = 10
widgets = list(range(1, (len(buttons)**2)+1))
bombs = choices(widgets, k = numOfBombs)
def findNumbers():
global numbers
numbers = []
lis_num = []
for i in widgets:
if i in bombs:
lis_num.append('•')
continue
else:
trash = [i+1, i+8, i+9, i+10, i-1, i-8, i-9, i-10]
num = 0
for a in trash:
if a > 0 and a in bombs:
num += 1
lis_num.append(num)
for i in range(0, len(lis_num), 9):
numbers.append(lis_num[i:i + 9])
window = tk.Tk()
window.title('Minesweeper')
sideLen = 9
row_index = 0
cell_index = 0
buttons = []
while row_index != sideLen:
button_row = []
while cell_index != sideLen:
button = tk.Button(window, width=5, height = 2, command=lambda row_index=row_index, cell_index=cell_index: click(row_index, cell_index))
button_row.append(button)
button.grid(row=row_index, column=cell_index)
cell_index += 1
buttons.append(button_row)
cell_index = 0
row_index += 1
placeBombs()
findNumbers()

Python Tkinter & matplotlib - RuntimeError

Okay so I wrote this code...
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import matplotlib.pyplot as plt
import threading
CDatei = subprocess.Popen("/home/pi/meinc++/Spi")
print("Hallo")
i = 0
x = 0
def GetValue():
with open("/home/pi/meinc++/BeispielDatei.txt","r") as Datei:
for line in Datei:
time.sleep(0.01)
return line
def WithoutNull(input):
ReturnValue = input
while ReturnValue is None:
ReturnValue = GetValue()
return ReturnValue
def UebergabeWert():
while x == 0:
WholeString = WithoutNull(GetValue())
StringVar, DatumVar = WholeString.strip().split(' - ')
IntStringVar = [int(v) for v in StringVar.split()]
return IntStringVar, DatumVar
def MinutenWert():
Maximum = 0
Minimum = 0
i = 0
LaengeArray = 0
Multiplikator = 10000
ArrayValue = [-999999]*Multiplikator
AlteZeit = time.time()
while 1:
CompleteValue, Trash = UebergabeWert()
ArrayValue[i] = CompleteValue[0]
i = i + 1
ArrayFilter = filter(lambda c: c != -999999,ArrayValue)
ArraySumme = numpy.sum(ArrayFilter)
LaengeArray = len(ArrayFilter)
Mittelwert = ArraySumme/LaengeArray
ArraySortierung = sorted(ArrayFilter)
Maximum = ArraySortierung[LaengeArray-1]
Minimum = ArraySortierung[0]
NeueZeit = time.time()
if NeueZeit-AlteZeit >= 60:
AlteZeit = time.time()
ArrayValue[i:Multiplikator] = [-999999]*(Multiplikator-i)
i = 0
yield Mittelwert
yield Maximum
yield Minimum
yield LaengeArray
yield ArrayFilter
def UebergabeTkinter():
while 1:
Mittelwert = next(MinutenWertYield)
Maximum = next(MinutenWertYield)
Minimum = next(MinutenWertYield)
LaengeArray = next(MinutenWertYield)
ArrayFilter = next(MinutenWertYield)
CompleteValue, DatumVar = UebergabeWert()
Variable1.set(CompleteValue[0])
Variable2.set(CompleteValue[1])
Variable3.set(CompleteValue[2])
Variable4.set(CompleteValue[3])
VariableMittelwert.set(Mittelwert)
VariableMaximum.set(Maximum)
VariableMinimum.set(Minimum)
t = threading.Thread(target = Grafik)
t.start()
root.update()
def Grafik():
GrafikAnfang = time.time()
Array = 0
ArrayGrafik = [0]*20
GrafikEnde = 1
while 1:
CompleteValue, DatumVar = UebergabeWert()
ArrayGrafik[Array] = CompleteValue[0]
LaengeArrayGrafik = len(ArrayGrafik)
fig = Figure(figsize = (3, 3))
axis = fig.add_subplot(111)
axis.legend()
axis.grid()
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.get_tk_widget().grid(row=10,column=0,rowspan=2,columnspan=2)
LinienBreite = numpy.linspace(1,LaengeArrayGrafik,LaengeArrayGrafik)
axis.plot(LinienBreite,ArrayGrafik,'b-')
axis.set_xticks(LinienBreite)
DatumArray = [DatumVar]
axis.set_xticklabels(DatumArray)
canvas.draw()
fig.clear()
print Array
if GrafikEnde-GrafikAnfang < 600:
Array = Array + 1
GrafikEnde = time.time()
if GrafikEnde-GrafikAnfang >= 600:
del ArrayGrafik[0]
def Exit():
root.destroy()
return
try:
MinutenWertYield = MinutenWert()
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
VariableMittelwert = IntVar()
VariableMaximum = IntVar()
VariableMinimum = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label(text = "Der Mittelwert ist: ").grid(row=4,column=0)
Label(text = "Das Maximum ist: ").grid(row=5,column=0)
Label(text = "Das Mimimum ist: ").grid(row=6,column=0)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7)
LabelMittelwert = Label(root, textvariable = VariableMittelwert)
LabelMittelwert.grid(row = 4, column = 1)
LabelMaximum = Label(root, textvariable = VariableMaximum)
LabelMaximum.grid(row = 5, column = 1)
LabelMinimum = Label(root, textvariable = VariableMinimum)
LabelMinimum.grid(row = 6, column = 1)
UebergabeTkinter()
print "Hallo"
root.mainloop()
except KeyboardInterrupt:
CDatei.kill()
root.quit()
root.destroy()
and when i run it, it says "RuntimeError: main thread is not in the main loop".
Short explanation of the code: It's a code to read out sensor data from a text file -
GetValue().
If the Data is Null it'll read out again - WithoutNull().
The Data is then splitted into data and timestamp (cause it has the format val1, val2, val3, val4, time) - UebergabeWert.
Then the maxima, minima and average of the data will be measured - MinutenWert()
After this, the values are set as labels and go their way into Tkinter - UebergabeTkinter()
The Tkinter build is mainly in Try:
What I wanted to do there, is to implement a graph to Tkinter, but because of the fast changing values it got tremendously slow so i decided to put the graph build in a thread and run it parallel to Tkinter. Unfortunately, it doesn't seem to work and I don't know why
Any suggestions?

Improving tkinter.ttk code

I am a fairly novice programmer and through coffee, google, and an immense loss of hair and fingernails have managed to write a very messy code. I am asking anyone to help me simplify the code if possible.
from tkinter import ttk
from tkinter import *
from tkinter.ttk import *
one = 0
why = 'Total Number: {}'
no = 0
clack = 0
click = 'Clicks: {}'
s = ttk.Style()
s.theme_use('clam')
s.configure('red.Vertical.TProgressbar', foreground = 'red', background = 'red')
s.configure('green.Vertical.TProgressbar', foreground = 'green', background = 'green')
s.configure('TButton', relief = 'groove')
def iround(x):
y = round(x) - .5
return int(y) + (y > 0)
class Application(ttk.Frame):
def __init__(self, master = None):
ttk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def Number(self):
global one
cost = 10*(self.w['to'])
if self.number['text'] == "Make Number go up":
self.number['text'] = one
if iround(self.w.get()) == 0:
one += 1
else:
one += iround(self.w.get())
self.number['text'] = one
if self.number['text'] >= cost:
self.buy['state'] = 'normal'
else:
self.buy['state'] = 'disabled'
self.number['text'] >= cost
self.progress['value'] = one
if self.number['text'] >= cost:
self.progress['style'] = 'red.Vertical.TProgressbar'
else:
self.progress['style'] = 'green.Vertical.TProgressbar'
def Buy(self):
global one
self.w['to'] += 1
cost = 10*(self.w['to'])
one = self.number['text'] = (one + 10 - cost)
self.buy['text'] = ('+1 to slider | Cost: {}'.format(cost))
if self.number['text'] < (cost):
self.buy['state'] = 'disabled'
self.progress['value'] = one
self.progress['maximum'] += 10
if self.number['text'] >= cost:
self.progress['style'] = 'red.Vertical.TProgressbar'
else:
self.progress['style'] = 'green.Vertical.TProgressbar'
def scaleValue(self, event):
self.v['text'] = 'Slider Bonus + ' + str(iround(self.w.get()))
def clicks(self, event):
global click
global clack
if self.Clicks['text'] == 'Clicks: 0':
clack += 1
self.Clicks['text'] = click.format(clack)
self.Clicks['text'] = click.format(clack)
clack += 1
def NumberVal(self, event):
global why
global no
if self.fun['text'] == "Total Number: 0":
self.fun['text'] = why.format(no)
if iround(self.w.get()) == 0:
no += 1
else:
no += iround(self.w.get())
self.fun['text'] = why.format(no)
def createWidgets(self):
self.number = Button(self, text = 'Make number go up', command = self.Number, width = 20, style = 'TButton')
self.number.grid(row = 1, column = 1)
self.number.bind('<ButtonRelease>', self.clicks, add = '+')
self.number.bind('<ButtonRelease>', self.NumberVal, add = '+')
self.buy = Button(self, text = '+1 to Slider | Cost: 10', command = self.Buy, width = 20, style = 'TButton')
self.buy.grid(row = 2, column = 1)
self.buy.config(state = 'disabled')
self.v = Label(self, text = 'Slider Bonus + 0', width = 20, anchor = 'center')
self.v.grid(row = 3, column = 3)
self.w = Scale(self, from_ = 0, to = 1, orient = 'horizontal')
self.w.grid(row = 3, column = 1)
self.w.bind('<Motion>', self.scaleValue)
self.progress = Progressbar(self, value = 0, orient = 'vertical', maximum = 10, mode = 'determinate')
self.progress.grid(row = 1, rowspan = 5, column = 2)
self.Clicks = Label(self, text = 'Clicks: 0', width = 20, anchor = 'center')
self.Clicks.grid(row = 1, column = 3)
self.fun = Label(self, text = 'Total Number: 0', width = 20, anchor = 'center')
self.fun.grid(row = 2, column = 3)
app = Application()
app.master.title('Number')
app.mainloop()

How do I validate an entry widget in python?

I'm creating a GUI using Tkinter that is used to collect information from a user. I need to validate:
First and Last name only contain letters, apostrophes, and dashes
Address
Phone number has the correct number of digits
Valid birthday (Feb 31 doesn't exist and birth year between 1900 and 2014)
Email address contains '#' and '.'
Here is my code:
from tkinter import *
import datetime
class tkwindow:
def __init__(self):
window = Tk() # Create window
window.title("Contact Form") # Give window a title
menubar = Menu(window) # Create menu bar
window.config(menu = menubar) # Display menu bar
'''Using the pulldown menu allows easier access to the menu items instead of using a pop-up menu '''
# Create pulldown menu and add to menu bar
messagesMenu = Menu(menubar, tearoff = 0)
menubar.add_cascade(label = "Messages", menu = messagesMenu)
messagesMenu.add_command(label = "Send a Birthday Greeting", command = self.bdayGreeting)
messagesMenu.add_command(label = "Print Address", command = self.printAddress)
# Create another menu option
endMenu = Menu(menubar, tearoff = 0)
menubar.add_cascade(label = "End", menu = endMenu)
endMenu.add_command(label = "Reset Form", command = self.resetForm)
endMenu.add_command(label = "Exit Program", command = window.quit)
# Using Label widget
labelFirst = Label(window, text = "First Name: ").grid(row = 1, column = 1, sticky = E)
labelLast = Label(window, text = "Last Name: ").grid(row = 2, column = 1, sticky = E)
labelAddress = Label(window, text = "Address: ").grid(row = 3, column = 1, sticky = E)
labelPhone = Label(window, text = "Phone Number (8005551234): ").grid(row = 4, column = 1, sticky = E)
labelBday = Label(window, text = "Birthday (MM/DD/YYYY): ").grid(row = 5, column = 1, sticky = E)
labelEmail = Label(window, text = "Email Address (user#domain.com): ").grid(row = 6, column = 1, sticky = E)
# Using Entry widget
self.firstName = StringVar()
entryFirst = Entry(window, textvariable = self.firstName, justify = LEFT).grid(row = 1, column = 2, sticky = W)
self.lastName = StringVar()
entryLast = Entry(window, textvariable = self.lastName, justify = LEFT).grid(row = 2, column = 2, sticky = W)
self.address = StringVar()
entryAddress = Entry(window, textvariable = self.address, justify = LEFT).grid(row = 3, column = 2, sticky = W)
self.phone = StringVar()
entryPhone = Entry(window, textvariable = self.phone, justify = LEFT).grid(row = 4, column = 2, sticky = W)
self.bday = StringVar()
entryBday = Entry(window, textvariable = self.bday, justify = LEFT).grid(row = 5, column = 2, sticky = W)
self.email = StringVar()
entryEmail = Entry(window, textvariable = self.email, justify = LEFT).grid(row = 6, column = 2, sticky = W)
self.errorLblFirst = Label(window, fg = "red")
self.errorLblFirst.grid(row = 1, column = 3)
self.errorLblLast = Label(window, fg = "red")
self.errorLblLast.grid(row = 2, column = 3)
self.errorLblAddress = Label(window, fg = "red")
self.errorLblAddress.grid(row = 3, column = 3)
self.errorLblPhone = Label(window, fg = "red")
self.errorLblPhone.grid(row = 4, column = 3)
self.errorLblBday = Label(window, fg = "red")
self.errorLblBday.grid(row = 5, column = 3)
self.errorLblEmail = Label(window, fg = "red")
self.errorLblEmail.grid(row = 6, column = 3)
# Using Button widget
buttonSubmit = Button(window, text = "Submit", command = self.submit).grid(row = 7, column = 2, sticky = E)
window.mainloop()
def resetForm(self):
self.firstName.set('')
self.errorLblFirst["text"] = ''
self.lastName.set('')
self.errorLblLast["text"] = ''
self.address.set('')
self.errorLblAddress["text"] = ''
self.phone.set('')
self.errorLblPhone["text"] = ''
self.bday.set('')
self.errorLblBday["text"] = ''
self.email.set('')
self.errorLblEmail["text"] = ''
def validFirst(self):
for letter in self.firstName.get():
if not letter.isalpha() and letter not in "'-":
self.errorLblFirst["text"] = " * Letters, apostrophes('), and hypens(-) only"
return False
return True
def validLast(self):
for letter in self.lastName.get():
if not letter.isalpha() and letter not in "'-":
self.errorLblLast["text"] = " * Letters, apostrophes('), and hypens(-) only"
return False
return True
def validAddress(self):
for letter in self.address.get():
if not letter.isalnum() and letter not in "'- .,":
self.errorLblAddress["text"] = " * No special characters"
return False
return True
def validPhone(self):
D = 0
for number in self.phone.get():
if number.isdigit():
D += 1
if D == 10:
return True
else:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
def validBday(self):
'''try:
valid_date = datetime.datetime.strptime(str(self.bday), '%m/%d/%Y')
except ValueError:
print('Invalid date!')'''
return True
def validEmail(self):
for letter in self.email.get():
if not letter.isalnum() and letter not in "#.":
self.errorLblEmail["text"] = " * Must have # and ."
return False
return True
def bdayGreeting(self):
if self.validBday() and self.validFirst() == True:
print("Happy Birthday" + self.firstName.get() + "\n" + self.bday.get())
def printAddress(self):
if self.validFirst() and self.validLast() and self.validAddress() == True:
print(self.firstName.get() + " " + self.lastName.get() + "\n" + self.address.get())
def submit(self):
self.validFirst()
self.validLast()
self.validAddress()
self.validPhone()
self.validBday()
self.validEmail()
tkwindow()
I have a couple questions.
Starting from def validFirst(self), how do I validate the different entry fields? I keep getting NameError: name "asdf" is not defined, SyntaxError: unexpected EOF while parsing, and TypeError: 'int' object is not subscriptable when I modify the code and I'm still stuck on validFirst(self).
I have a set of labels in column 3 reserved for error messages: errorLblFirst = Label(window, text = " ", fg = "red").grid(row = 1, column = 3). Is it possible to set it to " * Invalid Entry", fg = "red" when the validation for that entry fails? Is there another way to get error messages to show?
Thanks in advance for the input!
Edit: I updated to my latest code. Most of the validation works now except for validBday and validEmail if you could check it out.
errorLblFirst = Label(...).grid(...)
This way you assign result of grid() to errorLblFirst but grid() always returns None
Always do it this way
errorLblFirst = Label(...)
errorLblFirst.grid(...)
And now you can do (for example)
errorLblFirst["text"] = " * Invalid Entry"
errorLblFirst["fg"] = "red"
EDIT:
You forgot len() in for i in range(first): in validFirst()
And you don't need eval().
(You got the same problem in validPhone())
F = 0
fName = True
first = self.firstName.get() # without eval()
for i in range(len(first)): # len()
if first[i].isdigit():
F += 1
if F > 0:
return False
else:
return fName
return fName
but you could do this shorter
for letter in self.firstName.get():
if letter.isdigit():
return False
return True
if you need only letters (no space, commas, etc.) you could do this
return self.firstName.get().isalpha()
EDIT:
I see First Name can have apostrophes, and dashes
for letter in self.firstName.get():
if not letter.isalpha() and letter not in "'-":
return False
return True
EDIT: problem with self.phone and StringVar
self.phone is StringVar() - not string
but StringVar() has .get() to get string
for number in range(len( self.phone.get() )):
By the way: you can do for loop more pythonic - without range(len())
for char in self.phone.get():
if char.isdigit():
EDIT: problem with validEmail() and validBday()
Email validation needs more if.
For example you could add
email = self.email.get()
if '#' not in email and '.' not in email::
print( 'email needs # and . at the same time')
but '.#' will pass this test :/
Real email validation is more complicated.
See valid email examples: https://fightingforalostcause.net/content/misc/2006/compare-email-regex.php
self.bday is StringVar - use self.bday.get() in place of str(self.bday)
EDIT:
def validPhone(self):
D = 0
for number in self.phone.get():
if number.isdigit():
D += 1
# outside
if D == 10:
return True
else:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
or even
def validPhone(self):
# remove previous error message
self.errorLblPhone["text"] = ""
D = 0
for number in self.phone.get():
if number.isdigit():
D += 1
if D != 10:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
If number can have only 10 digits (no space, no - , etc):
def validPhone(self):
# remove previous error message
self.errorLblPhone["text"] = ""
D = True
for number in self.phone.get():
if not number.isdigit():
D = False
break
if not D or len(number) != 10:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True

how to update a listbox in one window in one class using a different class python

what i have is a window that opens up and it has a list box. this is created using one class. when i click the search button and results are found using a different class, i want the list box to update without having to open up another window. below is my code so far\n
from Tkinter import *
class addTask:
def __init__(self):
self.addWindow = Tk()
self.addWindow.configure(background = "black")
self.addWindow.geometry("450x450")
self.addWindow.resizable(width = False, height = False)
self.addWindow.title("Add Task")
self.addNameLabel = Label(self.addWindow,text="Add the name of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addNameLabel.place(relx=0.01, rely=0.05)
self.nameWiget = Text (self.addWindow, width = 63, height = 1)
self.nameWiget.place(relx=0.0, rely=0.1)
self.addDateLabel = Label(self.addWindow,text="Add the date of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addDateLabel.place(relx=0.01, rely=0.2)
self.dateWiget = Text (self.addWindow, width = 63, height = 1)
self.dateWiget.place(relx=0.0, rely=0.25)
self.addTaskLabel = Label(self.addWindow,text="Add the details of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addTaskLabel.place(relx=0.01, rely=0.35)
self.taskWiget = Text (self.addWindow, width = 63, height = 1)
self.taskWiget.place(relx=0.0, rely=0.4)
addButton = Button(self.addWindow,height = 5, width = 20, text="Add Task",highlightbackground="black",font=("Helvetica",10,"bold"),command=lambda:self.saveFuntion())
addButton.place(relx=0.25, rely=0.55)
def saveFuntion(self):
nameInfo = (self.nameWiget.get(1.0, END))
dateInfo = self.dateWiget.get(1.0, END)
taskInfo = self.taskWiget.get(1.0, END)
print nameInfo
task1 = Task(nameInfo,dateInfo,taskInfo)
task1.save()
self.nameWiget.delete(1.0,END)
class Task:
def __init__(self,name,date,task):
self.__name = name
self.__date = date
self.__task = task
def save(self):
fileName = open("dataFile.txt","a")
fileName.write(self.__name)
fileName.write(self.__date)
fileName.write(self.__task)
class editTask:
def __init__(self):
self.editWindow = Tk()
self.newWindow = Tk()
self.newWindow.geometry("450x750")
self.editWindow.configure(background = "black")
self.editWindow.geometry("450x750")
self.editWindow.resizable(width = False, height = False)
self.editWindow.title("Edit Task")
self.listBox = Listbox(self.editWindow,heigh = 15, width = 30)
self.listBox.place(relx = 0.2, rely = 0.6)
#drop down menu
self.var = StringVar(self.editWindow)
self.var.set("Select search critria")
self.choices = ["Name","Date"]
self.option = OptionMenu(self.editWindow,self.var,*self.choices)
self.option.configure(bg = "black")
self.option.place(relx = 0.5, rely = 0.2)
#edit label and text box
self.editLabel = Label(self.editWindow,text="Add the name of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.editLabel.place(relx=0.01, rely=0.05)
self.editInfoWiget = Text (self.editWindow, width = 63, height = 1)
self.editInfoWiget.place(relx=0.0, rely=0.1)
# search button
searchButton = Button(self.editWindow,height = 5, width = 20, text="Search for Task",highlightbackground="black",font=("Helvetica",10,"bold"),command=lambda:self.searchFuntion())
searchButton.place(relx=0.3, rely=0.4)
def searchFuntion(self):
critria = self.var.get()
info = self.editInfoWiget.get(1.0,END)
thing = info.split("\n")
thing2 = thing[0]
search = searchCritria(critria,thing2)
search.search()
# def openListBox(self):
class searchCritria():
def __init__(self,critria,info):
self.__critria = critria
self.__info = info
def search(self):
self.file = open("dataFile.txt", "r+")
fileData = self.file.readlines()
self.file.close()
lengthOfFile = len(fileData)
counter = 1
self.name = []
self.date = []
self.details = []
for i in range (lengthOfFile):
split = fileData[i].split("\n")
while counter == 1:
self.name.append(split)
break
while counter == 2:
self.date.append(split)
break
while counter == 3:
self.details.append(split)
break
counter = counter +1
if counter > 3:
counter = 1
if self.__critria == "Name":
for x in range (len(self.name)):
self.taskName = self.name[x]
self.taskName2 = self.taskName[0]
if self.__info == self.taskName2:
openWindow = True
else :
openWindow = False
if openWindow == True:
editTask().listBox.insert(END,self.taskName2)
if self.__critria == "Date":
for x in range (len(self.date)):
self.taskDate = self.date[x]
self.taskDate2 = self.taskDate[0]
if self.__info == self.taskDate2:
print "found"
else :
print"not found"
class editTask2():
def __init__(self):
self.edit2Window = Tk()
self.edit2Window.configure(background = "black")
self.edit2Window.geometry("450x350")
self.edit2Window.resizable(width = False, height = False)
self.edit2Window.title("Edit Task")
any help would be great
thanks
The biggest problem in your code is that you're creating multiple instances of Tk. Tkinter simply isn't designed to work that way. You should only ever create a single instance of Tk. If you need additional windows, create instances of Toplevel.
Also, you need to call the mainloop function of this instance of Tk exactly once. Without it, your GUI will not work.
If you want to update a listbox in another class than where it was created, the concept is pretty simple: if A needs to update B, A needs a reference to B. So, either pass in a reference to the listbox when you create the other class, or give the other class a method you can call where you pass in the reference to the listbox after it was created.

Categories

Resources