PyQt Calculator- Not getting Result - python-3.x

In the following Program, the calculator gui is closing itself when i press "=" for getting the result. I think there is some problem with the eval function. if i remove the eval then i didn't encounter any problem with the program. Need help in figuring this out. Is there any other approach i can try besides this? Thanks in advance.
class Calci(QWidget):
def __init__(self, Parent=None):
super(Calci,self).__init__()
self.initgui()
def initgui(self):
self.list1=
["%","rt","pow","1/x","CE","C","BCK","/","7","8","9","*","4","5","6","-
","1","2","3","+","+-","0",".","="]
self.list2=[(i,j) for i in range(2,8) for j in range(0,4)]
self.button={}
self.data1=""
self.data2=0
self.lineedit=QLineEdit()
self.lineedit.setFocus()
grid=QGridLayout()
self.setLayout(grid)
self.font=QFont("Bookman Old Style",15,25)
self.lineedit.setFont(self.font)
for x,y in zip(self.list1,self.list2):
self.button[y]=QPushButton(x)
grid.addWidget(self.lineedit,0,0,2,4)
self.lineedit.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Expanding)
self.lineedit.setMinimumHeight(70)
grid.addWidget(self.button[y],*y)
self.button[y].setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Expanding)
self.button[y].setMinimumHeight(70)
self.lineedit.setAlignment(Qt.AlignRight)
self.button[y].clicked.connect(lambda state,x=x: self.click(x))
def click(self,n):
if (n=="="):
data1=self.lineedit.text()
self.lineedit.clear()
self.lineedit.insert(eval(data1))
else:
self.lineedit.insert(n)
app=QApplication(sys.argv)
calci=Calci()
calci.show()
app.exec_()

It's most likely failing because of a TypeError when you try to set the line edit text to an integer value. I also don't think self.lineedit.insert() is the method that you want to use. This will add the calculation after the line after the text already entered.
try:
self.lineedit.setText(str(eval(data1)))
This will clear the line edit and set the text to the calculated value.
But:
Please don't use eval like this. This is a very dangerous practice as any python code entered in the text edit will be run.

Related

ValueError: complex() arg is a malformed string

I have to take complex number as an input from Entry widget of tkinter and perform the conjugate operation on that complex number. I applied explicit conversion method but my code is not able to convert Entry widget string into complex number and showing error "ValueError: complex() arg is a malformed string" Can anyone help me?
Thank you in advance.
lbl_shh=Label(second_root,text="Enter parameter Shh",fg="red").grid(column=0,row=7,padx=20,pady=20)
e_shh = Entry(second_root)
lbl_svv=Label(second_root,text="Enter parameter Svv",fg="red").grid(column=0,row=8,padx=20,pady=20)
e_svv = Entry(second_root)
e_shh.grid(column=1,row=7)
e_svv.grid(column=1,row=8)
shh=e_shh.get()
svv=e_svv.get()
shh=shh.replace(" ","")
svv=svv.replace(" ","")
shh=complex(shh)
svv=complex(svv)
#shh=complex(''.join(shh.split()))
#svv=complex(''.join(svv.split()))
shhs=np.conjugate(shh)
svvs=np.conjugate(svv)
num= svv*svvs
dem=shh*shhs
f=np.power(num/dem, 0.25)
I have to print the value of f
I think you misunderstand how to properly get information within tkinter and probably Python in general.
You cannot just use .get() when your code is just initializing. It will always return an empty string unless you have some code that sets the value prior to get and at that point its just redundant to use get.
What you need to do is have some code like a button that will pull the value of your entry(s) after someone has added something to them.
Also I noticed in your example code you have second_root and this leads me to believe you are using 2 instances of Tk() in your code. If that is the case this may also be part of your problem. You should only ever have one instance of Tk() when coding in tkinter.
To ilistrate your problem Take this example:
I added some print statements, a function and a button to show what was actually being grabbed by get() or rather to show it is an empty string. If you do not have anything in the field by the time get() is executed.
And here is an example result from when you put a proper value that complex() can use.
See below example to get an idea of how get() works:
import tkinter as tk
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
def print_entry():
print(entry.get())
tk.Button(root, text='Print Entry', command=print_entry).pack()
root.mainloop()

Tkinter, curselection()[0], IndexError: tuple index out of range

I am connecting frontend to backend of a database application using Tkinter and sqlite3.
Need help finding potential reasons that resulted in this error:
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Peng\AppData\Local\Programs\Python\Python36\lib\tkinter\__init__.py", line 1699, in __call__
    return self.func(*args)
  File "frontend.py", line 9, in get_selected_row
    index=list1.curselection()[0]
