Imagine that i have a tkinter application with three buttons TestA, TestB, TestC which when pressed show the message "Test Status: Running Test A" (or ...B, ...C) and for some reason i want to create a second script from where when pressed these buttons, three functions of the other script would be called which among many other things that will have to do, at the end should update the config bar of the first (tkinter) script. How could this be achieved, as at any trial i receive errors like the following "AttributeError: module 'testsUnit' has no attribute 'runTestA'"
Here they follow the code for the above described question
First the tkinter gui with no second script which works perfect (Name of script gui_trial.py) (functions runTestA|B|C)
from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import time
#Constants
GUI_WIDTH = 300
GUI_HEIGHT = 200
def powerOn():
statusBar.config(text='Test Status: powerOn')
def powerOff():
statusBar.config(text='Test Status: powerOff')
def shutdown():
statusBar.config(text='Test Status: shutDown')
def runTestA():
statusBar.config(text='Test Status: Running Test A')
def runTestB():
statusBar.config(text='Test Status: Running Test B')
def runTestC():
statusBar.config(text='Test Status: Running Test C')
master = Tk()
gui_resolution = str(GUI_WIDTH) 'x' str(GUI_HEIGHT) ' 0 0'
master.geometry(gui_resolution)
master.title("Trial GUI")
powerOnButton = Button(master, text="Power On", command=powerOn)
powerOnButton.grid(column=1, row=1, pady=5, ipadx=12)
powerOffButton = Button(master, text="Power Off", command=powerOff)
powerOffButton.grid(column=1, row=2, pady=5, ipadx=12)
newTestButton = Button(master, text="Shutdown", command=shutdown) # showPassTestResult)
newTestButton.grid(column=1, row=3, pady=5, ipadx=12)
testAButton = Button(master, text="Test A", command=runTestA)
testAButton.grid(column=2, row=1, pady=5, ipadx=12)
testBButton = Button(master, text="Test B", command=runTestB)
testBButton.grid(column=2, row=2, pady=5, ipadx=12)
testCButton = Button(master, text="Test C", command=runTestC)
testCButton.grid(column=2, row=3, pady=5, ipadx=12)
statusBar = Label(master, width=25, relief=SUNKEN, text='Test Status: IDLE')
statusBar.grid(column=1, row=4, sticky=SW, padx=10, pady=20)
master.mainloop()
Then the first script again modified for calling a second one (functions runGuiTestA|B|C)
from tkinter import *
from tkinter import ttk
import testsUnit
#Constants
GUI_WIDTH = 300
GUI_HEIGHT = 200
def powerOn():
statusBar.config(text='Test Status: powerOn')
def powerOff():
statusBar.config(text='Test Status: powerOff')
def shutdown():
statusBar.config(text='Test Status: shutDown')
def runGuiTestA():
#statusBar.config(text='Test Status: Running Test A')
testsUnit.runTestA()
def runGuiTestB():
#statusBar.config(text='Test Status: Running Test B')
testsUnit.runTestB()
def runGuiTestC():
#statusBar.config(text='Test Status: Running Test C')
testsUnit.runTestC()
master = Tk()
gui_resolution = str(GUI_WIDTH) 'x' str(GUI_HEIGHT) ' 0 0'
master.geometry(gui_resolution)
#master.resizable(FALSE, FALSE)
master.title("Trial GUI")
powerOnButton = Button(master, text="Power On", command=powerOn)
powerOnButton.grid(column=1, row=1, pady=5, ipadx=12)
powerOffButton = Button(master, text="Power Off", command=powerOff)
powerOffButton.grid(column=1, row=2, pady=5, ipadx=12)
newTestButton = Button(master, text="Shutdown", command=shutdown) # showPassTestResult)
newTestButton.grid(column=1, row=3, pady=5, ipadx=12)
testAButton = Button(master, text="Test A", command=runGuiTestA)
testAButton.grid(column=2, row=1, pady=5, ipadx=12)
testBButton = Button(master, text="Test B", command=runGuiTestB)
testBButton.grid(column=2, row=2, pady=5, ipadx=12)
testCButton = Button(master, text="Test C", command=runGuiTestC)
testCButton.grid(column=2, row=3, pady=5, ipadx=12)
statusBar = Label(master, width=25, relief=SUNKEN, text='Test Status: IDLE')
statusBar.grid(column=1, row=4, sticky=SW, padx=10, pady=20)
master.mainloop()
and the second one named testsUnit.py (functions here runTestA|B|C)
import gui_trial
def runTestA():
gui_trial.statusBar.config(text='Test Status: Running Test A')
def runTestB():
gui_trial.statusBar.config(text='Test Status: Running Test B')
def runTestC():
gui_trial.statusBar.config(text='Test Status: Running Test C')
CodePudding user response:
There is circular import issue. Better design is to pass statusBar
as an argument of those functions in testsUnity.py
:
# no need to import gui_trial
#import gui_trial
def runTestA(statusBar):
statusBar.config(text='Test Status: Running Test A')
def runTestB(statusBar):
statusBar.config(text='Test Status: Running Test B')
def runTestC(statusBar):
statusBar.config(text='Test Status: Running Test C')
Then modify gui_trial.py
to pass statusBar
to the above functions when they are executed:
...
def runGuiTestA():
#statusBar.config(text='Test Status: Running Test A')
testsUnit.runTestA(statusBar) # pass statusBar as an argument
def runGuiTestB():
#statusBar.config(text='Test Status: Running Test B')
testsUnit.runTestB(statusBar)
def runGuiTestC():
#statusBar.config(text='Test Status: Running Test C')
testsUnit.runTestC(statusBar)
...