Blender TOPBAR_HT_upper_bar 在顶部栏出现两个相同内容的而解决办法!

问题描述

在为Blender 编写插件时,需要在Blender顶部右侧区域显示插件的按钮,
但是使用下方的测试代码后会出现两个完全相同的内容,
一个在 顶部 ,一个在 右侧!

为了解决这个问题,我看了Blender 安装目录下的space_topbar.py文件
位置在 scripts\startup\bl_ui\space_topbar.py

其中 TOPBAR_HT_upper_bar 类,
有在获取 region = context.region
然后 if region.alignment == 'RIGHT' 在判断方向区域
于是就有了这篇随笔!

class TOPBAR_HT_upper_bar(Header):
    bl_space_type = 'TOPBAR'

    def draw(self, context):
        region = context.region

        if region.alignment == 'RIGHT':
            self.draw_right(context)
        else:
            self.draw_left(context)

    def draw_left(self, context):
        layout = self.layout

        window = context.window
        screen = context.screen

        TOPBAR_MT_editor_menus.draw_collapsible(context, layout)

        layout.separator()

        if not screen.show_fullscreen:
            layout.template_ID_tabs(window, "workspace", new="workspace.add", menu="TOPBAR_MT_workspace_menu")
        else:
            layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")

    def draw_right(self, context):
        layout = self.layout

        window = context.window
        screen = context.screen
        scene = window.scene

        # If statusbar is hidden, still show messages at the top
        if not screen.show_statusbar:
            layout.template_reports_banner()
            layout.template_running_jobs()

        # Active workspace view-layer is retrieved through window, not through workspace.
        layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")

        row = layout.row(align=True)
        row.template_search(
            window, "view_layer",
            scene, "view_layers",
            new="scene.view_layer_add",
            unlink="scene.view_layer_remove",
        )

测试代码

下面是示例代码

import bpy


class SYA_OT_Hi(bpy.types.Operator):
    """Say Hi from Button"""

    bl_idname = "sya.hi"
    bl_label = "Say Hi"

    def execute(self, context):
        print("HiHiHiHiHiHiHiHiHiHiHiHi!")
        return {"FINISHED"}


def draw_topbar_menu(self, context):
    """
    顶部栏绘制函数
    """

    # 获取当前渲染区域的布局容器
    layout = self.layout
    # 创建水平布局容器
    row = layout.row(align=True)
    # 测试按钮
    row.operator("sya.hi", text="Test Button")


def register():
    """注册"""
    # 1. 注册操作器类
    bpy.utils.register_class(SYA_OT_Hi)
    # 2. 将绘制函数挂载到顶部栏系统
    bpy.types.TOPBAR_HT_upper_bar.append(draw_topbar_menu)


def unregister():
    """卸载"""
    # 1. 从顶部栏系统移除绘制函数
    bpy.types.TOPBAR_HT_upper_bar.remove(draw_topbar_menu)
    # 2. 注销操作器类
    bpy.utils.unregister_class(SYA_OT_Hi)


# 直接运行时手动注册(开发调试用)
if __name__ == "__main__":
    register()

image

我们将看到两个相同的内容出现在了顶部栏的中部和右侧!
(如果看不到中部的内容就缩小UI比例!)

解决办法

import bpy


class SYA_OT_Hi(bpy.types.Operator):
    """Say Hi from Button"""

    bl_idname = "sya.hi"
    bl_label = "Say Hi"

    def execute(self, context):
        print("HiHiHiHiHiHiHiHiHiHiHiHi!")
        return {"FINISHED"}


def draw_topbar_menu(self, context):
    """
    顶部栏绘制函数
    context.region.alignment 说明:
    - "RIGHT": 顶部栏右侧区域(Scene, View Layer)
    - "TOP": 顶部栏顶部区域(包含文件/编辑...)
    """
    # 获取当前渲染区域的对齐方式
    alignment = context.region.alignment

    # 获取当前渲染区域
    layout = self.layout
    # 创建水平布局容器
    row = layout.row(align=True)

    # 区域敏感型按钮绘制
    if alignment == "RIGHT":
        # 右侧区域
        row.operator("sya.hi", text="Right Button")
    elif alignment == "TOP":
        # 顶部区域
        row.operator("sya.hi", text="Top Button")


def register():
    """注册"""
    # 1. 注册操作器类
    bpy.utils.register_class(SYA_OT_Hi)
    # 2. 将绘制函数挂载到顶部栏系统
    bpy.types.TOPBAR_HT_upper_bar.append(draw_topbar_menu)


def unregister():
    """卸载"""
    # 1. 从顶部栏系统移除绘制函数
    bpy.types.TOPBAR_HT_upper_bar.remove(draw_topbar_menu)
    # 2. 注销操作器类
    bpy.utils.unregister_class(SYA_OT_Hi)


# 直接运行时手动注册(开发调试用)
if __name__ == "__main__":
    register()

image

使用 alignment = context.region.alignment 获取渲染区域,
之后判断是TOP 或 是 RIGHT
即可根据需要在指定区域显示内容!
这样就不会出现两个相同的内容在顶部栏了!

posted @ 2025-07-18 17:22  letleon  阅读(27)  评论(0)    收藏  举报