etree findall not working inside function - python

I am puzzled.
I have written this little piece of code before and used it somewhere else:
def testBut(p):
print(root)
for items in root.findall("a/item"):
print(items.get("name"))
and it has worked just fine.
But now in my newer project i have the following code:
for items in root.findall("a/item"):
print(items.get("name"))
def testBut(p):
print(root)
for items in root.findall("a/item"):
print(items.get("name"))
so OUTSIDE the def. it workes just fine, and shows me all the items in a, where as INSIDE the def i get nothing but root (because i print it). Can anyone explain why?
i am sorry if this is a repost or whatever, but i simply cannot find an answer, especially given it works just fine in a different file but exact same setup..
edit: full(ish) code.
from tkinter import *
from xml.etree.ElementTree import ElementTree
from xml.etree.ElementTree import Element
import xml.etree.ElementTree as ET
tree = ET.parse("Alphabet.xml")
root = tree.getroot()
colour0 = "WHITE"
colour1 = "OLIVEDRAB1"
colour2 = "PALETURQUOISE1"
colour3 = "ROSYBROWN1"
font1 = "Arial, 24"
counterRow = 1
counterColumn = 0
for items in root.findall("a/item"):
print(items.get("name"))
def testBut(p):
print(root)
for items in root.findall("a/item"):
print("test")
print(items.get("name"))
def setup():
for letters in root:
global counterRow
global counterColumn
letters.tag = Button(vindue, text=letters.tag, font=font1,
command=lambda p=letters.tag: testBut(p))\
.grid(row=counterRow, column=counterColumn, sticky="nsew")
counterColumn += 1
if counterColumn > 7:
counterRow += 1
counterColumn = 0
def reset():
for buttons in vindue.grid_slaves():
if buttons.grid_info()["row"] > 0:
buttons.grid_forget()
def showBut(input):
counter = 0
reset()
lst = []
print(input)
str = input+"/item"
print(str)
for items in root.findall("a/item"):
print(items.get("name"))
print("test")
varstr = items.get("name")+"Var"
varstr = IntVar()
varstr2 = items.get("name")
varstr2 = Button(vindue, text=items.get("name"), font="Arial, 44", command=lambda varstr=varstr: (varstr.set(varstr.get() + 1), print(varstr.get())))
varstr2.grid(row=1, column=counter)
counter += 1
vindue = Tk()
setup()
vindue.mainloop()

Related

Print value and key in all ListBox TKinter

I cant print the key value of the dic when I print the value of each list
I tried with the code I wrote down!
import tkinter as tk
from tkinter import ttk
limit_before_list = [0]
max_posts_list = [0]
max_comments_list = [0]
limit_before = 'limit_before'
max_posts = 'max_posts'
max_comments = 'max_comments'
def mostrar_nombre(event):
listbox = event.widget
index = listbox.curselection()
value = listbox.get(index[0])
print(pestaña_text)
print(value)
pestañas = {
limit_before: list(range(0, 160, 10)),
max_posts: list(range(0, 410, 10)),
max_comments: list(range(0, 4100, 100)),
}
note = ttk.Notebook()
for pestaña, items in pestañas.items():
frame = ttk.Frame(note)
note.add(frame, text=pestaña)
listbox = tk.Listbox(frame, exportselection=False)
listbox.grid(row=0, column=0)
listbox.bind("<<ListboxSelect>>", mostrar_nombre)
if pestaña == limit_before:
pestaña_text = limit_before
elif pestaña == max_posts:
pestaña_text = max_posts
elif pestaña == max_comments:
pestaña_text = max_comments
for item in items:
listbox.insert(tk.END, item)
note.pack()
note.mainloop()
I excpected something like with the prints. The problem is when I print, I have the same Key for all listbox
>>>limit_before
>>>50
>>>max_post
>>>60
>>>max_comments
>>>100
>>>max_post
>>>30
....
Creating the variable pestaña_text is not handy in this case. It is defined in the main scope but it is overridden in the for loop and keeps the last value max_comments:
for pestaña, items in pestañas.items():
...
if pestaña == limit_before:
pestaña_text = limit_before
elif pestaña == max_posts:
pestaña_text = max_posts
elif pestaña == max_comments:
pestaña_text = max_comments
So when you call it next, in the the function mostrar_nombre, you will only get max_comments.
You can delete this for loop and use directly the selected tab text attribute by referring to the active tab of the NoteBook object with the method select:
def mostrar_nombre(event):
listbox = event.widget
index = listbox.curselection()
value = listbox.get(index[0])
print(note.tab(note.select(), "text"))
print(value)
Some doc here and another similar question here.