IndexError: tuple index out of range
But list1.curselection()[0] is just the id, why is it out of range?
Any help on finding where went wrong will be greatly appreciated!!!
My code:
frontend.py:
from tkinter import *
import backend
window=Tk()
list1.bind('<<ListboxSelect>>',get_selected_row)
def update_command():
backend.update(selected_tuple[0],title_text.get(),author_text.get(),year_text.get(),isbn_text.get())
def get_selected_row(event):
global selected_tuple
index=list1.curselection()[0]
selected_tuple=list1.get(index)
e1.delete(0,END)
e1.insert(END,selected_tuple[1])
e2.delete(0,END)
e2.insert(END,selected_tuple[2])
e3.delete(0,END)
e3.insert(END,selected_tuple[3])
e4.delete(0,END)
e4.insert(END,selected_tuple[4])
backend.py:
import sqlite3
def update(id,title,author,year,isbn):
conn=sqlite3.connect("books.db")
cur=conn.cursor()
cur.execute("UPDATE book SET title=?,author=?,year=?,isbn=? WHERE id=?",(title,author,year,isbn,id))
conn.commit()
conn.close()
Your method is being triggered when there is nothing selected. The easiest fix is to simply check if the tuple is empty:
def get_selected_row(event):
global selected_tuple
index=list1.curselection()
if index: # if the tuple is not empty
selected_tuple=list1.get(index[0])
e1.delete(0,END)
e1.insert(END,selected_tuple[1])
e2.delete(0,END)
e2.insert(END,selected_tuple[2])
e3.delete(0,END)
e3.insert(END,selected_tuple[3])
e4.delete(0,END)
e4.insert(END,selected_tuple[4])
A more proper fix is to find out when it's being triggered like that and prevent it.
it happens when you click into the list1 while it is empty
this is the line that triggers it
list1.bind('<<ListboxSelect>>',get_selected_row)
the solution mentioned above is suitable since you don't seem to have any other code manipulating this event
however, i would word the solution a bit differently, to be consistent with your code naming conventions:
def get_selected_row(event):
global selected_tuple
if list1.curselection():
index=list1.curselection()[0]
selected_tuple=list1.get(index)
e1.delete(0,END)
e1.insert(END,selected_tuple[1])
e2.delete(0,END)
e2.insert(END,selected_tuple[2])
e3.delete(0,END)
e3.insert(END,selected_tuple[3])
e4.delete(0,END)
e4.insert(END,selected_tuple[4])
Since the listbox is empty, then list1.curselection()will be an empty list with no items. Trying to access the first item of that list with [0] in line 3 will throw an error since there is no first item in the list.
def get_selected_row(event):
try:
global selected_tuple
index=list1.curselection()
selected_tuple=list1.get(index[0])
e1.delete(0,END)
e1.insert(END,selected_tuple[1])
e2.delete(0,END)
e2.insert(END,selected_tuple[2])
e3.delete(0,END)
e3.insert(END,selected_tuple[3])
e4.delete(0,END)
e4.insert(END,selected_tuple[4])
except IndexError:
pass
When the get_selected_row function is called, Python will try to execute the indentedblock under try. If there is an IndexErrornone of the lines under try will be executed. Instead the line under except will be executed which is pass. Thepass stetementmeans do nothing. So the function will do nothing when there's an empty listbox.

Yahtzee, need two arguments to an if, remove method

