Related
I am new to python, the above figure is two UI, I was trying to insert the two tab from the right side UI into the left side UI. But I had met some error and no idea how to solve.
Now below is the original coding of the left side UI
import tkinter as tkk
from tkinter import *
from tkinter import messagebox
import os.path
import hashlib
import sys
import time
import getpass
from tkinter import filedialog
import platform
import getpass
import os,sys
import tkinter.font as font
from tkinter import ttk
from tkinter import StringVar
import Consts
import shutil
class Page(tkk.Frame):
def __init__(self, *args, **kwargs):
tkk.Frame.__init__(self, *args, **kwargs)
def show(self):
self.lift()
class Page1(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
my_system=platform.uname()
#computer information
comsys=my_system.system
comnode=my_system.node
comrel=my_system.release
comver=my_system.version
commac=my_system.machine
compro=my_system.processor
comuser=getpass.getuser()
label1 = tkk.Label(self, text="System: "+comsys,bg='white')
label1.grid(row=1,column=1,pady=10,sticky='w')
label2 = tkk.Label(self, text="Computer Name: "+comnode,bg='white')
label2.grid(row=2,column=1,pady=10,sticky='w')
label3 = tkk.Label(self, text="Release: "+comrel,bg='white')
label3.grid(row=3,column=1,pady=10,sticky='w')
label4 = tkk.Label(self, text="Version: "+comver,bg='white')
label4.grid(row=4,column=1,pady=10,sticky='w')
label5 = tkk.Label(self, text="Machine: "+commac,bg='white')
label5.grid(row=5,column=1, pady=10,sticky='w')
label6 = tkk.Label(self, text="Processor: "+compro,bg='white')
label6.grid(row=6,column=1, pady=10,sticky='w')
label7 = tkk.Label(self, text="Username: "+comuser,bg='white')
label7.grid(row=7,column=1,pady=10,sticky='w')
#computer usage hold first, no idea how to do
class Page2(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
tabControl=ttk.Notebook(self)
qsFrame = ttk.Frame(tabControl)
fsFrame = ttk.Frame(tabControl)
csFrame = ttk.Frame(tabControl)
#tab
tabControl.add(qsFrame, text='Quick Scan')
tabControl.add(fsFrame, text='Full Scan')
tabControl.add(csFrame, text='Custom Scan')
tabControl.pack(expand=1,fill="both")
class Page3(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
label = tkk.Label(self, text="This is page 3")
label.grid(row=2,column=1)
def mytools():
total, used, free = shutil.disk_usage("/")
print("Total:%d GB" %(total // (2**30)))
print("Used:%d GB" %(used // (2**30)))
print("Free:%d GB" %(free // (2**30)))
if free <= total/2:
clean = os.popen('Cleanmgr.exe/ sagerun:1').read()
#print(clean)
def btn1():
if __name__ =="__main__":
mytools()
button1=ttk.Button(self,text="Clean Up",command=btn1)
button1.grid(row=3,column=2)
class Page4(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
label = tkk.Label(self, text="This is page 4")
label.grid(row=2,column=1)
class MainView(tkk.Frame):
def __init__(self, *args, **kwargs):
tkk.Frame.__init__(self, *args, **kwargs)
p1 = Page1(self)
p2 = Page2(self)
p3 = Page3(self)
p4 = Page4(self)
buttonframe = tkk.Frame(self)
container = tkk.Frame(self,bg='white')
buttonframe.pack(side="left", fill="x", expand=False)
container.pack(side="left", fill="both", expand=True)
buttonframe.grid_rowconfigure(0,weight=1)
buttonframe.grid_columnconfigure(0,weight=1)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0,weight=1)
p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p3.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p4.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
stats_btn = tkk.PhotoImage(file='C:/FYP/SecuCOM2022/icon&pic/stats.png')
scanner_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\scanner.png')
speedup_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\speedup.png')
settings_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\settings.png')
#logo
logo=tkk.PhotoImage(file="C:\FYP\SecuCOM2022\icon&pic\g (1).png")
label=tkk.Label(buttonframe,image=logo)
label.grid(row=0,column=0, padx=10,pady=10)
logo.image = logo
b1 = tkk.Button(buttonframe, image=stats_btn, command=p1.show, borderwidth=0)
b2 = tkk.Button(buttonframe, image=scanner_btn, command=p2.show, borderwidth=0)
b3 = tkk.Button(buttonframe, image=speedup_btn, command=p3.show, borderwidth=0)
b4 = tkk.Button(buttonframe, image=settings_btn, command=p4.show, borderwidth=0)
b1.image = stats_btn
b2.image = scanner_btn
b3.image = speedup_btn
b4.image = settings_btn
b1.grid(row=1,column=0,padx=10,pady=10)
b2.grid(row=2,column=0,padx=10,pady=10)
b3.grid(row=3,column=0,padx=10,pady=10)
b4.grid(row=4,column=0,padx=10,pady=10)
if __name__ == "__main__":
root= Tk()
main = MainView(root)
main.pack(side="top", fill="both", expand=True)
main.grid_rowconfigure(0,weight=1)
main.grid_columnconfigure(0,weight=1)
root.title("SecuCOM2022")
root.geometry("600x300")
root.maxsize(600,375)
root.minsize(600,375)
root.iconbitmap('C:\FYP\SecuCOM2022\icon&pic\g.png')
root.mainloop()
root.mainloop()
#GUI end`
Next below here is the right side UI coding, there are multiple files for it. I just show files related with the UI only.
Consts.py
ENTRY_WIDTH = 50
FileReportTab.py
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
from tkinter import StringVar
import time
import os.path
import sys
from VTPackage import Consts
class FileReportTab:
def __init__(self, root, frame, vtClient):
self.root = root
self.frame = frame
self.vtClient = vtClient
self.mainVTURLframe = ttk.LabelFrame(frame, text=' File report')
self.mainVTURLframe.grid(column=0, row=1, padx=8, pady=4)
ttk.Label(self.mainVTURLframe, text="Progress:").grid(column=0, row=1, sticky='W') # <== right-align
self.progressBar = ttk.Progressbar(self.mainVTURLframe, orient='horizontal', length=300, mode='determinate')
self.progressBar.grid(column=1, row=1)
ttk.Label(self.mainVTURLframe, text="File path:").grid(column=0, row=2, sticky='W') # <== right-align
self.filePath = StringVar()
filePathEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.filePath, state='readonly')
filePathEntry.grid(column=1, row=2, sticky='W')
ttk.Label(self.mainVTURLframe, text="Status:").grid(column=0, row=3, sticky='W') # <== right-align
self.status = StringVar()
statusEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.status, state='readonly')
statusEntry.grid(column=1, row=3, sticky='W')
ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=4, sticky='W') # <== right-align
self.positiveIndications = StringVar()
positiveIndicationsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.positiveIndications, state='readonly')
positiveIndicationsEntry.grid(column=1, row=4, sticky='W')
ttk.Label(self.mainVTURLframe, text="SHA1:").grid(column=0, row=5, sticky='W') # <== right-align
self.sha1 = StringVar()
sha1Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha1, state='readonly')
sha1Entry.grid(column=1, row=5, sticky='W')
ttk.Label(self.mainVTURLframe, text="SHA256:").grid(column=0, row=6, sticky='W') # <== right-align
self.sha256 = StringVar()
sha256Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha256, state='readonly')
sha256Entry.grid(column=1, row=6, sticky='W')
chooseFileButton = ttk.Button(self.mainVTURLframe, text="Choose File", width=40, command=self._scanFile).grid(column=1, row=0)
self.scanCheckingTimeInterval = 25000 # This is the amount of time we are going to wait before asking VT again if it already processed our scan request
for child in self.mainVTURLframe.winfo_children():
child.grid_configure(padx=4, pady=2)
def showResults(self, results):
try:
#self.file_Path = self.filePath
self.sha1.set(results["sha1"])
self.sha256.set(results["sha256"])
self.positiveIndications.set(results["positives"])
if results["positives"] == 0:
messagebox.showwarning("Analysis Info","File is Safe.\nOur Scanners found nothing Malicious")
elif results["positives"] <= 5:
messagebox.showwarning("Analysis Alert", "Given File may be Malicious")
elif results["positives"] >= 5:
messagebox.showwarning("Analysis Alert", f"Given File is Malicious.\nAdvice you remove the file from your System!")
res = messagebox.askyesno("Analysis Alert","The given file is highly Malicious.\nDo you want to Delete it permanently?")
if res == 1:
print("Attemting to delete file...")
time.sleep(1)
os.remove(self.filePath1)
#if os.PathLike(_scanFile.filePath):
# os.remove(self.filePath)
else:
print("This file cannot be deleted. Please do not use the fie. It's Malicious")
except Exception as e:
messagebox.showerror('Error', e)
def checkStatus(self):
try:
self.scanResult = self.vtClient.get_file_report(self.scanID)
print(self.scanResult)
if self.scanResult["response_code"] == -2: # By reading the next line, you can understand what is the meaning of the -2 response ode
self.status.set("Scanning...")
self.progressBar['value'] = self.progressBar['value'] + 5
self.root.update_idletasks()
self.mainVTURLframe.after(self.scanCheckingTimeInterval, self.checkStatus)
else:
self.hasScanFinished = True
self.showResults(self.scanResult)
self.status.set("Finished!")
self.progressBar['value'] = 100
except Exception as e:
if "To much API requests" in str(e):
pass
def _scanFile(self):
try:
self.progressBar['value'] = 0
self.filePath1 = filedialog.askopenfilename(initialdir="/", title="Select file for VT", filetypes=(("EXE files", "*.exe"), ("all files", "*.*")))
if (self.filePath): # Only if the user chose a file, we will want to continue the process
self.filePath.set(self.filePath1)
self.status.set("Sending file...")
self.progressBar['value'] = 10
self.root.update_idletasks()
self.scanID = self.vtClient.scan_file(self.filePath1)
self.hasScanFinished = False
if not self.hasScanFinished:
self.scanResult = self.vtClient.get_file_report(self.scanID)
print(self.scanResult)
self.checkStatus()
# We could have been using time.sleep() or time.wait(), but then our UI would get stuck.
# by using after, we are initiating a callback in which does not blocks our event loop
except Exception as e:
messagebox.showerror('Error', e)
URLreportTab.py
from tkinter import ttk
from tkinter import StringVar
from VTPackage import Consts
class URLreportTab:
def __init__(self, root, frame, vtClient):
self.root = root
self.frame = frame
self.mainVTURLframe = ttk.LabelFrame(frame, text=' URL report tab!')
# using the tkinter grid layout manager
self.mainVTURLframe.grid(column=0, row=0, padx=8, pady=4)
ttk.Label(self.mainVTURLframe, text="URL:").grid(column=0, row=0, sticky='W') # What does sticky does? Sticky sayes where to stick the label to : N,S,E,W
urlEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH)
urlEntry.grid(column=1, row=0, sticky='E')
ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=1, sticky='W') # <== right-align
Positive = StringVar()
PositiveEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=Positive, state='readonly')
PositiveEntry.grid(column=1, row=1, sticky='W')
ttk.Label(self.mainVTURLframe, text="Detections:").grid(column=0, row=2, sticky='W') # <== right-align
detections = StringVar()
detectionsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=detections, state='readonly')
detectionsEntry.grid(column=1, row=2, sticky='W')
self.notificationFrame = ttk.LabelFrame(self.frame, text=' Notifications', width=40)
# using the tkinter grid layout manager
self.notificationFrame.grid(column=0, row=1, padx=8, pady=10, sticky='W')
ttk.Label(self.notificationFrame, text="Errors:").grid(column=0, row=0, sticky='W') # <== increment row for each
Error = StringVar()
ErrorEntry = ttk.Entry(self.notificationFrame, width=Consts.ENTRY_WIDTH, textvariable=Error, state='readonly')
ErrorEntry.grid(column=1, row=0, sticky='W')
def _cleanErrorMessage(): # We could have been doing this without a function, but it is more neat that way
Error.set("")
def _getReport():
# the _ notation before a function means that this function is internal to the class only. As python cannot really prevent you from using it outside the class (as C# for example) the notation is being used to warn other developers not to call this function outside the class
try:
_cleanErrorMessage() # Starting with cleaning the error message bar
if not urlEntry.get():
print('Please enter a URL')
Error.set("Please enter a URL!")
return
urlToCheck = urlEntry.get()
response = vtClient.get_url_report(urlToCheck)
print(response)
Positive.set(response["positives"])
scans = response["scans"]
findings = set()
for key, value in scans.items():
if value["detected"]:
findings.add(value["result"])
detections.set(",".join([str(finding) for finding in findings]))
except Exception as e:
print(e)
Error.set(e)
checkURLinVTButton = ttk.Button(self.mainVTURLframe, text='Check Now!', command=_getReport).grid(column=2, row=0)
# Instead of setting padding for each UI element, we can just iterate through the children of the main UI object.
for child in self.mainVTURLframe.winfo_children():
child.grid_configure(padx=4, pady=2)
for child in self.notificationFrame.winfo_children():
child.grid_configure(padx=4, pady=2)
VTApp.py
import tkinter as tk
import configparser
from tkinter import Menu
from tkinter import ttk
from tkinter import messagebox
from VTPackage import URLreportTab
from VTPackage import FileReportTab
from VTPackage import VTClient
config = configparser.ConfigParser()
config.read('config.ini')
class VTApp:
def __init__(self):
# Loading the config file
self.config = configparser.ConfigParser()
self.config.read('config.ini')
self.virusTotalAPIkey = config['VirusTotal']['apiKey']
self.vtClient = VTClient.VTClient(self.virusTotalAPIkey)
self.root = tk.Tk()
self.root.title("Virus Total UI")
self.menuBar = Menu()
self.root.config(menu=self.menuBar)
self.fileMenu = Menu(self.menuBar, tearoff=0)
self.fileMenu.add_command(label="New")
self.fileMenu.add_separator()
self.menuBar.add_cascade(label="File", menu=self.fileMenu)
if not self.vtClient.is_API_key_valid():
messagebox.showerror('Error', "API key is not valid! Check your config file")
def _quit():
self.root.quit() # The app will exist when this function is called
self.root.destroy()
exit()
self.fileMenu.add_command(label="Exit", command=_quit) # command callback
self.tabControl = ttk.Notebook(self.root) # Create Tab Control
self.urlFrame = ttk.Frame(self.tabControl)
self.urlTab = URLreportTab.URLreportTab(self.root, self.urlFrame, self.vtClient)
self.tabControl.add(self.urlFrame, text='URL')
self.fileFrame = ttk.Frame(self.tabControl)
self.fileTab = FileReportTab.FileReportTab(self.tabControl, self.fileFrame, self.vtClient)
self.tabControl.add(self.fileFrame, text='File')
self.tabControl.pack(expand=1, fill="both") # Pack to make visible
def start(self):
self.root.mainloop()
Main.py
from VTPackage import VTApp
vtApp = VTApp.VTApp()
vtApp.start()
This is the original code, Sorry for the spacing error, I copy&paste from vsc and it seem like the got some spacing error after Class. So basically this is the original code and I try like import VTApp and code inside class Page2 like
vtApp = VTApp.VTApp()
vtApp.start()
and change some coding in the VTApp.py but it doesn't work.... Does anyone know how to make the script works? I been trying and trying for a week and still couldn't get the solution.
You cannot move a widget from one window to another in tkinter. You will have to recreate the tab in the other window.
So I want to make a simple inventory system CRUD program. So far, I have been able to make it able to add new items, modify them and delete them. I'm lacking one last thing and that is to be able to search from a treeview which shows all of the items from the sqlite3 database. I wish to have a search box where i could just type in the name of the item and the program will print and select the items searched, which then i could do things such as modify or delete the selected items.
So far my code is:
from tkinter import Tk, Button, PhotoImage, Label, LabelFrame, W, E, N, S, Entry, END, StringVar, Scrollbar, Toplevel
from tkinter import ttk
import sqlite3
class Inventory:
db_filename = 'stock.db'
def __init__(self, root):
self.root = root
self.create_gui()
ttk.style = ttk.Style()
ttk.style.configure('Treeview', font=('helvetica',10))
ttk.style.configure('Treeview.Heading', font=('helvetica', 12, 'bold'))
def execute_db_query(self, query, parameters=()):
with sqlite3.connect(self.db_filename) as conn:
print(conn)
print('You have successfully connected to the Database')
cursor = conn.cursor()
query_result = cursor.execute(query, parameters)
conn.commit()
return query_result
def create_gui(self):
self.create_left_icon()
self.create_label_frame()
self.create_message_area()
self.create_tree_view()
self.create_scrollbar()
self.create_bottom_buttons()
self.view_items()
def create_left_icon(self):
photo = PhotoImage(file='./icons/logo.png')
label = Label(image=photo)
label.image = photo
label.grid(row=0, column=0)
def create_label_frame(self):
labelframe = LabelFrame(self.root, text='Input New Items', bg='sky blue', font='helvetica 10')
labelframe.grid(row=0, column=1, padx=8, pady=8, sticky='ew')
Label(labelframe, text='Name of Item:', bg='sky blue', fg='black').grid(row=1, column=1, sticky=W, pady=2, padx=15)
self.typefield = Entry(labelframe)
self.typefield.grid(row=1, column=2, sticky=W, padx=5, pady=2)
Label(labelframe, text='Stock Card ID:', bg='sky blue', fg='black').grid(row=2, column=1, sticky=W, pady=2, padx=15)
self.cardfield = Entry(labelframe)
self.cardfield.grid(row=2, column=2, sticky=W, padx=5, pady=2)
Label(labelframe, text='Count:', bg='sky blue', fg='black').grid(row=3, column=1, sticky=W, pady=2, padx=15)
self.countfield = Entry(labelframe)
self.countfield.grid(row=3, column=2, sticky=W, padx=5, pady=2)
Button(labelframe, text='Add', command=self.on_add_item_button_clicked, fg='black').grid(row=4, column=2, sticky=E, padx=5, pady=5)
def create_message_area(self):
self.message = Label(text='', fg='red')
self.message.grid(row=3, column=1, sticky=W)
def create_tree_view(self):
self.tree = ttk.Treeview(height=10, columns=('card', 'stock'), style='Treeview')
self.tree.grid(row=6, column=0, columnspan=3)
self.tree.heading('#0', text='Name of Item', anchor=W)
self.tree.heading('card', text='Stock Card ID', anchor=W)
self.tree.heading('stock', text='Count', anchor=W)
def create_scrollbar(self):
self.scrollbar = Scrollbar(orient='vertical', command=self.tree.yview)
self.scrollbar.grid(row=6, column=3, rowspan=10, sticky='sn')
def create_bottom_buttons(self):
Button(text='Delete', command=self.on_delete_selected_button_clicked).grid(row=8, column=0, sticky=W, pady=10, padx=20)
Button(text='Edit Stock', command=self.on_modify_selected_button_clicked).grid(row=8, column=1, sticky=W)
def on_add_item_button_clicked(self):
self.add_new_item()
def on_delete_selected_button_clicked(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['values'][0]
except IndexError as e:
self.message['text'] = 'Select at least one item to be deleted'
return
self.delete_items()
def on_modify_selected_button_clicked(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['values'][0]
except:
self.message['text'] = 'Select at least one item to be modified'
return
self.open_modify_window()
def add_new_item(self):
if self.new_items_validated():
query = 'INSERT INTO items_list VALUES(NULL, ?, ?, ?)'
parameters = (self.typefield.get(), self.cardfield.get(), self.countfield.get())
self.execute_db_query(query, parameters)
self.message['text'] = '{} has been added'.format(self.typefield.get())
self.typefield.delete(0, END)
self.cardfield.delete(0, END)
self.countfield.delete(0, END)
self.view_items()
else:
self.message['text'] = 'All entry field must be filled'
self.view_items()
def new_items_validated(self):
return len(self.typefield.get()) !=0 and len(self.cardfield.get()) != 0 and len(self.countfield.get()) != 0
def view_items(self):
items = self.tree.get_children()
for item in items:
self.tree.delete(item)
query = 'SELECT * FROM items_list ORDER BY TipeBarang'
item_entries = self.execute_db_query(query)
for row in item_entries:
self.tree.insert('', 0, text=row[1], values=(row[2], row[3]))
def delete_items(self):
self.message['text']=''
name = self.tree.item(self.tree.selection())['text']
query = 'DELETE FROM items_list WHERE TipeBarang = ?'
self.execute_db_query(query, (name,))
self.message['text'] = '{} has been deleted'.format(name)
self.view_items()
def open_modify_window(self):
name = self.tree.item(self.tree.selection())['text']
old_stock = self.tree.item(self.tree.selection())['values'][1]
self.transient = Toplevel()
self.transient.title('Update Stock')
Label(self.transient, text='Name: ').grid(row=0, column=1)
Entry(self.transient, textvariable=StringVar(
self.transient, value=name), state='readonly').grid(row=0, column=2)
Label(self.transient, text='Old Stock Count: ').grid(row=1, column=1)
Entry(self.transient, textvariable=StringVar(
self.transient, value=old_stock), state='readonly').grid(row=1, column=2)
Label(self.transient, text='New Stock Count: ').grid(row=2, column=1)
new_stock_number_entry_widget = Entry(self.transient)
new_stock_number_entry_widget.grid(row=2, column=2)
Button(self.transient, text='Update Item', command=lambda: self.update_stock(
new_stock_number_entry_widget.get(), old_stock, name)).grid(row=3, column=2, sticky=E)
self.transient.mainloop()
def update_stock(self, newstock, old_stock, name):
query = 'UPDATE items_list SET JumlahStok=? WHERE JumlahStok=? AND TipeBarang=?'
parameters = (newstock, old_stock, name)
self.execute_db_query(query, parameters)
self.transient.destroy()
self.message['text'] = '{} Stock Count has been updated'.format(name)
self.view_items()
if __name__ == "__main__":
root = Tk()
root.title("Inventory System")
root.resizable(width=False, height=False)
application = Inventory(root)
root.mainloop()
Below, I have also attached a screenshot of the program I have made so far. Thank you so much for your help.
Program Screenshot: https://i.stack.imgur.com/1kJch.png
There are a few different ways a search feature can be done here. You can add a search button that creates a Toplevel window and add widgets to it as needed. Or more simply, you can use simpledialog to get text input from the user like so:
queryString = simpledialog.askstring("Search", "Enter item name to search:")
Then pass the resulting queryString to a database function, sanitize it to prevent SQL injection, and SELECT * FROM table WHERE Item = 'queryString'
Then use the data returned from this query to populate your treeview.
def Search():
if SEARCH.get() != "":
tree.delete(*tree.get_children())
conn = sqlite3.connect("db_member.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM `member` WHERE `firstname` LIKE ? OR `lastname` LIKE ?", ('%'+str(SEARCH.get())+'%', '%'+str(SEARCH.get())+'%'))
fetch = cursor.fetchall()
for data in fetch:
tree.insert('', 'end', values=(data))
cursor.close()
conn.close()
this how you can search from Specific Column in Python with Sqlite3 and Tkinter, you have just to change tow things:
the Name of 'member', which is the Name of your created Table
firstname and lastname are the name of your columns, SEARCH.get() is the variable from the entry box
I'm trying to setup a program where my tkinter GUI functions are in a class and my database functions are in another class. I have a function external to both classes that fails when I try to call a function within the DB class. Can you help me resolve this error? Should both my GUI and any database be in separate functions or is that a poor design. The attached code is a stripped down version to illustrates my issue. Clicking the "View all" button generates the error.
import sqlite3
from tkinter import *
from tkinter import messagebox
class DB:
def __init__(self):
self.conn = sqlite3.connect("mybooks.db")
self.cur = self.conn.cursor()
self.cur.execute(
"CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title TEXT, author TEXT, isbn INTEGER)")
self.conn.commit()
def __del__(self):
self.conn.close()
def view(self):
self.cur.execute("SELECT * FROM book")
rows = cur.fetchall()
return rows
def view_command():
# there is a problem with the next line
# when rows=DB.view() error is TypeError: view() missing 1 required positional argument: 'self'
# when rows=DB.view(self) error is NameError: name 'self' is not defined
rows=DB.view(self)
for row in rows:
print(row)
class App_GUI(): # create the main window
def __init__(self, master):
self.master = master
self.master.title("My Books")
self.master.l1 = Label(self.master, text="Title")
self.master.l1.grid(row=0, column=0)
self.master.l2 = Label(self.master, text="Author")
self.master.l2.grid(row=0, column=2)
self.master.l3 = Label(self.master, text="ISBN")
self.master.l3.grid(row=1, column=0)
self.master.title_text = StringVar()
self.master.e1 = Entry(self.master, textvariable=self.master.title_text)
self.master.e1.grid(row=0, column=1)
self.master.author_text = StringVar()
self.master.e2 = Entry(self.master, textvariable=self.master.author_text)
self.master.e2.grid(row=0, column=3)
self.master.isbn_text = StringVar()
self.master.e3 = Entry(self.master, textvariable=self.master.isbn_text)
self.master.e3.grid(row=1, column=1)
self.master.list1 = Listbox(self.master, height=6, width=35)
self.master.list1.grid(row=2, column=0, rowspan=6, columnspan=2)
self.master.sb1 = Scrollbar(self.master)
self.master.sb1.grid(row=2, column=2, rowspan=6)
self.master.list1.configure(yscrollcommand=self.master.sb1.set)
self.master.sb1.configure(command=self.master.list1.yview)
self.master.b1 = Button(self.master, text="View all", width=12, command=view_command)
self.master.b1.grid(row=2, column=3)
self.master.b6 = Button(self.master, text="Close", width=12, command=self.master.destroy)
self.master.b6.grid(row=7, column=3)
return
###############################
# Program Main #
###############################
def main():
db = DB()
root = Tk()
def on_closing():
dd = db
if messagebox.askokcancel("Quit", "Do you want to close the application"): # ask the user if he/she wants to close the application
root.destroy()
del dd
root.protocol("WM_DELETE_WINDOW", on_closing) # catch the user closing the window
app = App_GUI(root) # creation of an instance
root.mainloop() # tkinter mainloop
if __name__ == '__main__':
main()
````
You need to pass db to App_GUI and then on to the function:
def view_command(db):
rows = db.view()
for row in rows:
print(row)
class App_GUI(): # create the main window
def __init__(self, master, db):
# other stuff elided ...
self.master.b1 = Button(self.master, text="View all", width=12, command=lambda : view_command(db))
...
def main():
db = DB()
# other stuff elided
app = App_GUI(root, db)
edit: forgot to remove self.
I figured it out! In addition to your changes, I had to remove 'self' from rows=db.view(). Thanks for your help! Revised code:
import sqlite3
from tkinter import *
from tkinter import messagebox
class DB:
def __init__(self):
self.conn = sqlite3.connect("mybooks.db")
self.cur = self.conn.cursor()
self.cur.execute(
"CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title TEXT, author TEXT, isbn INTEGER)")
self.conn.commit()
def __del__(self):
self.conn.close()
def view(self):
self.cur.execute("SELECT * FROM book")
rows = self.cur.fetchall()
return rows
def view_command(db):
rows=db.view()
for row in rows:
print(row)
class App_GUI(): # create the main window
def __init__(self, master, db):
self.master = master
self.master.title("My Books")
self.master.l1 = Label(self.master, text="Title")
self.master.l1.grid(row=0, column=0)
self.master.l2 = Label(self.master, text="Author")
self.master.l2.grid(row=0, column=2)
self.master.l3 = Label(self.master, text="ISBN")
self.master.l3.grid(row=1, column=0)
self.master.title_text = StringVar()
self.master.e1 = Entry(self.master, textvariable=self.master.title_text)
self.master.e1.grid(row=0, column=1)
self.master.author_text = StringVar()
self.master.e2 = Entry(self.master, textvariable=self.master.author_text)
self.master.e2.grid(row=0, column=3)
self.master.isbn_text = StringVar()
self.master.e3 = Entry(self.master, textvariable=self.master.isbn_text)
self.master.e3.grid(row=1, column=1)
self.master.list1 = Listbox(self.master, height=6, width=35)
self.master.list1.grid(row=2, column=0, rowspan=6, columnspan=2)
self.master.sb1 = Scrollbar(self.master)
self.master.sb1.grid(row=2, column=2, rowspan=6)
self.master.list1.configure(yscrollcommand=self.master.sb1.set)
self.master.sb1.configure(command=self.master.list1.yview)
self.master.b1 = Button(self.master, text="View all", width=12, command=lambda : view_command(db))
self.master.b1.grid(row=2, column=3)
self.master.b6 = Button(self.master, text="Close", width=12, command=self.master.destroy)
self.master.b6.grid(row=7, column=3)
return
###############################
# Program Main #
###############################
def main():
db = DB()
root = Tk()
def on_closing():
dd = db
if messagebox.askokcancel("Quit", "Do you want to close the application"): # ask the user if he/she wants to close the application
root.destroy()
del dd
root.protocol("WM_DELETE_WINDOW", on_closing) # catch the user closing the window
app = App_GUI(root, db) # creation of an instance
root.mainloop() # tkinter mainloop
if __name__ == '__main__':
main()
I have the following Tkinter application which basically helps you to configure a new network just by inserting in the entry box a new value. This value entered by the user it is saved somewhere in a file using the template. This script runs well, but problem is that I am seeing the Tenant entry box upper than Network name entry box. The same is happening with their labels. Then, when we click on the Add network and getting another 2 entry box, are displayed very strange way.
How can I align the labels + entry boxes and how can I have them displayed each group of label+entry box one bellow the other?
Something like:
Tenant [entrybox] Network [entrybox]
Tenant [entrybox] Network [entrybox]
....................................
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.networks = []
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
start_label = tk.Label(self, text="This is the start page")
network_button = tk.Button(self, text="Create the networks", command=lambda: master.switch_frame(Networks))
start_label.pack(side="top", fill="x", pady=10)
deployment_button.pack()
network_button.pack()
subnet_button.pack()
neutronports_button.pack()
script_button.pack()
class Networks(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.entries=[]
self.create_widgets(master)
def create_widgets(self, master):
label = tk.Label(self, text="Insert the name of the networks")
start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
new_network_button = tk.Button(self, text="Add network", command=self.add_network)
new_network_button.bind("<Return>", self.add_network)
new_network_button.grid(row=len(self.master.networks), column=3, padx=4, pady=6, sticky="W")
next_button=tk.Button(self, text="Submit", command=self.networks)
next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
label.pack(side="top", fill="x", pady=10)
start_button.pack()
new_network_button.pack()
next_button.pack()
for index, network in enumerate(self.master.networks):
self.render_network_field(network, index)
def add_network(self):
requirements={'variable': tk.StringVar(self.master), 'cloudvariable': tk.StringVar(self.master)}
if requirements:
self.master.networks.append(requirements)
self.master.switch_frame(Networks)
else:
tkMessageBox.showerror("tk", "No networks defined!")
self.master.switch_frame(Networks)
def render_network_field(self, network, index):
labelText=tk.StringVar()
labelText.set("Tenant name")
labelDir=tk.Label(self,textvariable=labelText, height=4)
labelDir.pack(side="top")
nw_entry_field = tk.Entry(self, textvariable=network['variable'])
nw_entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
nw_entry_field.pack(side="right")
labelText=tk.StringVar()
labelText.set("Network name")
labelDir=tk.Label(self,textvariable=labelText, height=4)
labelDir.pack(side="top")
cloud_entry_field = tk.Entry(self, textvariable=network['cloudvariable'])
cloud_entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
cloud_entry_field.pack(side="right")
self.entries.append((network['cloudvariable'],network['variable']))
def networks(self):
with open("/home/dante/networks.yml", "w") as f:
f.write("--- #" + "\n")
for ent, cloudent in self.entries:
network_value=ent.get()
cloud_value=cloudent.get()
if network_value:
if cloud_value:
f.write("- { cloud: "+cloud_value+", network: "+network_value+ " }"+ "\n")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Following is a simple code that I just made to solve your problem. You just have to put the function register() in your class, that is executed when you press the button register (put it in the same class).
import tkinter as tk
from tkinter import *
def register():
username = x1.get()
password = y1.get()
if username!="" and password=="":
file = open("accountfile.txt","a")
file.write(username)
file.write(" ")
file.write(password)
file.write("\n")
file.close()
root=Tk()
# String variables
x1=StringVar()
y1=StringVar()
Us=Entry(root,textvariable=x1)
Us.grid()
Ps=Entry(root, textvariable=y1)
Ps.grid()
Reg=Button(root,text="Register",command=lambda:register())
Reg.grid()
root.mainloop()
Edit:
To solve your error, make s a global variable. This will define s for all blocks of code in the file. Also, you can set a new value to it and then, use the new value, anywhere else
global s
s=""
def networks(self):
with open("/home/dante/networks.yml", "w") as f:
f.write("--- #" + "\n")
f.write("networks:" + "\n")
for ent in s:
if ent:
f.write("- { cloud: cloud1, network: "+str(ent)+ " }"+ "\n")
def render_network_field(self, network, index):
entry_field = tk.Entry(self, textvariable=network['variable'])
entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
entry_field.pack()
global s
s=entry_field.get()
Hope this helps
I am having trouble outputting my SQL queries properly. I have posted this earlier but I don't think I explained it very well. I am using an entry widget for at least 10 rows in a SQL query.
The program can search for a first name or last name and provide a list of names tied to the search criteria.
It should only list the name in relation to the present query.
Right now, if you enter a name, it will list all the people that have the same name. Then if you do a second search, it will list the new name plus the previous names you searched for. I am trying to figure out how to properly clear it so that the previous names will no longer show.
I am attaching a screen shot of 3 searches from a database of random names.
The first search is for the first name Burney. There is only one Burney in my database so it lists that one Burney.
Second, Josh is searched for. There are probably around 20 Josh's in the datbase so it overwrites Burney and lists Josh names.
Third, Burney is search for again.
Well, it only overwrites the top Entry row with Burney but leaves all of the previous Josh names.
I only want it to show Burney.
I have played with self.myentry.delete(0, END) in the results[x] but I am not sure if I am using it properly. Or if it would even help my situation.
Attached is a screenshot and a short version of my code:
import os
import pypyodbc
import tkinter
from tkinter import ttk
from tkinter import messagebox
from tkinter import BOTH, END, LEFT
class Adder(ttk.Frame):
"""The adders gui and functions."""
def __init__(self, parent, *args, **kwargs):
ttk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.init_gui()
def calculate(self):
firstname = str(self.first_entry.get())
lastname = str(self.last_entry.get())
if (firstname and not lastname): # "You entered first name."
try:
connection = pypyodbc.connect('Driver={SQL Server};Server=MYSERVERNAME;Database=MYDATABASE;Trusted_Connection=yes;')
except pypyodbc.Error as ex:
sqlstate = ex.args[0]
if sqlstate == '28000':
self.answer_label['text'] = "You do not have access."
cursor = connection.cursor()
SQLCommand = ("SELECT LASTNAME, FIRSTNAME "
"FROM dbo.MYTABLENAMEHERE " # table name
"with (nolock)"
"WHERE FIRSTNAME = ?")
Values = [firstname]
cursor.execute(SQLCommand,Values)
results = cursor.fetchmany(10)
if results:
self.output0.delete(0, END)
self.output0.insert(0,results[0])
self.output1.insert(0,results[1])
self.output2.insert(0,results[2])
self.output3.insert(0,results[3])
self.output4.insert(0,results[4])
connection.close()
def init_gui(self):
"""Builds GUI."""
self.root.title('Verify')
self.root.option_add('*tearOff', 'FALSE')
self.grid(column=0, row=0, sticky='nsew') # this starts the entire form
# Input Boxes and Button
self.first_entry = tkinter.Entry(self, width=28) # first input box
self.first_entry.grid(sticky='', column=1, row=1)
self.last_entry = tkinter.Entry(self, width=28) # second input box
self.last_entry.grid(sticky='', column=2, row=1)
self.calc_button = ttk.Button(self, text='Search', command=self.calculate) # button
self.calc_button.grid(column=4, row=1, columnspan=1, sticky='w', padx=14)
# Output entries for answers
self.output0 = tkinter.Entry(self, width=150, bd=0,)
self.output0.grid(column=0, row=6, columnspan=5, padx=100, pady=0)
self.output1 = tkinter.Entry(self, width=150, bd=0,)
self.output1.grid(column=0, row=7, columnspan=5, padx=100, pady=0)
self.output2 = tkinter.Entry(self, width=150, bd=0,)
self.output2.grid(column=0, row=8, columnspan=5, padx=100, pady=0)
self.output3 = tkinter.Entry(self, width=150, bd=0,)
self.output3.grid(column=0, row=9, columnspan=5, padx=100, pady=0)
self.output4 = tkinter.Entry(self, width=150, bd=0,)
self.output4.grid(column=0, row=10, columnspan=5, padx=100, pady=0)
if __name__ == '__main__':
root = tkinter.Tk()
Adder(root)
root.resizable(width=False, height=False) # locks window from being resized
root.mainloop()