Python function returns empty list when string variable is passed

I am working on an Autocomplete text editor. It take an input from the user when space is pressed and prints the list of words with prefix mentioned by the user.
Here is the code:
#!/usr/bin/env python
from tkinter import *
import tkinter.font as tkFont
class Node:
def __init__(self):
self.word = None
self.nodes = {} # dict of nodes
def __get_all__(self):
x = []
for key, node in self.nodes.items():
if (node.word is not None):
x.append(node.word)
x = x + node.__get_all__
return x
def __str__(self):
return self.word
def __insert__(self, word, string_pos=0):
current_letter = word[string_pos]
if current_letter not in self.nodes:
self.nodes[current_letter] = Node();
if (string_pos + 1 == len(word)):
self.nodes[current_letter].word = word
else:
self.nodes[current_letter].__insert__(word, string_pos + 1)
return True
def __get_all_with_prefix__(self, prefix, string_pos):
x = []
#print("We are in the get prefix func", prefix)
for key, node in self.nodes.items():
if (string_pos >= len(prefix) or key == prefix[string_pos]):
if (node.word is not None):
x.append(node.word)
if (node.nodes != {}):
if (string_pos + 1 <= len(prefix)):
x = x + node.__get_all_with_prefix__(prefix, string_pos + 1)
else:
x = x + node.__get_all_with_prefix__(prefix, string_pos)
return x
class Trie:
def __init__(self):
self.root = Node()
def insert(self, word):
self.root.__insert__(word)
def get_all(self):
return self.root.__get_all__
def get_all_with_prefix(self, prefix, string_pos=0):
return self.root.__get_all_with_prefix__(prefix, string_pos)
root = Tk()
trie = Trie()
customFont = tkFont.Font(family="arial", size=17)
with open('words_file_for_testing.txt', mode='r') as f:
for line in f:
for word in line.split():
trie.insert(word)
def retrieve_input(self):
inputValue = content_text.get("1.0", "end-1c")
print(trie.get_all_with_prefix(inputValue))
printing_the_list(inputValue)
def printing_the_list(getinputvalue):
print(getinputvalue)
print(type(getinputvalue))
print(trie.get_all_with_prefix("A"))
print(trie.get_all_with_prefix(getinputvalue))
#print(type(words))
#print(words)
#print(trie.get_all_with_prefix("A"))
#master = Tk()
#listbox = Listbox(master)
#listbox.pack()
#for item in words:
# listbox.insert(END, item)
root.title("Autocomplete Word")
root.geometry('800x400+150+200')
content_text = Text(root, wrap='word', font=customFont)
content_text.focus_set()
content_text.pack(expand='yes', fill='both')
scroll_bar = Scrollbar(content_text)
content_text.configure(yscrollcommand=scroll_bar.set)
scroll_bar.config(command=content_text.yview)
scroll_bar.pack(side='right', fill='y')
root.bind("<space>", retrieve_input)
root.mainloop()
Now, I am having problem with its printing_the_list(getinputvalue) function. In this function, getinputvalue is the variable in which user input value is stored. When I manually entered the string to print(trie.get_all_with_prefix("A")) funtion it print the words list as desired but, when I tried to print the prefix list of words with user input value using the getinputvalue variable, got an empty list as [].
The above python code prints:
[]
A
<class 'str'>
['AAE', 'AAEE', 'AAG', 'AAF', 'AAP', 'AAPSS', 'AAM', 'AAMSI', 'AARC', 'AAII', 'AAO', 'Aar', 'Aaron', 'Aarika', 'Aargau', 'Aaren', 'Aarhus', 'Aara', 'Aarau', 'Aandahl', 'Aani', 'Aaqbiye', 'Aalesund', 'Aalto', 'Aalborg', 'Aalst', 'Aachen', 'A-and-R']
[]
What am I doing wrong.
Your problem is that when you type A and then press space
inputValue = content_text.get("1.0", "end-1c")
returns 'A ' instead of 'A'.
This is because content_text.get() adds a new line character at the end of the string. To ignore both the newline character and the space, use:
inputValue = content_text.get("1.0", "end-2c")