So I'm trying to make yahtzee-board, but I've come to an obstacle which shouldn't be that hard to solve, but I simply cant fix it. This is how my remove function is looking currently:
class Player:
def __init__(self,name):
self.name=name
self.lista={"aces":0,"twos":0,"threes":0,"fours":0,"fives":0,"sixs":0,"upperscore":0,"bonus":0,"pair":0,"twopair":0,"3ofakind":0,"4ofakind":0,"smallstraight":0,"largestraight":0,"fullhouse":0,"chance":0,"yahtzee":0,"lowerscore":0,"totalscore":0}
self.upperbracket={"aces":0,"twos":0,"threes":0,"fours":0,"fives":0,"sixs":0}
self.lowerbracket={"pair":0,"twopair":0,"3ofakind":0,"4ofakind":0,"smallstraight":0,"largestraight":0,"fullhouse":0,"chance":0,"yahtzee":0}
def remove(self,i):
b=input("Do you want to remove a moment?:")
if b=="yes":
c=input("Which moment do you want to remove?")
spelarlista[i].lista[c]=str("&")
self.printtable()
return True
if b=="no":
return False
def add(self):
rundor=0
while rundor!=15:
for i in range(len(spelarlista)):
count=0
print("Rolling dice for: ", str(spelarlista[i]))
self.rolldice()
if self.remove(i)==True:
i=i+1
count+=1
while count<=0:
moment=input("Where do you want to put your points,"+" "+ str(spelarlista[i])+"?:""\n" )
while moment not in self.lista:
print("oops! Try again!")
if spelarlista[i].lista[moment]!=0 or spelarlista[i].lista[moment]==str("&"):
print("Moment has either been removed or you already got points there")
else:
points=input("How many points did you get?: ")
What I want to do is that if I decide to remove an already removed "moment" it's supposed to print "no can do" or something like that, the same thing is if there is already points there.
currently the line of code is looking like this:
if spelarlista[i].lista[moment]!=0 or spelarlista[i].lista[moment]==str("&"):
Notice that this line is working prefectly if I've already added points, but if I try to remove an already removed "moment" it does not work as intended, I simply cant see where everything has gone wrong...
thanks in advance

Passing StringVar object from Entry to Label within functions in tkinter

Hi I've been struggling to get this to work, each time i change something I receive another error. I've been trying to create an entry box with a function and then get the variable from the entry box into a label, created by a button press. When I tried to do this often this error came up.
TypeError: get() missing 1 required positional argument: 'self'
I then put self in in the method brackets.
command = lambda: x.myFunc(self.my_variable.get(self))
Then another error, which I'm not sure how to sort out.
AttributeError: 'My_Class' object has no attribute '_tk'
Here's the full code, I'm new to classes and self, so any corrections are welcome.
from tkinter import *
import time
class My_Class:
def start(self):
self.root=Tk()
self.my_variable=StringVar
self.entry_box=Entry(self.root, textvariable=self.my_variable)
self.entry_box.pack()
self.button=Button(self.root,text="Pass variable now",
command=lambda:x.myFunc(self.my_variable.get(self)))
self.button.pack()
def myFunc(self,my_variable):
self.lab=Label(self.root,text=self.my_variable)
self.lab.pack()
x=My_Class()
x.start()
This is the correct way to create a StringVar object:
text = StringVar() # note additional ()
Can you explain me what x is in the following statement:
lambda: x.myFunc(self.my_variable.get(self))
x is not visible inside the class, because it's declared outside the class.
myFunc is not indented correctly: you should indent it like the __init__ method.
I really recommend you to watch some tutorials on OOP before proceeding. You are basically trying to guess how OOP works.
If you make myFunc A method if the class (which you might be trying to do; it's hard to know because your indentation is wrong), you don't have to pass anything to myFunc. That function has access to everything in the class, so it can get what it needs, when it needs it. That lets you eliminate the use of lambda, which helps reduce complexity.
Also, you normally don't need a StringVar at all, it's just one more thing to keep track of. However, if you really need the label and entry to show exactly the same data, have them share the same textvariable and the text is updated automatically without you having to call a function, or get the value from the widget, or set the value n the label.
Here's an example without using StringVar:
class My_Class:
def start(self):
...
self.entry_box = Entry(self.root)
self.button = Button(..., command = self.myFunc)
...
def myFunc(self):
s = self.entry_box.get()
self.lab = Label(..., text = s)
...

Scrolling an Entry widget on python

I try to make scrolling on an Entry in python.
when I run program nothing happen.
Please any one help me??
this is my code:
self.scrollbar = tk.Scrollbar(self,orient="horizontal")
self.e3 =tk.Entry(self,xscrollcommand=self.scrollbar.set)
self.e3.focus()
self.e3.pack(side="bottom",fill="x")
#self.e3.grid(row=10, column=7)
self.scrollbar.pack(fill="x")
self.scrollbar.config(command=self.e3.xview)
self.e3.config()
Your code works, just delete all "self". Word "self" is usually used in classes (can be replaced with anything, like "bananas"). Here you can find some explanation:
What is the purpose of self?
Working code:
import tkinter as tk
scrollbar = tk.Scrollbar(orient="horizontal")
e3 =tk.Entry(xscrollcommand=scrollbar.set)
e3.focus()
e3.pack(side="bottom",fill="x")
#e3.grid(row=10, column=7)
scrollbar.pack(fill="x")
scrollbar.config(command=e3.xview)
e3.config()
#EDIT: The last line (e3.config()) is unnecessary - it does nothing.

Resources