How to override this problem?

Hello
This thing is driving me crazy for 8 days now
All I want is to have a message show inside of a timer app like this

import bpy 

def ShowMessageBox(message = "", title = "Message Box", icon = 'INFO'): #Message function
    def draw(self, context):
        self.layout.label(text=message)
    bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)

def every_X_seconds_word():
    ShowMessageBox("Hello World", "Many Crash" ,"BLENDER")
    return 5.0
bpy.app.timers.register(every_X_seconds_word)

Unfortunately timer apps don’t allow for certain type of context.

I already have some solutions to override other situations, but I’m struggling to adapt thoses solutions to my case.
i found answers like this one or thoses below

Any people to help ?

Might be something special about context.window_manager.popup_menu that makes it rely on the context it was executed in. But yeah, it’s really buggy.

Here’s an example that uses bpy.ops and calls a panel, but you can probably call a menu, too.

import bpy


class POPUP_PT_SimplePopup(bpy.types.Panel):
    bl_label = "Popup every N secs"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout
        layout.label(text="Message")

    @staticmethod
    def every_n_sec(C_dict, times=4, interval=2):

        if times > 0:
            bpy.ops.wm.call_panel(C_dict,
                name='POPUP_PT_SimplePopoup')
            
            bpy.app.timers.register(
                lambda: __class__.every_n_sec(C_dict, times - 1),
                first_interval=interval)


def register():
    bpy.utils.register_class(POPUP_PT_SimplePopup)

def unregister():
    bpy.utils.unregister_class(POPUP_PT_SimplePopup)


if __name__ == "__main__":
    register()

    # pass context dict to the function so bpy.ops works in timer
    C_dict = bpy.context.copy()

    bpy.app.timers.register(
        lambda: POPUP_PT_SimplePopup.every_n_sec(C_dict))
1 Like

thanks it is working fine even with menus


import bpy
from bpy.types import Menu


class VIEW3D_MT_ScriptLauncher(Menu):
    bl_label = "Save Your File?"
    bl_idname = "OBJECT_MT_fc_main_menulaunchscript" #other id if two pies 

    def draw(self, context):
        layoutT = self.layout
        layoutT.label(text="30 minutes passed witouth any saves", icon='COLORSET_02_VEC')
        layoutT.label(text=" ")
        layoutT.separator()
        col = self.layout.column(align=False)
        col.label(text=" Quick save ")
        col.label(text=" Quick save as ")
        col.label(text=" Quick save as copy ")
        col.label(text=" Quick save as new version ")
        col.separator()
        col.label(text=" Don't ask anymore ")
        col.label(text=" No ")
        
    @staticmethod
    def every_n_sec(C_dict, times=10, interval=10):
        if times > 0:
            bpy.ops.wm.call_menu(C_dict,
                name='OBJECT_MT_fc_main_menulaunchscript')

            bpy.app.timers.register(
                lambda: __class__.every_n_sec(C_dict, times - 1),
                first_interval=interval)


def register():
    bpy.utils.register_class(VIEW3D_MT_ScriptLauncher)

def unregister():
    bpy.utils.unregister_class(VIEW3D_MT_ScriptLauncher)



if __name__ == "__main__":
    register()
    
    # pass context dict to the function so bpy.ops works in timer
    C_dict = bpy.context.copy()


    bpy.app.timers.register(
        lambda: VIEW3D_MT_ScriptLauncher.every_n_sec(C_dict))
        
        
#bpy.app.timers.register(every_n_sec, first_interval=50)
#bpy.ops.wm.call_menu(C_dict,name='OBJECT_MT_fc_main_menulaunchscript')

bpy.ops.wm.call_menu(name='OBJECT_MT_fc_main_menulaunchscript')