Tkinter - what's the Index of selected value in spinbox?

I've built a class for item selection with Tkinter Spinbox. I'd like to return the index of the selected item. Is that possible?
from Tkinter import *
class TestSpin():
def __init__(self, i_root, i_friendlist):
self.root = i_root
self.root.friend = Spinbox(self.root, values = i_friendlist)
self.root.friend.pack()
self.root.okbutton = Button(self.root, text='Ok', command = lambda: self.ack())
self.root.okbutton.pack()
def ack(self):
# here I'd like to have the index of selected item in friendlist
print "Index of "+self.root.friend.get()+" is [0 or 1 or 2]:", self.root.friend
# here I'd like to have the index of selected item in friendlist
self.root.destroy()
root = Tk()
list = ['Emma','Sarah','James']
app = TestSpin(root, list)
root.mainloop()
Thanks a lot for your advice. I tried self.root.friend.index(), but that method wants an argument which I do not understand.
There's no way to directly get the value from the widget, but it's just one line of python code:
index = i_fiendlist.index(self.root.friend.get())
Using your code, you need to save the value of the list:
class TestSpin():
def __init__(self, i_root,i_friendlist):
self._list = i_list
...
def ack(self):
value = self.root.friend.get()
index = self._list.index(value)
print "Index of " + value + " is " + str(index)
self.root.destroy()

Python 3.4 Assign variable with variable

