简体   繁体   中英

How to import an instance of a class from a module only if it exists

The project i am working on is tower defence level editor. I think for this question, it's important to understand the structure.So basically, we can have many projects and each project can hold many towers. I am making GUI, specifically sliders. I want to load the values the sliders were holding when the user last quit the program. For this, the values are stored in a text file. For loading the towers, i have a class.

class Workspace:
    def __init__(self):
        t = file.loadtowers(project.getprojectname())
        for tower in t:
            if tower.name == project.tower:
                self.speedslider = Slider([990, 10], text="Attack Speed/ s", start=int(tower.attackspeed), factor=40)
                self.damageslider = Slider([990, 50], text="Attack Damage", start=int(tower.damage))
                self.radiusslider = Slider([990, 90], text="Range Radius", start=int(tower.radius))
                self.levelslider = Slider([990, 130], text="Max Level", start=int(tower.max), factor=5)
                step = literal_eval(tower.step)
                self.step = [TickBox(text="Damage", value=step[0]), TickBox(text="Range", value=step[1])
                             , TickBox(text="Attack speed", value=step[2])]
                stepupby = literal_eval(tower.stepupby)
                self.damagestep = Slider([990, 340], text="Attack Damage", start=int(stepupby[0]))
                self.radiusstep = Slider([990, 380], text="Range Radius", start=int(stepupby[1]))
                self.attackspeed = Slider([990, 420], text="Attack Speed", start=int(stepupby[2]))
                self.chooseimage = RectButton(text="Choose Image", border=True)
                self.savebutton = RectButton(text="Save", border=True)

I want to load the values when instantiating the class, because i only want to load the values once and let the user change them afterwards. But, my problem is i can only instantiate the class after the user chooses the tower because i need to know what tower the user wants to work on.

def openproject(self):
        for b in self.buttons:
            if b.clicked():
                project.settower(b.text)
                global towerworkspace
                towerworkspace = Workspace()
                state.active = "tower workspace"

But now, i get an import error in main.py because towerworkspace only gets defined when openproject runs. So how would i get around this problem? Using a function would make everything much simpler, but i cant think of a way to only load values once, since the function would have to be in a loop. Only importing towerworkspace after its created would be ideal but i dont know how to do that. Thanks for helping

main.py

import pygame
import sys
from time import time
from home import home
from createproject import createproject, existingprojects
from towerworkspace import towerhome, towerworkspace

from GUI import popup
from States import state


class Editor:
    def __init__(self, winWidth, winHeight):
        self.win = pygame.display 

        self.display = self.win.set_mode((winWidth, winHeight)) #Initialize the pygame window with given size
        self.win.set_caption("A Level computer science project - Level Editor") #Set title for the window


editor = Editor(1200, 600)# Instantiation of Editor class with values 1200, 600 which is used as the screen size

# This function accepts event queue from the operating system as an argument and if one of those events is pygame.QUIT it exits the program.
def handleExit(events):
    for e in events:
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

def render():
    editor.display.fill((100, 100, 100)) # Fills the window with a grey-ish color every frame, which is the background
    if state.active == "create project":
        createproject.render(editor.display)
        existingprojects.render(editor.display)
    if state.active == "home":
        home.render(editor.display)
    if state.active == "tower home":
        towerhome.render(editor.display)
    if state.active == "tower workspace":
        towerworkspace.render(editor.display)

    popup.popup(editor.display)
    

def logic(events, window):        
    if state.active == "create project":
        createproject.logic(events, window)
        createproject.feedevents(events)
        existingprojects.logic(events)
        existingprojects.refresh()
    if state.active == "home":
        home.logic()
    if state.active == "tower home":
        towerhome.feedevents(events)
        towerhome.logic(events)
        towerhome.openproject()
        towerhome.refresh()
    if state.active == "tower workspace":
        towerworkspace.feedevents(events)
        towerworkspace.updatevalues(events)
    popup.handleactive()
 

# The application loop
while True:
    events = pygame.event.get() #  Request event queue from the operating system
    popup.handleactive()
    handleExit(events)
    render()
    logic(events, editor.display)
    editor.win.flip()

Error:

 ImportError: cannot import name 'towerworkspace' from 'towerworkspace' 

Remove towerworkspace from import on top and use it after user clicks like this:

    if state.active == "tower workspace":
        from towerworkspace import towerworkspace
        towerworkspace.feedevents(events)
        towerworkspace.updatevalues(events)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM