I have written the following code but for some reasons the .get() gives me nothing.
I have tried printing fullname.get()'s len and it gives me 0 with following error:
<class 'str'>
0
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
TypeError: 'NoneType' object is not callable
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
TypeError: 'NoneType' object is not callable
[Finished in 21.5s]
from tkinter import *
from tkinter.ttk import *
from tkinter.messagebox import *
from db import DBConnect
from listComp import ListComp
conn = DBConnect()
def Complaint():
comp = Tk()
comp.geometry('1366x768')
comp.title('Complaint Box')
comp.configure(background='#2919bf')
#Style
style1 = Style()
style1.theme_use('classic')
for elem in ['TLabel', 'TButton', 'TRadioutton']:
style1.configure(elem, background='#35a5e1')
labels = ['Full Name:', 'Gender:','Choose a Category', 'Comment:']
for i in range(4):
Label(comp, text=labels[i]).grid(row=i, column=0, padx=200, pady=25)
BuList = Button(comp, text='List Comp.')
BuList.grid(row=5, column=1)
BuSubmit = Button(comp, text='Submit Now')
BuSubmit.grid(row=5, column=2)
tkvar = StringVar(comp)
# Dictionary with options
choices = { 'Student','Teacher','Management','Infrastructure',''}
tkvar.set('') # set the default option
#Gridx1353
popupMenu = OptionMenu(comp, tkvar, *choices)
popupMenu.grid(row = 2, column =1)
tkvar.trace('w', change_dropdown(tkvar.get()))
#Entries
fullname = Entry(comp, width=40, font=('Arial', 14))
fullname.grid(row=0, column=1, columnspan=2)
SpanGender = StringVar()
r1 = Radiobutton(comp, text='Male', value='male', variable=SpanGender).grid(row=1, column=1)
r2 = Radiobutton(comp, text='Female', value='female', variable=SpanGender).grid(row=1, column=2)
comment = Text(comp, width=35, height=5, font=('Arial', 14))
comment.grid(row=3, column=1, columnspan=2, padx=10, pady=10)
f=fullname.get()
print(type(f))
print(len(f))
print(fullname.get())
s=SpanGender.get()
t=tkvar.get()
c=comment.get(1.0,'end')
BuSubmit.config(command=lambda:SaveData(f,s,t,c))
BuList.config(command=ShowList)
comp.mainloop()
# on change dropdown value
def change_dropdown(tkvar):
print( tkvar )
# link function to change dropdown
def SaveData(fullname,SpanGender,tkvar,comment):
msg1= "Failed please fill all information!."
#print(len(fullname))
if len(fullname) == 0 or len(SpanGender)==0:
showinfo(title='Add Info',message=msg1)
else:
msg = conn.Add(fullname,SpanGender,tkvar,comment)
#fullname.delete(0, 'end')
#comment.delete(1.0, 'end')
#r1.deselect()
#r2.deselect()
showinfo(title='Add Info', message=msg)
def ShowList():
listrequest = ListComp()
#Config
root = Tk()
root.geometry('1366x768')
root.title('Complaint Box')
root.configure(background='#2919bf')
style = Style()
style.theme_use('classic')
for elem in ['TLabel', 'TButton']:
style.configure(elem, background='#35a5e1')
Label(root, text="Welcome To Indian Government Complaint Department",font="Verdana 24 bold").grid(row=1, column=0,padx=150,pady=10)
BuRegister = Button(root, text='Register Complaint',command=Complaint)
BuRegister.grid(row=5,pady=200,padx=10)
#BuRegister.place(relx=0.5, rely=0.5, anchor=CENTER)
BuView = Button(root, text='View Complaint',command=ShowList)
BuView.grid(row=7,pady=0,padx=10)
root.mainloop()
There is no way for me to reproduce your error. I suspect it could be caused by import * or one of your bad get() methods. Likely the get() methods as you do not even set value of entry's text and probably getting the Null value from that.
Keep in mind you need to run the get() method inside of a function and not in the same location you are initializing your code.
One of the other major problems is the use of Tk() more than once. You always want to use only one instance of Tk() when building a Tkinter GUI. For new windows use Toplevel().
I have cleaned up your code to follow PEP8 more closely. Let me know if this helps.
import tkinter as tk # use these imports so you do not overwrite other imports.
import tkinter.ttk as ttk # use these imports so you do not overwrite other imports.
import tkinter.messagebox as messagebox # avoid import *. Its normally not needed.
from db import DBConnect
from listComp import ListComp
def complaint(master):
comp = tk.Toplevel(master)
comp.geometry('1366x768')
comp.title('Complaint Box')
comp.configure(background='#2919bf')
style1 = ttk.Style()
style1.theme_use('classic')
tkvar = tk.StringVar(master)
tkvar.set('')
labels = ['Full Name:', 'Gender:', 'Choose a Category', 'Comment:']
choices = {'Student', 'Teacher', 'Management', 'Infrastructure', ''}
for elem in ['TLabel', 'TButton', 'TRadiobutton']: # fixed typo
style1.configure(elem, background='#35a5e1')
for i in range(4):
ttk.Label(comp, text=labels[i]).grid(row=i, column=0, padx=200, pady=25)
popup_menu = tk.OptionMenu(comp, tkvar, *choices)
popup_menu.grid(row=2, column=1)
tkvar.trace('w', lambda: change_dropdown(tkvar)) # corrected your trace command.
fullname = tk.Entry(comp, text='', width=40, font=('Arial', 14))
fullname.grid(row=0, column=1, columnspan=2)
span_gender = tk.StringVar(master)
ttk.Radiobutton(comp, text='Male', value='male', variable=span_gender).grid(row=1, column=1)
ttk.Radiobutton(comp, text='Female', value='female', variable=span_gender).grid(row=1, column=2)
comment = tk.Text(comp, width=35, height=5, font=('Arial', 14))
comment.grid(row=3, column=1, columnspan=2, padx=10, pady=10)
ttk.Button(comp, text='List Comp.', command=show_list).grid(row=5, column=1)
ttk.Button(comp, text='Submit Now', command=lambda: save_data(fullname, span_gender,
tkvar, comment)).grid(row=5, column=2)
def change_dropdown(tkvar):
print(tkvar.get())
def save_data(fullname, span_gender, tkvar, comment):
msg1 = "Failed please fill all information!."
if len(fullname.get()) == 0 or len(span_gender.get()) == 0:
messagebox.showinfo(title='Add Info', message=msg1)
else:
conn = DBConnect() # moved conn to the function. No point in opening connection until its needed.
msg = conn.Add(fullname.get(), span_gender.get(), tkvar.get(), comment.get(1.0, 'end-1c'))
messagebox.showinfo(title='Add Info', message=msg)
# you should probably close the connection here.
def show_list():
# cannot test this function as I do not know what `ListComp()` is doing.
# That said this function is currently pointless as the local variable
# will be basically deleted when the function finishes.
listrequest = ListComp()
root = tk.Tk()
root.geometry('1366x768')
root.title('Complaint Box')
root.configure(background='#2919bf')
style = ttk.Style()
style.theme_use('classic')
for elem in ['TLabel', 'TButton']:
style.configure(elem, background='#35a5e1')
ttk.Label(root, text="Welcome To Indian Government Complaint Department",
font="Verdana 24 bold").grid(row=1, column=0, padx=150, pady=10)
ttk.Button(root, text='Register Complaint', command=lambda: complaint(root)).grid(row=5, pady=200, padx=10)
ttk.Button(root, text='View Complaint', command=show_list).grid(row=7, pady=0, padx=10)
root.mainloop()
Related
There is code that checks the availability of sites.
How can we make the status for each site to change at a user defined time (i.e. the time for each site can be different) The problem is that the number of sites is not limited, because you can add more lines to the application, so I do not understand how to implement it.
I attach a picture of how it looks like:
Code:
import tkinter as tk
from tkinter import ttk
import requests
import time
from tkinter import *
from tkinter import messagebox
data_list = []
window = Tk()
window.geometry('400x700')
window.title("SiteChecker")
def set_input(obj, value):
obj.delete(1.0, "END")
obj.insert("END", value)
def SiteCheck():
# time.sleep
for data in data_list:
url = data[0].get()
status = data[2]
if not str(url).startswith('http'):
continue
print(url)
Get_Response = None
try:
Get_Response = requests.get(url)
except:
status.config(text='status bad')
continue
if Get_Response.status_code == 200:
status.config(text='status ok')
pass
implement
else:
status.config(text='status bad')
def clicked():
txt = Entry(window, width=18)
txt.grid(column=0, pady=8)
txt_row = txt.grid_info()['row']
tim = Entry(window, width=3)
tim.grid(row=txt_row, column=1, pady=8)
txt_row = tim.grid_info()['row']
result1 = Label(window, text="status")
result1.grid(row=txt_row, column=2, pady=8)
data_list.append([txt, tim, result1])
lbl1 = Label(window, text="Enter references:")
lbl1.grid(column=0, row=1)
lbl2 = Label(window, text="Enter the test time: ")
lbl2.grid(column=1, row=1)
lbl3 = Label(window, text="Availability status ")
lbl3.grid(column=2, row=1)
for loop in range(2, 6):
txt1 = Entry(window, width=18)
txt1.grid(column=0, row=loop, pady=8)
tim1 = Entry(window, width=3)
tim1.grid(column=1, row=loop, pady=8)
result1 = Label(window, text="status")
result1.grid(column=2, row=loop, pady=8)
data_list.append([txt1, tim1, result1])
btn = Button(window, text="Add another site", command=clicked)
btn.grid(column=1, row=0)
Check_Button = Button(
window,
command=SiteCheck,
text='Start checking',
)
Check_Button.grid(row=0, column=2)
window.mainloop()
See here (How do I make my function run every second) how to use tkinter after() to achieve what you want. time.sleep won't work for your purpose because it is blocking the execution of the entire code.
From the link given in the comment to your question by Patrick Artner :
Tkinter root windows have a method called after() which can be used to schedule a function to be called after a given period of time. If that function itself calls after() you've set up an automatically recurring event.
i am building a google translator with tkinter and googletrans, and everything looks good and works well until i added the last part of it that handles what happens when you press the translator button, that is, this function:
def translate_now():
text_ = text1.get(1.0, END)
t1 = Translator()
trans_text = t1.translate(text_, src=combo1.get(), dest=combo2.get())
trans_text = trans_text.text
text2.delete(1.0, END)
text2.insert(END, trans_text)
it then gives me this error when i run it:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\FSTC\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\FSTC\Downloads\translator\main.py", line 24, in translate_now
trans_text = t1.translate(text_, src=combo1.get(), dest=combo2.get())
File "C:\Users\FSTC\Downloads\translator\venv\lib\site-packages\googletrans\client.py", line 182, in translate
data = self._translate(text, dest, src, kwargs)
File "C:\Users\FSTC\Downloads\translator\venv\lib\site-packages\googletrans\client.py", line 78, in _translate
token = self.token_acquirer.do(text)
File "C:\Users\FSTC\Downloads\translator\venv\lib\site-packages\googletrans\gtoken.py", line 194, in do
self._update()
File "C:\Users\FSTC\Downloads\translator\venv\lib\site-packages\googletrans\gtoken.py", line 62, in _update
code = self.RE_TKK.search(r.text).group(1).replace('var ', '')
AttributeError: 'NoneType' object has no attribute 'group'
below is my full source code for more clarity:
from tkinter import *
from tkinter import ttk, messagebox
import googletrans
from googletrans import Translator
root = Tk()
root.title("Google Translator")
root.geometry("1080x400")
root.resizable(False, False)
root.configure(background="white")
def label_change():
c = combo1.get()
c1 = combo2.get()
label1.configure(text=c)
label2.configure(text=c1)
root.after(1000, label_change)
def translate_now():
text_ = text1.get(1.0, END)
t1 = Translator()
trans_text = t1.translate(text_, src=combo1.get(), dest=combo2.get())
trans_text = trans_text.text
text2.delete(1.0, END)
text2.insert(END, trans_text)
# icon
image_icon = PhotoImage(file="images.png")
root.iconphoto(False, image_icon)
# arrow
arrow_image = PhotoImage(file="arrow.png")
image_label = Label(root, image=arrow_image, width=150)
image_label.place(x=460, y=50)
language = googletrans.LANGUAGES
languageV = list(language.values())
lang1 = language.keys()
# first combobox
combo1 = ttk.Combobox(root, values=languageV, font="Roboto 14", state="r")
combo1.place(x=110, y=20)
combo1.set("ENGLISH")
label1 = Label(root, text="ENGLISH", font="segoe 30 bold", bg="white", width=18, bd=5, relief=GROOVE)
label1.place(x=10, y=50)
# second combobox
combo2 = ttk.Combobox(root, values=languageV, font="Roboto 14", state="r")
combo2.place(x=730, y=20)
combo2.set("SELECT LANGUAGE")
label2 = Label(root, text="ENGLISH", font="segoe 30 bold", bg="white", width=18, bd=5, relief=GROOVE)
label2.place(x=620, y=50)
# frame 1
f = Frame(root, bg="black", bd=5)
f.place(x=10, y=118, width=440, height=210)
text1 = Text(f, font="Robote 20", bg="white", relief=GROOVE, wrap=WORD)
text1.place(x=0, y=0, width=430, height=200)
scrollbar1 = Scrollbar(f)
scrollbar1.pack(side="right", fill="y")
scrollbar1.configure(command=text1.yview)
text1.configure(yscrollcommand=scrollbar1.set)
# frame 2
f1 = Frame(root, bg="black", bd=5)
f1.place(x=620, y=118, width=440, height=210)
text2 = Text(f1, font="Robote 20", bg="white", relief=GROOVE, wrap=WORD)
text2.place(x=0, y=0, width=430, height=200)
scrollbar2 = Scrollbar(f1)
scrollbar2.pack(side="right", fill="y")
scrollbar2.configure(command=text2.yview)
text2.configure(yscrollcommand=scrollbar2.set)
# button to translate
translate = Button(root, text="Translate", font=("Roboto", 15), activebackground="white", cursor="hand2",
bd=1, width=10, height=2, bg="black", fg="white", command=translate_now)
translate.place(x=476, y=250)
label_change()
root.mainloop()
am suspecting it may be having problems connecting to google translator or something similar. but what could be the problem precisely?
you are getting this error because you dont have updated version of googletrans,
so use update version of googletrans :
Command to install update version: "pip install googletrans==3.1.0a0"
This will solve your problem.
I'm trying to build a very simple program in Python and Tkinter that allows the user to input people's names by keyboard and then a button is commanded to select a person from the list at random and show it in a tk.Label object.
My problem is once I run the root.mainloop(), I can add names to the list but the list does not update with the new names.
This is the main code for the Tkinter to initialize
import tkinter as tk
from tkinter import filedialog, Text
import random
root = tk.Tk()
root.title('Millor persona del moment')
root.geometry("500x200")
root.configure(bg='black')
peopleList = []
tk.Label(root, text="Insertar participante: ",fg="#ff007f", bg='black').grid(row=0)
e1 = tk.Entry(root)
e1.grid(row=0, column=1)
addButton = tk.Button(root, text='AƱadir', padx=10, pady=5, fg="#ff007f", bg='black', command=addPerson)
addButton.grid(row=0, column=2)
while peopleList:
turnButton = tk.Button(root, text='Saca Tema', padx=10, pady=5, fg="#ff007f", bg='black', command=wordTurn(peopleList))
turnButton.grid(row=1, column=0)
nom = tk.StringVar()
nom.set('Comencem')
personSpeaking = tk.Label(root, textvariable=nom,fg="#ff007f", bg='black')
personSpeaking.grid(row=1, column=1)
root.mainloop()
And these are the functions I use
def addPerson():
peopleList.append(e1.get())
e1.delete(0,'end')
def wordTurn(peopleList):
person = random.choice(peopleList)
peopleList.remove(person)
nom.set(person)
command=wordTurn(peopleList)) calls the return value of wordTurn when the button is pressed, which is None and should raise an error. Use command=lambda peopleList=peopleList: wordTurn(peopleList)) instead.
relatively new to coding and currently I am playing with tkinter in python, I am using a text widget within a function and want to send the input from the text box to another function. My global variable says undefined at module level, so How could I make it defined at a module level if its within a function?
When I press the send email button I get this error message "NameError: name 'user_message_entry' is not defined"
Any suggestions? Many thanks!
minimum reproduction:
import tkinter as tk
root = tk.Tk()
root.geometry("500x500")
def send_email():
global user_message_entry
subject = ":)"
body = user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback():
feedback_window = tk.Toplevel()
feedback_window.geometry("690x650")
message_frame = tk.Frame(feedback_window)
message_frame.grid(row=0, column=0, columnspan=3)
user_message_entry = tk.Text(message_frame, height=10, width=60)
user_message_entry.grid(row=0, column=0)
send_email_button = tk.Button(feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
send_email_button.grid(row=1, column=0)
open_feedback_button = tk.Button(root, command=feedback, height=20, width=20, bg="yellow", text="open feedback window")
open_feedback_button.grid(row=1, column=0)
root.mainloop()
You can use Object orient methodology to make access sympler, another option also you can use globals() to make variable global
One way
globals()['user_message_entry'] = tk.Text(message_frame, height=10, width=60)
....
and from another function you can call
body = globals()['user_message_entry'].get("1.0", "end")
Second way
Object oriented programming is good for every type of problem solving, so you can use class as well
import tkinter as tk
class CBased:
def __init__(self, master, *args, **kwargs):
super(CBased, self).__init__(*args, *kwargs)
self.master = master
master.geometry("500x500")
self.open_feedback_button = tk.Button(master, command=self.feedback, height=20, width=20, bg="yellow", text="open feedback window")
self.open_feedback_button.grid(row=1, column=0)
def send_email(self):
subject = ":)"
body = self.user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback(self):
self.feedback_window = tk.Toplevel()
self.feedback_window.geometry("690x650")
self.message_frame = tk.Frame(self.feedback_window)
self.message_frame.grid(row=0, column=0, columnspan=3)
self.user_message_entry = tk.Text(self.message_frame, height=10, width=60)
self.user_message_entry.grid(row=0, column=0)
self.send_email_button = tk.Button(self.feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
self.send_email_button.grid(row=1, column=0)
def main():
root = Tk()
myobj = CBased(root)
root.mainloop()
if __name__ == "__main__":main()
In this way you can call every single item by self.xyz
Below is the the code that I currently have. I am beginner programmer and am writing a small program that will automate some workflow for primer design (biologist / bioinformaticists represent).
The issue I have right now is that my lack of understanding of how OOP works with TKinter. I have read numerous stackoverflow posts and watched youtube videos and read guides that try to explain it but I am still somewhat at a loss. My current understanding is that each window should be its own object, with the window above it as its parent. I've attempted to do this with my program.
Currently I have two classes, AUTOPRIMER, and BlastAPI. AUTOPRIMER is the main window. There is a button in that window that I have created that should open up a new window when clicked. From my understanding, I have created a new object for that window called BlastAPI which deals with that particular requirement of my program. I see many guides that suggest the parent should be put in the init of the new object, but there are so many initialization variations I have seen from parent to master to args*, kwargs**. What is appropriate when? Also, currently the stack trace provides this feedback as it doesn't even compile properly.
Traceback (most recent call last):
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 201, in <module>
autoprimer = AUTOPRIMER(root)
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 105, in __init__
self.blast = BlastAPI(self)
File "/Users/Thunderpurtz/Desktop/CGIStuff/AUTOPRIMER/autoprimercode/test1.py", line 150, in __init__
eValueSetting = Entry(parent)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2673, in __init__
Widget.__init__(self, master, 'entry', cnf, kw)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2289, in __init__
BaseWidget._setup(self, master, cnf)
File "/anaconda3/lib/python3.6/tkinter/__init__.py", line 2259, in _setup
self.tk = master.tk
AttributeError: 'AUTOPRIMER' object has no attribute 'tk'
[Finished in 0.289s]
Fundamentally, I think my understanding of gui programming isn't solid so if anyone can provide some insight that would be great. If this question is sort of broad, I'll be happy to clarify in the comments.
import subprocess
from tkinter import *
from tkinter.filedialog import *
import tkinter.messagebox
class AUTOPRIMER:
def __init__(self, master):
#some functions, their content is removed as i do not believe they are relevant
def button1():
pass
def button2():
pass
def button3():
pass
def getPrimers():
pass
def PrimerParser():
pass
def poolPrimers():
pass
self.master = master
self.input = ""
self.output = ""
self.param = ""
self.inputbool = False
self.outputbool = False
self.parambool = False
self.p3filestring = '-p3_settings_file='
self.blast = BlastAPI(self)
master.title("Complete Genomics Inc.")
########## WIDGETS ##########
entry_1 = Entry(master) #input
entry_2 = Entry(master) #output
entry_3 = Entry(master) #parameters
label_1 = Label(master, text="AUTOPRIMER")
button_1 = Button(master, text="Input Filepath: ", command=button1)
button_2 = Button(master, text="Output Filepath: ", command=button2)
button_3 = Button(master, text="Parameters Filepath: ", command=button3)
button_get = Button(master, text="Get Primers", command=getPrimers)
button_parse = Button(master, text="Parse Primers", command = PrimerParser)
button_pool = Button(master, text="Pool Primers", command=poolPrimers)
button_blast = Button(master, text="Blast Primers", command=self.blast)
button_quit = Button(master, text="Quit", command=master.destroy)
########## LAYOUT ##########
label_1.grid(row=0, columnspan=4) #grid doesnt take left right, it takes NSEW directions
button_1.grid(row=1, sticky=E, padx=1, pady=1)
button_2.grid(row=2, sticky=E, padx=1, pady=1)
button_3.grid(row=3, sticky=E, padx=1, pady=1)
button_get.grid(row=4)
button_parse.grid(row=4, sticky=W, column=1)
button_pool.grid(row=4, sticky=W, column=2)
button_blast.grid(row=4, sticky=W, column=3)
button_quit.grid(row=4, sticky=W, column=4)
entry_1.grid(row=1, column=1, sticky=W, padx=1, pady=1)
entry_2.grid(row=2, column=1, sticky=W, padx=1, pady=1)
entry_3.grid(row=3, column=1, sticky=W, padx=1, pady=1)
class BlastAPI:
#class that does blast alignment on primers
from Bio.Blast import NCBIWWW
from Bio.Blast import NCBIXML
def __init__(self, parent):
self.parent = parent
super(BlastAPI, self).__init__() #saw this on another stackoverflow don't truly understand what it means
eValueSetting = Entry(parent)
closeButton = Button(parent, text="Close", command=self.destroy)
inputButton = Button(parent, text="Input file", command=doNothing)
entryField = Entry(parent)
#layout
self.title('Complete Genomics Inc.')
def blastPrimers():
filename = askopenfilename()
with open(filename) as file:
string = file.read()
fasta = fasta_string
result_handle = NCBIWW.qblast("blastn", "nt", fasta)
with open("my_blast.xml", "w") as out_handle:
out_handle.write(result_handle.read())
result_handle.close()
result_handle = open('my_blast.xml')
blast_record = NCBIXML.parse(result_handle)
evalue = 1 #add make it a GUI alterable value blastPrimers
item = next(blast_record)
E_VALUE_THRESH = eValueSetting
while True:
with open('BlastResults.txt', w) as blast:
try:
for alignment in item.alignments:
for hsp in alignment.hsps:
if hsp.expect < E_VALUE_THRESH: #use this to determine if the result will be applicable / HAVE USER SET / default value?
blast.write("****Alignment****")
blast.write("sequence:", alignment.title)
blast.write("length:", alignment.length)
blast.write("e value:", hsp.expect)
blast.write(hsp.query[0:75] + "...")
blast.write(hsp.match[0:75] + "...")
blast.write(hsp.sbjct[0:75] + "...")
item = next(blast_record)
except StopIteration:
print("Done!")
break
root = Tk()
autoprimer = AUTOPRIMER(root)
root.mainloop()
Thanks guys.
Ok so there is a lot that needs work here. I imagine the missing bits are part of your main code but without them testing your code is just not possible. I work with what I could and set up your class's to inherit from the tkinter objects they needed to be. Judging by your button command in your BlastAPI class I am assuming this class should be a Toplevel() window.
I have made some changes to your code and without having Bio.Blast I have changed some things to what I think you might need to do.
import subprocess
import tkinter as tk # import tkinter as tk is good for compatibility and maintainability. Don't use *
from tkinter.filedialog import *
import tkinter.messagebox
from Bio.Blast import NCBIWWW
from Bio.Blast import NCBIXML
class AutoPrimer(tk.Tk): # Class names should normally use the CapWords convention.
def __init__(self):
#initialization
tk.Tk.__init__(self)
self.title("Complete Genomics Inc.")
self.input = ""
self.output = ""
self.param = ""
self.inputbool = False
self.outputbool = False
self.parambool = False
self.p3filestring = '-p3_settings_file='
self.entry_input = tk.Entry(self)
self.entry_output = tk.Entry(self)
self.entry_parameters = tk.Entry(self)
self.entry_input.grid(row=1, column=1, padx=1, pady=1, sticky="w")
self.entry_output.grid(row=2, column=1, padx=1, pady=1, sticky="w")
self.entry_parameters.grid(row=3, column=1, padx=1, pady=1, sticky="w")
self.label1 = tk.Label(self, text="AUTOPRIMER").grid(row=0, columnspan=4)
tk.Button(self, text="Input Filepath: ", command=lambda: self.button1).grid(row=1, padx=1, pady=1, sticky="e")
tk.Button(self, text="Output Filepath: ", command=lambda: self.button2).grid(row=2, padx=1, pady=1, sticky="e")
tk.Button(self, text="Parameters Filepath: ", command=lambda: self.button3).grid(row=3, padx=1, pady=1, sticky="e")
tk.Button(self, text="Get Primers",).grid(row=4)
tk.Button(self, text="Parse Primers",).grid(row=4, column=1, sticky="w")
tk.Button(self, text="Pool Primers",).grid(row=4, column=2, sticky="w")
tk.Button(self, text="Blast Primers", command=lambda: BlastAPI(self)).grid(row=4, column=3, sticky="w")
tk.Button(self, text="Quit", command=self.destroy).grid(row=4, column=4, sticky="w")
#CLASS METHODS
#Series of buttons methods that take in the filepath and displays it in the text widget to the user
def button1(self):
self.entry_input.delete(0,END)
ifp = askopenfilename()
self.setInput(ifp)
self.entry_input.insert(0, ifp)
self.setInputBool(True)
def button2(self):
self.entry_output.delete(0,END)
ofp = asksavefilename()
self.setOutput(ofp)
self.entry_output.insert(0, ofp)
self.setOutputBool(True)
def button3(self):
self.entry_parameters.delete(0,END)
pfp = askopenfilename()
self.entry_parameters.insert(0, pfp)
self.setParameterBool(True)
#Methods that rely on class attributes after using above buttons to set
def get_primers(self):
pass
def primer_parser(self):
pass
def pool_primers(self):
pass
#Setters and Getters
def setInput(self, value):
self.input = value
def setOutput(self, value):
self.output = value
def setParam(self, value):
self.param = value
def setInputBool(self, value):
self.inputbool = value
def setOutputBool(self, value):
self.outputbool = value
def setParameterBool(self, value):
self.parambool = value
class BlastAPI(tk.Toplevel):
def __init__(self, parent):
tk.Toplevel.__init__(self, parent)
self.title('Complete Genomics Inc.')
self.e_value_thresh = ""
self.e_value_setting = tk.Entry(self)
self.e_value_setting.pack() # Used pack here for quick testing. You will need to work on geometry yourself.
tk.Button(self, text="Close", command=self.destroy).pack()
tk.Button(self, text="Input file").pack()
self.entry_field = tk.Entry(self)
self.entry_field.pack()
def blast_primers(self): # Nothing is calling this function in your example.
filename = askopenfilename()
with open(filename) as file:
string = file.read() # string is not being used here.
fasta = string # No such var name in code.
result_handle = NCBIWWW.qblast("blastn", "nt", fasta) # This had a typo NCBIWW instead of NCBIWWW.
with open("my_blast.xml", "w") as out_handle:
out_handle.write(result_handle.read())
result_handle.close()
result_handle = open('my_blast.xml')
self.blast_record = NCBIXML.parse(result_handle)
evalue = 1 # Is not being used here.
self.item = next(self.blast_record)
self.e_value_thresh = self.e_value_setting.get()
self.blast_write_loop()
def blast_write_loop(self):
# I don't really like while loops and they have problems in event based GUI's.
# I don't think a while loop is needed here anyway.
with open('BlastResults.txt', 'w') as blast:
try:
for alignment in self.item.alignments:
for hsp in alignment.hsps:
if hsp.expect < self.e_value_thresh:
blast.write("****Alignment****")
blast.write("sequence:", alignment.title)
blast.write("length:", alignment.length)
blast.write("e value:", hsp.expect)
blast.write(hsp.query[0:75] + "...")
blast.write(hsp.match[0:75] + "...")
blast.write(hsp.sbjct[0:75] + "...")
self.item = next(self.blast_record)
except StopIteration:
print("Done!")
autoprimer = AutoPrimer()
autoprimer.mainloop()