This is a rather simple question;
I know that you can do:
foo = 1,
self.card1 = "This is card number %s." % (foo)
But I'm trying to assign that variable given by function to the name itself:
def card(foo):
self.foo = foo
self.usrCrdImg%self.foo = Image.open(self.crdStk[randint(1, 50)])
self.usrCrdBg%self.foo = ImageTk.PhotoImage(usrCrdImg%self.foo)
self.usrCrd%self.foo = tkinter.Label(root, image=usrCrdBg%self.foo)
self.usrCrd%self.foo.image = self.usrCrdBg%self.foo
card(1)
#Should Execute like this
def card(1):
self.usrCrdImg1 = Image.open(self.crdStk[randint(1, 50)])
self.usrCrdBg1 = ImageTk.PhotoImage(usrCrdImg1)
self.usrCrd1 = tkinter.Label(root, image=usrCrdBg1)
self.usrCrd1.image = self.usrCrdBg1
Once I get the answer to this question, I'll have another question to ask.
Here's my Code
import tkinter
import winsound
from tkinter import *
from PIL import Image, ImageTk
from random import randint, randrange
class CardGame(tkinter.Frame):
def __init__(self, root):
tkinter.Frame.__init__(self, root)
#define variables for cards
self.crdImg = []
usrStk = None
cpuStk = None
#define card images
i = 1
while i < 57:
i = i + 1
self.crdImg.append('img/cards/%s.png' % (i - 1))
usrStk = self.crdImg[54]
cpuStk = self.crdImg[55]
def debug(card):
self.card = card
self.usrCrdImg%self.card = Image.open(self.crdStk[randint(1, 50)])
self.usrCrdBg%self.card = ImageTk.PhotoImage(self.usrCrdImg%self.card)
self.usrCrd%self.card = tkinter.Label(root, image=self.usrCrdBg%self.card)
self.usrCrd%self.card.image = self.usrCrdBg%i
def card(self):
###
self.usrStk1 = self.crdImg[54]
self.cpuStk1 = self.crdImg[55]
##
self.usrCrdImg1 = Image.open(self.usrStk1)
self.usrCrdBg1 = ImageTk.PhotoImage(self.usrCrdImg1)
self.usrCrd1 = tkinter.Label(root, image=self.usrCrdBg1)
self.usrCrd1.image = self.usrCrdBg1
##
self.cpuCrdImg1 = Image.open(self.cpuStk1)
self.cpuCrdBg1 = ImageTk.PhotoImage(self.cpuCrdImg1)
self.cpuCrd1 = tkinter.Label(root, image=self.cpuCrdBg1)
self.cpuCrd1.image = self.cpuCrdBg1
What you are trying to do is just about the worst way to solve your problem. Generally speaking, you shouldn't ever try to generate variable names on the fly.
The simplest solution is to use a dictionary. Something like this:
def debug(card):
self.card = card
self.usrCrd[self.card]["Img"] = ...
self.usrCrd[self.card]["Bg"] = ...
Though, a better solution is to make a "card" be an instance of a class. Then, you can store these properties as attributes of the class:
class Card(object):
def __init__(self, background, image):
self.bg = background
self.img = image
...
...
self.usrCrd = Card(...)
self.cpuCrd = Card(...)
If you Absolutely Must Create a variable, Eg. a Tkinter button, use something like:
vars = []
founditems = ['item', 'otheritem']
for i in founditems:
vars.append(i)
for n in range(len(founditems)-1):
exec('tkbutton' + vars[i] + '=' + 'Button(textvariable=tv' + vars[i] + ', command=lambda: buttoncommand(' + vars[i] + '))')
The basic format:
exec(var + '=' + varvalue)
If you only need to define the variables name, just do exec('varname = ' + varvalue)

