0

I am writing a large program, and I would like to break out functional chunks into other modules to make coding & maintenance easier.


main.py


#  Call Schedule Program -- v0.1a
#  Here we go ..

import tkinter as tk
import tkinter.font as font

from reporting import *             # bring in the stuff from reporting.py


def center_window_on_screen():
# This centres the window when it is not maximised.

    x_cord = int((screen_width / 2) - (width / 2))
    y_cord = int((screen_height / 2) - (height / 2))
    root.geometry(f"{width}x{height}+{x_cord}+{y_cord}")

<<snip!>>

def change_main_to_report():
# changes from main frame to schedule management frame

    reporting_frame.pack(fill='both', expand=1)
    main_frame.forget()


def change_report_to_main():
# changes from schedule management frame back to main frame
    main_frame.pack(fill='both', expand=1)
    reporting_frame.forget()

<<snip!>>

# ---------------< Begin the real work >---------------
# Let's set up the window ...

root = tk.Tk()
root.title("The Dreaded Call Schedule v0.1a")
root.configure(bg='lightyellow')

width, height = 800, 600
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
center_window_on_screen()

# Here, we create frames which we will swap between 
main_frame = tk.Canvas(root, width=800, height=600)
file_maint_frame = tk.Canvas(root, width=800, height=600)
phys_maint_frame = tk.Canvas(root, width=800, height=600)
reporting_frame = tk.Canvas(root, width=800, height=600)        # setup reporting frame

# Let's create the fonts that we need.
font_large = font.Font(family='Candara',
                       size=24,
                       weight='bold')
font_small = font.Font(family='Candara',
                       size=12)

# ---------------< Main Frame >---------------
# The widgets needed for the Main frame.
# First, let's display the logo.

<<snip!>>

# ---------------< Reporting Frame >---------------
# The widgets needed for the File Maintenance frame.

setup_reporting_frame()         # this code got moved into reporting.py (below)


# ---------------< Open and Read data files >---------------

# Open the files and set those up
#  Physician, Special Characters, Calendar, Main Schedule

<<snip!>>


# ---------------< Main Routine >---------------
# 

main_frame.pack(fill='both', expand=1)

root.mainloop()

And below is Reporting.py


reporting.py


# ---------------< Reporting Frame >---------------
# The widgets needed for the reporting frame.

def setup_reporting_frame():

    reporting_frame = tk.Canvas(root, width=800, height=600)

    img_logo_report = tk.PhotoImage(file='logo.png')
    lbl_logo_report = tk.Label(reporting_frame, image=img_logo_report)
    lbl_logo_report.place(x=680, y=8)

# add a heading.
    lbl_heading_report = tk.Label(reporting_frame,
                            text='Reporting Menu',
                            font=font_large)
    lbl_heading_report.place(x=150, y=100)

# button for main availability
    btn_change_report_to_main_avail_rpt = tk.Button(reporting_frame,
                               font=font_small,
                               text='Main Availability',
                               command=change_report_to_main_avail_rpt)
    btn_change_report_to_main_avail_rpt.place(x=150, y=200)

# button for surgical avail
    btn_change_report_to_sx_avail_rpt = tk.Button(reporting_frame,
                               font=font_small,
                               text='Surgical Availability',
                               command=change_report_to_sx_avail_rpt)
    btn_change_report_to_sx_avail_rpt.place(x=350, y=200)

# button to generate main schedule
    btn_change_report_to_main_sched_rpt = tk.Button(reporting_frame,
                               font=font_small,
                               text='Main Call Schedule',
                               command=change_report_to_main_sched_rpt)
    btn_change_report_to_main_sched_rpt.place(x=150, y=250)

# button to generate surgical schedule
    btn_change_report_to_sx_sched_rpt = tk.Button(reporting_frame,
                               font=font_small,
                               text='Surgical Schedule',
                               command=change_report_to_sx_sched_rpt)
    btn_change_report_to_sx_sched_rpt.place(x=350, y=250)

# button to swap back to the main frame.
    btn_change_to_main = tk.Button(reporting_frame,
                               font=font_small,
                               text='Exit',
                               command=change_report_to_main)
    btn_change_to_main.place(x=150, y=350)

    reporting_frame.create_line(750, 300, 700, 400, width=3, fill='aqua')

When I try running this, I get an error saying that tkinter isn't defined. If I put in a definition for tk, the error moves to saying 'reporting_frame' isn't defined. After that it moves to the fonts and so on.

I have browsed around and found similar solutions, but they invariably lead to defining things as a Class. I honestly don't see how this lends itself to being defined as a class.

What I'm looking for is how to set this up so that I have the Main, and I include a bunch of other modules. I suspect I'm missing something basic here, but I don't see it. I was under the impression that the files would be compiled, and then the linker would resolve name problems.

For reference, I'm using the latest version of Python, and PyCharm v2021.3

If anyone can help, that would be greatly appreciated.

Thanks muchly.

thomas

ThomasL
  • 1
  • 1
  • 2
    Python is quite different from something like C or C++. I don't know very much about compiled languages like that, but Python doesn't have a linker. Any file that needs to use a name needs to import it. And importing in Python *doesn't* effectively just paste it into the current file, the way `include` would. (I would type up a more complete answer but I'm not at a computer.) – CrazyChucky Jul 05 '22 at 16:57
  • 1
    It looks like you have circular dependencies. I don't have much experience with it myself, but FWIW, there are existing questions, like this: [Circular dependency in Python](/q/894864/4518341) – wjandrea Jul 05 '22 at 17:02
  • One issue is that you have variables called in methods which haven't been declared yet which is why you're getting that error. – Alias Cartellano Jul 05 '22 at 17:26
  • So, what I'm hearing people saying is that either I resign myself to writing something that will likely evolve to 10,000 lines of python code in one file, or I switch languages to something like C++ .. – ThomasL Jul 06 '22 at 20:43
  • Not at all. Large Python projects are absolutely split across multiple files all the time. You just have to learn how importing works, which is different than you may be used to if you've used statically linked languages before. Maybe try a [tutorial](https://realpython.com/python-modules-packages/) first? – CrazyChucky Jul 06 '22 at 21:44
  • P.S. Looking more at your code, it seems like you could also use an introduction to [scoping](https://realpython.com/python-scope-legb-rule/). Names defined inside functions aren't, by default, available outside of those functions. You need to `return` something, or modify a mutable object, or use global variables (not usually a good idea)... This isn't an impediment to organizing larger projects, it's practically a necessity for it. In my opinion, you probably do want classes, at this point, but there are other ways to go about it. – CrazyChucky Jul 07 '22 at 03:02

0 Answers0