How to fix StringVar.get() issue - python

I am trying to make autocomplete GUI (like Google's) in Tkinter using StringVar. I defined a callback function , where i used StringVar.get(), where I for different input in Entry I get different output via autocomplete suggestions in ListBox. The problem is that after typing one letter in Entry I get right output but after typing 2 or more I get empty ListBox. Here's the code.
num=input()
num=int(num)
sv=StringVar()
def callback(sv,list,num):
a=sv.get()
pom_list = list
bin_list = []
lexicographic_sort(pom_list)
x = binary_search(a, pom_list)
while x != -1:
bin_list.append(x)
pom_list.remove(x)
x = binary_search(a, pom_list)
i = 0
l = Listbox(root, width=70)
l.grid(row=2, column=5)
if len(bin_list) == 0 or len(a) == 0:
l.delete(0, END)
else:
for list1 in bin_list:
if i == num:
break
l.insert(END, list1[0])
i += 1
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv,list,num))
te = Entry(root, textvariable=sv)
te.grid(row=1,column=5)
where list outside callback function is a list of all suggestions, and bin_list is a list of suggestions of StringVar.get() using binary_search.

It is because all matched items for the first letter have been removed from the search list. You should use a cloned search list in callback(). Also don't create new list to show the result list, create the result list once and update its content in callback().
Furthermore, sort the search list beforehand:
def callback(sv, wordlist, num):
result.delete(0, END) # remove previous result
a = sv.get().strip()
if a:
pom_list = wordlist[:] # copy of search list
#lexicographic_sort(pom_list) # should sort the list beforehand
x = binary_search(a, pom_list)
while x != -1 and num > 0:
result.insert(END, x)
pom_list.remove(x)
num -= 1
x = binary_search(a, pom_list)
...
lexicographic_sort(wordlist)
sv = StringVar()
sv.trace("w", lambda *args, sv=sv: callback(sv, wordlist, num))
...
result = Listbox(root, width=70)
result.grid(row=2, column=5)

Related

replacing all integers in one list, with strings in another

testdeck = ['rock']
finaldeck = ['apple','banana','napalm','ice',5,6,7,8]
def deckhelp(testdeck,finaldeck):
testnumber = 0
testlength = len(testdeck)
for index, (card, item) in enumerate(zip(testdeck, finaldeck)):
if isinstance(item, int): #checks if item is an integer
finaldeck[index] = card
print(finaldeck)
testnumber += 1
if testnumber == testlength:
print('done')
pass
deckhelp(testdeck,finaldeck)
I want rock to replace the 5 located in finaldeck, can't seem to make it happen
This is not an appropriate use of zip() because you only want to iterate through testdeck when you reach the integers in finaldeck.
You also need to use return, not pass, to end the function when you reach the end of testdeck.
def deckhelp(testdeck, finaldeck):
testindex = 0
testlength = len(testdeck)
for index, item in enumerate(finaldeck):
if isinstance(item, int):
finaldeck[index] = testdeck[testindex]
testindex += 1
if testindex == testlength:
print('done')
return
Zip only works in testdeck and finaldeck have the same length. Instead, you can use something like this:
def deckhelp(testdeck, finaldeck):
replace_index = 0
for i, val in enumerate(finaldeck):
if isinstance(val, int):
finaldeck[i] = testdeck[replace_index]
replace_index += 1
if replace_index == len(testdeck):
print("done")
return

I am trying to get an int from entry

