0

So I'm trying to create some sort of email log system with the subject and message previewed on each line, like gmail.

In mainWindowScript.py, I have a 'compose' button that appends a string to an array in getLogs.py, and a 'logs' button that runs getLogs.py using the os module. In getLogs.py, I just have a ListBox. I used tkinter to create buttons and listboxes.

When I run mainWindowScript.py, it first opens the listbox created in getLogs.py which isn't supposed to happen. But the weird part is when I close that window and click my 'compose' button, the list I tried to append to is still empty, making the listbox empty.

It's really confusing I need help.

Here is mainWindowScript.py:

import tkinter as tk
from tkinter import ttk
import os

import getLogs as gl

mainWin = tk.Tk()

canvas = tk.Canvas(mainWin, width = 400, height = 400)
canvas.pack()

frame = tk.Frame(mainWin, bg = "gray")
frame.place(relx = 0, rely = 0, relwidth = 1, relheight = 1)


def compose():
    gl.tos.append("isybgf")
    #os.system("python email_gui.py")            #run another python file


def getEmailLogs():
    os.system("python getLogs.py")


composeButton = tk.Button(frame, bg = "blue", fg = "white", text = "COMPOSE", command = compose)
composeButton.place(relx = 0.3, rely = 0.2, relwidth = 0.4, relheight = 0.2)

logsButton = tk.Button(frame, bg = "blue", fg = "white", text = "LOGS", command = getEmailLogs)
logsButton.place(relx = 0.3, rely = 0.5, relwidth = 0.4, relheight = 0.2)

mainWin.mainloop()

And getLogs.py:

import tkinter as tk

mainWind = tk.Tk()

canvas = tk.Canvas(mainWind, width = 400, height = 600)
canvas.pack()

frame = tk.Frame(mainWind, bg = "gray")
frame.place(relx = 0, rely = 0, relwidth = 1, relheight = 1)

mailLogs = tk.Listbox(frame)
mailLogs.place(relx = 0.1, rely = 0.05, relwidth = 0.8, relheight = 0.9)

tos = []
subjects = []
messages = []

print(tos)

mails = {
    "to:": tos,
    "subject:": subjects,
    "message:": messages
}

for i in range(0, len(tos)):
    emailLogTitle = "{}: {} - {}".format(mails["to:"][i], mails["subject:"][i], mails["message:"][i])
    mailLogs.insert('end', emailLogTitle)

mainWind.mainloop()
iraj jelodari
  • 3,118
  • 3
  • 35
  • 45
  • put code in fuctions and run functions after import it. Using `os.system("python getLogs.py")` you run separated program which know nothing about list `tos` which you created in `mainWindowScript` - it starts with own empty list `tos` and has no access to data create in `mainWindowScript.py`. – furas Feb 18 '20 at 18:07
  • 1
    BTW: when you import `import getLogs as gl` then you automatically run code from `getLogs.py` so you see it at start. If you put code in function(s) then it will not run it at start and you may run it as `gl.function()` when you press button - without using `os.system()` – furas Feb 18 '20 at 18:10
  • if you want to run it as `os.system("python getLogs.py")` then you would have to save data from `tos` in file and `getLogs.py` would have to read these data from file. – furas Feb 18 '20 at 18:14
  • 1
    Read up on [Modules](https://docs.python.org/3/tutorial/modules.html#modules), [Why are multiple instances of Tk discouraged?](https://stackoverflow.com/questions/48045401/why-are-multiple-instances-of-tk-discouraged) and [Tkinter understanding mainloop](https://stackoverflow.com/questions/29158220/tkinter-understanding-mainloop) – stovfl Feb 18 '20 at 18:48

1 Answers1

0

Using os.system() you run separated program which has no access to data create in current program. Because you import getLogs so you should put code in function to execute it without os.system()

getLogs.py

import tkinter as tk

tos = []
subjects = []
messages = []

def log_window():

    #mainWind = tk.Tk()
    mainWind = tk.Toplevel()

    canvas = tk.Canvas(mainWind, width = 400, height = 600)
    canvas.pack()

    frame = tk.Frame(mainWind, bg = "gray")
    frame.place(relx = 0, rely = 0, relwidth = 1, relheight = 1)

    mailLogs = tk.Listbox(frame)
    mailLogs.place(relx = 0.1, rely = 0.05, relwidth = 0.8, relheight = 0.9)

    print(tos)

    mails = {
        "to:": tos,
        "subject:": subjects,
        "message:": messages
    }

    for i in range(0, len(tos)):
        emailLogTitle = "{}: {} - {}".format(mails["to:"][i], mails["subject:"][i], mails["message:"][i])
        mailLogs.insert('end', emailLogTitle)

    #mainWind.mainloop()

And now you can execute it

def getEmailLogs():
    gl.log_window()

and it will have access to values in tos


Because both windows run in the same program so second doesn't need mainloop() and it should be created by Toplevel(), not Tk()


BTW: composer was adding only tos so later dictionary mail was no subjects and messages. You could rather create one list with mails instead of separated list for to, subject, message


mai.py

import tkinter as tk
import os

import getLogs as gl

# --- functions ---

def compose():
    gl.tos.append("isybgf")
    gl.subjects.append("isybgf")
    gl.messages.append("isybgf")
    # it could be better to keep it in one list ie.
    # mails.append( {'to': "isybgf", 'subject': "isybgf", 'message': "isybgf" } )

def getEmailLogs():
    gl.log_window()

# --- main ---

mainWin = tk.Tk()

canvas = tk.Canvas(mainWin, width=400, height=400)
canvas.pack()

frame = tk.Frame(mainWin, bg="gray")
frame.place(relx = 0, rely = 0, relwidth = 1, relheight = 1)

composeButton = tk.Button(frame, bg="blue", fg="white", text="COMPOSE", command=compose)
composeButton.place(relx=0.3, rely=0.2, relwidth=0.4, relheight=0.2)

logsButton = tk.Button(frame, bg="blue", fg="white", text="LOGS", command=getEmailLogs)
logsButton.place(relx=0.3, rely=0.5, relwidth=0.4, relheight=0.2)

mainWin.mainloop()

EDIT: Version with other changes - reduced to important elements. I keep mails on one list mails in main program and send to log as argument.

main.py

import tkinter as tk
import getLogs as gl

# --- functions ---

def compose():
    mails.append( {'to': "user@domain.com", 'subject': "Read it", 'message': "Hello World!"} )

def get_email_logs():
    gl.log_window(mails)

# --- main --- (lower_case_names)

mails = []

main_window = tk.Tk()

compose_button = tk.Button(main_window, text="COMPOSE", command=compose)
compose_button.pack(fill='x')

logs_button = tk.Button(main_window, text="LOGS", command=get_email_logs)
logs_button.pack(fill='x')

close_button = tk.Button(main_window, text="CLOSE", command=main_window.destroy)
close_button.pack(fill='x')

main_window.mainloop()

getLogs.py

import tkinter as tk

def log_window(mails):

    window = tk.Toplevel()

    mail_logs = tk.Listbox(window)
    mail_logs.pack(fill='both', expand=True)

    close_button = tk.Button(window, text="CLOSE", command=window.destroy)
    close_button.pack(fill='x')

    for item in mails:
        mail_logs.insert('end', "{}: {} - {}".format( item["to"], item["subject"], item["message"] ))
furas
  • 134,197
  • 12
  • 106
  • 148