Hangman game (GUI) in Python giving TypeError [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I created a Hangman class and a HangmanGUI class for a final project I am doing for a introductory python class. I'm sorry if I am making amateur mistakes but I do not have a very strong background in coding. Every time my partner and I run the GUI class, we get this error:
self.__letterVar.set(self.__ans.getAnswer())
TypeError: set() missing 1 required positional argument: 'value'
Here is the hangman class:
from random import *
FOUR = 4
class Hangman:
# --------------------------------------------------------------------------
# Constructor
def __init__(self):
self.__theWord = ''
self.__indexList = []
self.__answer = '_ _ _ _ _ _'
# ---------------------------------------------------------------------------
# Accessors
def getTheWord(self):
return self.__theWord
def getIndexList(self):
return self.__indexList
def getAnswer(self):
return self.__answer
def startFruit(self):
randNumber = randint(0,FOUR)
fruit = open("fruits.txt", 'r')
fruitList = fruit.read().splitlines()
self.__theWord = fruitList[randNumber]
return self.__theWord
def startVege(self):
randNumber = randint(0,FOUR)
vege = open("veges.txt", 'r')
vegeList = vege.read().splitlines()
self.__theWord = vegeList[randNumber]
return self.__theWord
def startName(self):
randNumber = randint(0,FOUR)
name = open("names.txt", 'r')
nameList = name.read().splitlines()
self.__theWord = nameList[randNumber]
return self.__theWord
# --------------------------------------------------------------------------
# Mutators
def find(self, answerWord, inputLetter):
if inputLetter in answerWord:
self.__indexList = [index for index, letter in enumerate(answerWord) if letter == inputLetter]
else:
self.__indexList = []
def set (self, inputLetter):
newString = ""
textList = list(self.__answer)
self.__indexList = self.getIndexList()
location = self.__indexList
for aNum in location:
textList[aNum * 2] = inputLetter
newString = ''.join(textList)
self.__answer = newString
def reset(self):
self.__answer = '_ _ _ _ _ _'
# --------------------------------------------------------------------------
# toString()
def__str__(self):
return "Current answer is: %s" % self.__answer
'''
def main():
game = Hangman()
keyWord = game.startFruit()
letter = input("enter letter")
while letter:
game.find(keyWord, letter)
game.set(letter)
print(game)
letter = input("enter letter")
main()
'''
In the same folder there are several files named Fruits, Veges and Names and each file has about 5-6 six letter words in their respective category. I wanted to have the program open and read the file and extract one word randomly in a list.
We tested out our hangman class and we think it works fine but I think our problem stems from our HangmanGUI class.
from tkinter import *
from random import *
from hangman import *
FOUR = 4
class HangmanUI(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("Hangman")
self.grid()
self.__label = Label(self, text = "Let's play Hangman!")
self.__label2 = Label(self, text = "Please choose a category!")
self.__label2.grid(row = 1, column = 0)
self.__buttonPane = Frame(self)
self.__buttonPane.grid(row = 2, column = 0)
# created a model of the hangman class
self.__ans = Hangman()
self.__fruitButton= Button(self.__buttonPane, text = 'Fruits', command = self.startFruit)
self.__nameButton = Button(self.__buttonPane, text = 'Names' , command = self.startName)
self.__vegeButton = Button(self.__buttonPane, text = 'Veges', command = self.startVege)
self.__fruitButton.grid(row = 2, column = 0)
self.__vegeButton.grid(row = 2, column = 1)
self.__nameButton.grid(row = 2, column = 2)
self.__label.grid(row = 0 , column = 0)
#to change later so if shuffles images 1-10 with each error (for loop)
self.__image = PhotoImage(file = "0.gif")
self.__imageLabel = Label(self, image = self.__image)
self.__imageLabel.grid(row = 3, column = 0)
self.__letterLabel = Label(self, text = "Please submit a letter to play!")
# instead of the submit button, tried using enter instead for now
self.__letterVar= StringVar
#self.__letterEntry = Entry(self, textvariable = self.__letterVar) # commented out this line, maybe i shouldn't have?
self.__letterEntry = Entry(self, width = 10)
self.__letterEntry.bind('<Return>', self.set)
self.__letterLabel.grid(row = 4, column = 0)
self.__letterEntry.grid(row = 5, column = 0)
self.__value = Label(self, textvariable = self.__letterVar)
self.__value.grid(row= 6, column = 0)
#creates nested frame
self.__letterPane = Frame(self)
self.__letterPane.grid(row = 7, column = 0)
self.__letter1 = Label(self.__letterPane, text = '_ _ _ _ _ _')
self.__letter1.grid(row = 7, column = 0)
def startFruit(self):
self.__ans.startFruit()
def startVege(self):
self.__ans.startVege()
def startName(self):
self.__ans.startName()
def set(self,event):
guessWord = self.__ans.getTheWord()
entryLetter = self.__letterEntry.get()
self.__ans.find(guessWord, entryLetter)
newValue = self.__letterEntry.get()
self.__ans.set(newValue)
# display new value in letterVar
# this is where the program crashes
self.__letterVar.set(self.__ans.getAnswer())
# invoke delete() to clear entry box
self.__letterEntry.delete(0,END)
def main():
HangmanUI().mainloop()
main()
Sorry for the long code, this is my first time posting here and we're both really stressed out because its finals week at our university and we've been frantically trying to put this together. We're both aren't comp sci majors so this has been a fairly difficult process.
We weren't sure how we should go about calling the Hangman class and use methods from the Hangman class in the GUI. As of right now, we're getting the error I stated above and we're not sure how we can fix it. The program crashes towards the end of the GUI class at def set(self, event):
If anyone can provide any insight and tips, that would be greatly appreciated!
You need to make __letterVar an instance of StringVar:
self.__letterVar = StringVar()
otherwise the set() method on it is unbound and won't get the automatic self first argument.
Your code assigned it as the class, not a new instance, instead.

Categories

Resources