So when I am calling the list directory code below directly then it's working fine. But when I am calling main.py which uses app class from gui which calls the list directory function, It prints "yoo" but prints an empty list instead of list of directories. I am stuck and can't figure out why that's happening. Any ideas?
Outputs:
When list directory called directly :
["/home/shubham/Desktop/movies/djangounchained.mkv"]
"yoo"
When called by main.py with same argument:
[]
"yoo"
Here is my main script
from gui import app
from list_directory import display_files
import tkinter as tk
root = tk.Tk()
directory = input("Enter directory name:")
root.geometry("400x300")
widgets_creator = app(root)
name = "get list"
directory_button = widgets_creator.create_button(name,function=display_files,path=directory)
root.mainloop()
Here is my gui script
import tkinter as tk
class app(tk.Frame):
def __init__(self,master):
super(app,self).__init__(master=master)
self.master = master
self.init_window()
def init_window(self):
# changing the title of our master widget
self.master.title("GUI")
# allowing the widget to take the full space of the root window
self.pack(fill=tk.BOTH, expand=1)
# creating a button instance
quitButton = tk.Button(self, text="Quit")
# placing the button on my window
quitButton.place(x=0, y=0)
def create_button(self,button_name,function,path):
button = tk.Button(self.master,text=button_name,command=lambda: function(path))
button.place(x=200,y=5)
return button
Here is my list_directory code:
import glob
def display_files(path):
x = glob.glob(path)
print(x)
print("yoo")
if __name__ == '__main__':
display_files("/home/shubham/Desktop/movies/*")
I might have found your problem. The code works fine, the problem is your argument. For example, if I enter '/Users/rudy/Desktop/*' when the input prompt comes up, I have the same result as you.
However, when I enter /Users/rudy/Desktop/* (without quotes), everything works fine. input() already saves the input as a string, so you don't need to add additional quotes.
Related
I have this script where I initialize a tkinter object with some labels, entries, and buttons with commands. when I run the script, the init function executes fine and the instance of the tkinter window gets spawned and the buttons work just fine. The problem is that, the logic after the init function does not get executed and the tkinter window stays looping for ever unless I hit the exit button and then it just finishes the script. I want to be able to use the inputs from the tkinter.Entry() and the tkinter.filedialog.askopenfilename() functions to do more stuff later in the application such as loading an excel sheet based on the path passed on the askopenfilename() sections but I can't get it to continue.
Note: I am new to using classes so I believe my mistake is somewhere in the way I am laying down the building blocks of the instance itself. Also, while putting this scrip together so many other questions arised and it has been very hard to find concise answers online. I will post some of those questions here in case someone wants to answer them (not needed though)
1- Do I need to declare every single new variable that come in new methods of the class in the init function, if so, why? I just did it here because pycharm game me warning every time I did not do it but not sure what is the reason behind it.
2- When calling a variable on a new method within the class, and the variable is already defined in the init fucntion, do I need to include the variable in the arguments section of the method? if so, do I add the variable with the self argument or not?
import pandas as pd
from openpyxl import load_workbook
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter.messagebox import showinfo
from datetime import datetime
import openpyxl
class App(tk.Tk):
def __init__(self):
super().__init__()
# Define parameters
self.current_PR_report = ""
self.new_PR_report = ""
self.path = ""
self.raw_excel = None
self.new_report = None
self.current_report = ""
# Configure the root window
self.title("PR Reader")
self.geometry('250x200')
# Label
self.label = ttk.Label(self, text="Merge Problem Reports!")
self.label.pack()
# Date Label and Entry
self.date_label = tk.Label(self, text="Enter Date (MM-DD-YYYY)")
self.date_label.pack()
self.date_label_entry = tk.Entry(self)
self.date_label_entry.pack()
# Run button
self.button = ttk.Button(self, text="Run", command=self.select_file)
self.button.pack()
# Button for closing
self.exit_button = tk.Button(self, text="Exit", command=self.destroy)
self.exit_button.pack(pady=20)
# Bring Dialog box to obtain Excel files paths
def select_file(self):
self.current_PR_report = filedialog.askopenfilename(
title="Select Current PR Report",
initialdir="some path",
filetypes=[("Excel Files", "*.xlsx")])
self.new_PR_report = filedialog.askopenfilename(
title="Select New PR Report",
initialdir="some path",
filetypes=[("Excel Files", "*.xlsx")])
# Load the spreadsheets
self.new_report = self.read_excel_report(self.new_PR_report)
self.current_report = self.read_excel_report(self.current_PR_report)
# Define function to load Excel data
def read_excel_report(self, path):
try:
# sheet_name=None indicates you want a dictionary of data frames, each item in the dictionary
# representing a different worksheet.
self.raw_excel = pd.read_excel(path, sheet_name=-1, engine='openpyxl')
self.raw_excel = self.raw_excel.fillna('')
print("data extracted")
return self.raw_excel
except Exception as e:
print(e)
if __name__ == "__main__":
app = App()
app.mainloop()
My main issue is that after running the script my other methods were not getting executed. I learned that I not only need to define the methods on my class but also need to call them inside of it. I this case, I had to call them inside the logic of the "select_file" method since it is the method called when the "Run" button gets called.
I am wondering if there is a way, in tkinter or using any other python module, to make it so you keep a label or any other element in every window made by just using something like a function that makes the label within the window? I've tried this:
#Modules
import tkinter as tkin
#The initializer window
class Test:
def __init__(self):
#Initializes the main window
self.start = tkin.Tk()
self.start.title('Test')
self.label_thing()
#Makes a label
def label_thing(self):
self.label1 = tkin.Label(text='Not Button')
self.label1.pack()
I don't know if I made any errors or if this isn't a thing you can do but I'd also like to refrain from having the label localized to this window and having to remake the code for every window.
Let us assume you have a button that creates windows, you would pass this window as an argument to the function that creates the label, so like:
import tkinter as tk # Fixed weird import naming
class Test:
def __init__(self):
self.start = tk.Tk()
self.start.title('Test')
self.label_thing(self.start) # Label on the main window
tk.Button(self.start,text='Click me',command=self.create_win).pack()
self.start.mainloop()
def label_thing(self, master):
self.label1 = tk.Label(master, text='Not Button')
self.label1.pack()
def create_win(self):
new = tk.Toplevel()
self.label_thing(new) # Label on the new window
if __name__ == '__main__':
Test()
As you can see, as long as you press the button, new windows are created, and all those windows have the label on them, dynamically.
I have little python programs to create html, for example insertMedia.py: this takes the name of the media file, puts it in the html code string and writes it to the output file.
insertMedia.py uses tkinter. I have a window with the buttons "insert audio" and 'insert video".
insertMedia.py works well, no problems. Also, I have some more "makehtml" programs, each for a specific task.
I want to have a master window, with buttons, or maybe a menu item for each "makehtml" program.
How can I open and run insertMedia.py from a master window?
Should I put all the "makehtml" programs in a module and import the module?
This code from Bryan Oakley, here in stackoverflow, opens a new window. Can it be modified to open my insertMedia.py?
import Tkinter as tk
def create_window():
window = tk.Toplevel(root)
root = tk.Tk()
b = tk.Button(root, text="Create new window", command=create_window)
b.pack()
root.mainloop()
To show you just the priciple of a common way to do this.
Frist you create a main file with your stuff in main.py wich looks like for exampel:
main.py
import tkinter as tk
import Mod1
root = tk.Tk()
def callback():
m1 = Mod1.Model(root, var='my_html')
b = tk.Button(text='click me', command=callback)
b.grid(column=0,row=1)
root.mainloop()
Then you are creating another script with your Toplevel and stuff in it like this:
Mod1.py
from __main__ import tk
class Model(tk.Toplevel):
def __init__(self, master, var=None):
tk.Toplevel.__init__(self, master)
self.master = master
self.configure(bg="red", width=300, height=300)
b=tk.Button(self,text='print html', command=lambda:print(var))
b.pack()
So what I did here is to create another script with a class with the parent class tk.Toplevel. This means the class becomes a subclass of it. We pass the parameter master wich is root, as you can see in the main.py to get a reference through the interface.
Also note that we imported the Mod1 script and later we reference the Model by Mod1.Model(). You could just import the Model with from Mod1 import Model instead of import Mod1. Also we imported from the main script the reference of tk to work with.
To pass a variabel like a string of your html, you can pass var through the interface. I made it like a kwarg(keyword argument), to make it necessary for the class to initialize you have to delete =None wich is a default vaulue.
Thats all we need to work it out. Have fun!
For more complex stuff you also could do a dictionary with keys and values.
main.py
import tkinter as tk
import Mod1
root = tk.Tk()
def callback():
data_dict = {'key a':'value a','key b':'value b'}
m1 = Mod1.Model(root, dct= data_dict)
b = tk.Button(text='click me', command=callback)
b.grid(column=0,row=1)
root.mainloop()
and Mod1.py
from __main__ import tk
class Model(tk.Toplevel):
def __init__(self, master, dct=None):
tk.Toplevel.__init__(self, master)
self.master = master
self.configure(bg="red", width=300, height=300)
b=tk.Button(self,text='print html', command=lambda:print(dct['key a']))
b.pack()
i have a two python scripts with two classes. How do i display a widget which exists in the second script to the a frame in the first script for example
I have the main script where i have my frames in the first script. in the second script(Toplevel) i ran some functions to perform some tasks. after the tasks are performed, the results are written to the database.
while the tasks are running, i wanted a progress bar to be displayed in the Main so that after the tasks is finished then the progress bar can stop.
the challenge is the condition used to start and stop the progressbar occurs in the second script. but i want the progressbar to be displayed in the main
from tkinter import *
from tkinter import ttk
#import script2
class Main(object):
def __init__(self,master):
self.master = master
#main frames
self.mainFrame = Frame(self.master)
self.mainFrame.pack()
self.topFrame= Frame(self.mainFrame,width=200,height =150, bg="#f8f8f8",padx =20, relief =SUNKEN,
borderwidth=2)
self.topFrame.pack(side=TOP,fill = X)
self.btnseldate = Button(self.topFrame, text="open script2", font="arial 12 bold")
self.btnseldate.configure(compound=LEFT, command=self.sc)
self.btnseldate.pack()
def sc(self):
s = script2.class2(self.master,self.mainFrame)
def main():
root =Tk()
app = Main(root)
root.title("two variables")
root.geometry("200x200+350+200")
root.mainloop()
if __name__=="__main__":
main()
this is the second script
####In the second script titled "script2.py"
from tkinter import *
from tkinter import ttk
class class2(Toplevel):
def __init__(self,parent, mainFrame):
Toplevel.__init__(self)
self.geometry("200x200+350+200")
self.title("display")
#object1 = script1.Main()
#self.script1Frame = object1.topFrame()
##this button should be displayed just under the first button in script 1
self.progbar = ttk.Progressbar(self.topFrame, orient=HORIZONTAL, length=200)
self.progbar.pack()
self.progbar.config(mode='determinate')
self.progbar.start()
self.self.topFrame.pack()
#this is a dummy function just to describe what i have
def funcdotask():
#this function contains so many local variables that are only known in
#this script
pass
so the widget actually depends on a condition in the second script , thats why i didn't just place it in the first script.
i need ideas on even how i inherit variables from script2 to script 1 for example
or if there is a way i can get the results from the performed function in script 1(Main). it could help
I tried to make a module in which I made a funtion which just reads and display the image in GUI. Then I made another module which makes call to that function when the button is clicked. Button gives me error.
#module code:
from tkinter import *
class disp:
def __init__(self):
root1.geometry("400x500")
image = PhotoImage(file = 'png2.png')
Label(root1,image=image).pack()
root1.mainloop()
#main code:
from tkinter import *
import testimg as ti
def click():
ti.disp()
root = Tk()
Button(text = 'Click me',command=click).pack()
root.mainloop()
In your class disp, you have put the master as root1 whereas in the main code, you have defined Tk() as root. This means that root1 is no window so the label that has a master of root1 has no where to pack itself.
You also need to remove root1.mainloop() because it’s useless and causing errors due to the fact that root1 doesn’t have Tk(). It’s like trying to loop a while statement without typing in while. This gives an error.
Below modified code is based on yours:
#module code:
from tkinter import *
class disp:
def __init__(self):
root1 = Tk()
root1.geometry("400x500")
image = PhotoImage(master=root1, file='png2.png') # set master to root1
Label(root1, image=image).pack()
root1.mainloop()
But using multiple Tk() instances is not a good design.