import tkinter as tk
import math
window = tk.Tk()
label = tk.Label(text = 'Want to find a root?')
label.pack()
entry = tk.Entry(fg = 'blue')
entry.pack()
n = entry.get()
number = int(n)
answers = {}
roots = [x for x in range(2, 100)]
def search(number):
for i in roots:
if number > i:
if number//i**2 != 0:
if number//i**2 != 1:
if (i**2)*(number//i**2) == number:
answers[i] = number//i**2
print(answers)
search(number)
window.mainloop()
So I need to get a integer from entry and work with it as a int, but entry gives me a string with which i can't work.I can't type a int in entry because the programm doesn't start due to an error
Error:number = int(n)
ValueError: invalid literal for int() with base 10: ''
You are getting the value of an Entry you created seconds ago. Of course it will be nothing! Use entry.get() when you need it, not anytime before. Put the .get() in the search function, and then call int on it.
Updated search function:
def search(number):
number = int(entry.get())
for i in roots:
if number > i:
if number//i**2 != 0:
if number//i**2 != 1:
if (i**2)*(number//i**2) == number:
answers[i] = number//i**2
And remove the two lines in your code that get the entry value and turn it into an int.

Tkinter freeze and won't load the result on screen

I'm new to programming and I'm trying to make an app that calculates the smallest common for you, but for some reason whenever i run it, tkinter seems to just freeze and i don't know what the error seems to be. I suspect that it's the myLabel part, since I can still read the result inside the Terminal.
Thanks in advance~
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!'
, command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!'
, command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!'
, command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 3:
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start'
, command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Most probably, you have problem if the numbers entered is less than 3. As a result, one simple way is to decrease the condition to 2 and if a single number is entered the result is the number itself, if 2 or more no freezing.
NOTE: Freezing here is actually, while loop is running as condition is always True, because of process_list.count(y) == 3 will always be False if less than 3 number entered.
See my suggestion:
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!', command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!', command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!' , command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
if len(numbers_list) == 1: # RETURN IF THE LIST HAS A SINGLE VALUE
result = 'The number is ' + str(numbers_list[0]) + '!'
else:
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 2: # DECREASE THE CONDITIONS TO 2
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start', command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Suggestion to add two conditons;
(1) create a condition until at least 1 number is entered! if len(numbers_list) == 0, loop to enter a number.
(2) create a condition, until N number is added, let's say user must enter at least 3 numbers, change process_list.count(y) == 3 to process_list.count(y) == N and add condition if len(numbers_list) != N, loop to enter more numbers.

Python: Failing to break out of while loop with "SyntaxError: 'break' outside loop"

I am developing a breadth-first-search algorithm for a factorization problem and am running into an interesting/confusing bug when attempting to break out of a while loop. If you run the code below, it will fail inside the "construct_path" method, stating :
File "main.py", line 96
break
SyntaxError: 'break' outside loop
but I am inside of a while loop! If anyone could give me some advice on this issue, I would really appreciate it. Thanks in advance.
from numpy import random
import itertools
import Queue
#Finding multiples, BFS problem
#Given input of list with unique integers 0 - 9 and n = range(0,1000000), calculate smallest multiple of n and unique combination of values in the list
#Example : Input : list = {0,1,2} , n = 3,
# output = 12
# Input : list = {0,1,2} , n = 50
# Output = 200
class Problem:
def __init__(self):
self.n = random.randint(0,10000000)
listSize = random.randint(1,9)
mainSet = set()
self.mainList = []
while True:
toAdd = random.randint(0,9)
if(toAdd not in self.mainList):
self.mainList.append(toAdd)
if(len(self.mainList) == listSize):
break
def get_start_state(self):
s = ''.join(map(str, self.mainList))
return int(s)
def is_goal(self, state):
return True
def get_sucessors(self):
print "Getting successors"
def breadth_first_search(problem):
# a FIFO open_set
open_set = Queue.Queue()
# an empty set to maintain visited nodes
closed_set = set()
# a dictionary to maintain meta information (used for path formation)
meta = dict() # key -> (parent state, action to reach child)
# initialize
start = problem.get_start_state()
meta[start] = (None, None)
open_set.put(start)
while not open_set.empty():
parent_state = open_set.get()
print "{} {}".format("parent_state is ", parent_state)
if problem.is_goal(parent_state):
return construct_path(parent_state, meta)
for (child_state, action) in problem.get_successors(parent_state):
if child_state in closed_set:
continue
if child_state not in open_set:
meta[child_state] = (parent_state, action)
open_set.put(child_state)
closed_set.add(parent_state)
#collect path to desired answer
def construct_path(state, meta):
action_list = list()
while True:
row = meta[state]
if (len(row) == 2):
state = row[0]
action = row[1]
action_list.append(action)
else:
break
return action_list.reverse()
x = Problem()
breadth_first_search(x)
Could be that you have a mix of tabs and spaces so that the break in line 96 looks like it is indented to be below action_list.append(action) but effectively it is below the while. That would explain the error at least.
It is just a guess. But it could be like this, using a visible tabwidth of 4 in the editor:
→ while True:
→ → row = meta[state]
if (len(row) == 2):
state = row[0]
action = row[1]
action_list.append(action)
else:
break
To the Python interpreter this looks like this (because it assumes a tabwidth of 8):
→ while True:
→ → row = meta[state]
if (len(row) == 2):
state = row[0]
action = row[1]
action_list.append(action)
else:
break
This is still valid but obviously means a different thing and would put your break outside of the while loop.

Pop from Empty list error

I am trying to push elements from a list to a stack. Here is the code:
#!/usr/bin/python
class Stack :
def __init__(self) :
self.items = []
def push(self, item) :
self.items.append(item)
def pop(self) :
return self.items.pop()
def isEmpty(self) :
if self.items == []:
return true
def InsertIntostacks(lst1):
X = Stack() #for each expression a stack is defined
Y = Stack()
for words in lst1:
if (ord(words) >= 48 and ord(words) <= 57) or (ord(words) >=65 and ord(words) <= 90):
X.push(words)
else:
Y.push(words)
print X.pop()
if __name__ == '__main__':
a = open("testinput1.txt","r+")
wordList = [line.strip() for line in a];
#print wordList[1]
lst=list()
for words in wordList:
if words == '#':
print "End of file"
else:
lst = list(words)
lst1 = list()
print lst
for x1 in lst:
if x1 != ' ':
lst1.append(x1)
InsertIntostacks(lst1)
So X is getting populated and I need Y to contain the operators, but apparently none of the elements are getting in Y ( input like A=B=C, so Y should contain = = ).
If i remove the constraints and just push all the elements in one stack the operators are there.
What am I doing wrong here?
I suspect maybe your indentation is wrong for InsertIntostacks(lst1), and that's the problem.
Try ensuring that InsertIntostacks(lst1) is properly aligned with the for loop, meaning it executes after the loop, not within it. Right now it's executing during every iteration of the loop, including the first one, where lst is indeed empty.

Categories

Resources