This commit is contained in:
Rowland 2026-01-16 09:36:35 +08:00
parent 6a7b6b6959
commit 9424ddd0c2
5 changed files with 166 additions and 55 deletions

21
check_docking.py Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
"""
验证ImGui docking功能是否启用
"""
from imgui_bundle import imgui
# 创建一个虚拟的IO对象来检查标志
import imgui_bundle
print("检查ImGui docking支持...")
print(f"ConfigFlags_.docking_enable 存在: {hasattr(imgui.ConfigFlags_, 'docking_enable')}")
print(f"dock_space_over_viewport 存在: {hasattr(imgui, 'dock_space_over_viewport')}")
# 检查docking标志值
docking_flag = imgui.ConfigFlags_.docking_enable
print(f"Docking标志值: {docking_flag}")
# 检查窗口标志
print(f"WindowFlags_.no_title_bar 存在: {hasattr(imgui.WindowFlags_, 'no_title_bar')}")
print(f"WindowFlags_.no_collapse 存在: {hasattr(imgui.WindowFlags_, 'no_collapse')}")
print("\n✓ ImGui docking API 可用!")

View File

@ -3,8 +3,7 @@ ImGui样式管理器
用于统一管理ImGui UI样式与主程序Qt UI保持一致 用于统一管理ImGui UI样式与主程序Qt UI保持一致
""" """
import imgui from imgui_bundle import imgui, imgui_ctx
from imgui_bundle import imgui_ctx
import os import os
import platform import platform
from pathlib import Path from pathlib import Path
@ -210,27 +209,25 @@ class ImGuiStyleManager:
print("✓ ImGui样式已应用与Qt UI保持一致") print("✓ ImGui样式已应用与Qt UI保持一致")
def get_window_flags(self, window_type="default"): def get_window_flags(self, window_type="default"):
"""获取不同类型窗口的标志""" """获取不同类型窗口的标志支持docking"""
base_flags = 0 base_flags = 0
if window_type == "main_menu": if window_type == "main_menu":
return imgui.WINDOW_MENU_BAR return imgui.WindowFlags_.menu_bar
elif window_type == "dockable": elif window_type == "dockable":
# 移除NO_MOVE和NO_RESIZE以支持docking
return (base_flags | return (base_flags |
imgui.WINDOW_NO_TITLE_BAR | imgui.WindowFlags_.no_title_bar |
imgui.WINDOW_NO_RESIZE | imgui.WindowFlags_.no_collapse)
imgui.WINDOW_NO_MOVE |
imgui.WINDOW_NO_COLLAPSE)
elif window_type == "toolbar": elif window_type == "toolbar":
# 工具栏允许docking但保持无标题栏
return (base_flags | return (base_flags |
imgui.WINDOW_NO_TITLE_BAR | imgui.WindowFlags_.no_title_bar |
imgui.WINDOW_NO_RESIZE | imgui.WindowFlags_.no_collapse |
imgui.WINDOW_NO_MOVE | imgui.WindowFlags_.no_scrollbar)
imgui.WINDOW_NO_COLLAPSE |
imgui.WINDOW_NO_SCROLLBAR)
elif window_type == "panel": elif window_type == "panel":
return (base_flags | # 面板窗口完全支持docking
imgui.WINDOW_NO_COLLAPSE) return base_flags # 移除NO_COLLAPSE限制
return base_flags return base_flags

57
demo.py
View File

@ -115,6 +115,10 @@ class MyWorld(CoreWorld):
# Install Dear ImGui # Install Dear ImGui
p3dimgui.init() p3dimgui.init()
# 启用ImGui Docking功能
imgui.get_io().config_flags |= imgui.ConfigFlags_.docking_enable
print("✓ ImGui Docking功能已启用")
# 初始化样式管理器 # 初始化样式管理器
from core.imgui_style_manager import ImGuiStyleManager from core.imgui_style_manager import ImGuiStyleManager
self.style_manager = ImGuiStyleManager(self.imgui) self.style_manager = ImGuiStyleManager(self.imgui)
@ -311,6 +315,11 @@ class MyWorld(CoreWorld):
def __newFrame(self): def __newFrame(self):
# Dear ImGui commands can be placed here. # Dear ImGui commands can be placed here.
# 创建全屏DockSpace在第一帧之后创建
if imgui.get_frame_count() > 0:
viewport = imgui.get_main_viewport()
imgui.dock_space_over_viewport(0, viewport, imgui.DockNodeFlags_.passthru_central_node)
# 在第一帧应用样式 # 在第一帧应用样式
if imgui.get_frame_count() == 0: if imgui.get_frame_count() == 0:
self.style_manager.apply_style() self.style_manager.apply_style()
@ -379,46 +388,25 @@ class MyWorld(CoreWorld):
imgui.show_demo_window() imgui.show_demo_window()
def _draw_docked_layout(self, window_width, window_height): def _draw_docked_layout(self, window_width, window_height):
"""绘制停靠布局(模拟)""" """绘制可停靠的布局(支持拖拽)"""
# 布局参数
left_panel_width = 250
right_panel_width = 300
top_toolbar_height = 40
bottom_console_height = 150
menu_bar_height = 20
# 左侧场景树面板 # 左侧场景树面板
if self.showSceneTree: if self.showSceneTree:
imgui.set_next_window_pos((0, menu_bar_height), imgui.Cond_.always.value)
imgui.set_next_window_size((left_panel_width, window_height - menu_bar_height - bottom_console_height), imgui.Cond_.always.value)
self._draw_scene_tree() self._draw_scene_tree()
# 右侧面板区域
right_panel_y = menu_bar_height
right_panel_height = (window_height - menu_bar_height - bottom_console_height) // 2
# 属性面板 # 属性面板
if self.showPropertyPanel: if self.showPropertyPanel:
imgui.set_next_window_pos((window_width - right_panel_width, right_panel_y), imgui.Cond_.always.value)
imgui.set_next_window_size((right_panel_width, right_panel_height), imgui.Cond_.always.value)
self._draw_property_panel() self._draw_property_panel()
# 脚本面板 # 脚本面板
if self.showScriptPanel: if self.showScriptPanel:
imgui.set_next_window_pos((window_width - right_panel_width, right_panel_y + right_panel_height), imgui.Cond_.always.value)
imgui.set_next_window_size((right_panel_width, right_panel_height), imgui.Cond_.always.value)
self._draw_script_panel() self._draw_script_panel()
# 底部控制台 # 底部控制台
if self.showConsole: if self.showConsole:
imgui.set_next_window_pos((0, window_height - bottom_console_height), imgui.Cond_.always.value)
imgui.set_next_window_size((window_width, bottom_console_height), imgui.Cond_.always.value)
self._draw_console() self._draw_console()
# 顶部工具栏 # 顶部工具栏
if self.showToolbar: if self.showToolbar:
imgui.set_next_window_pos((left_panel_width, menu_bar_height), imgui.Cond_.always.value)
imgui.set_next_window_size((window_width - left_panel_width - right_panel_width, top_toolbar_height), imgui.Cond_.always.value)
self._draw_toolbar() self._draw_toolbar()
@ -486,7 +474,10 @@ class MyWorld(CoreWorld):
def _draw_toolbar(self): def _draw_toolbar(self):
"""绘制工具栏""" """绘制工具栏"""
with self.style_manager.begin_styled_window("工具栏", self.showToolbar): # 工具栏可以保持无标题栏,但允许移动和调整大小
flags = self.style_manager.get_window_flags("toolbar")
with self.style_manager.begin_styled_window("工具栏", self.showToolbar, flags):
self.showToolbar = True # 确保窗口保持打开 self.showToolbar = True # 确保窗口保持打开
# 工具按钮组 # 工具按钮组
@ -548,7 +539,10 @@ class MyWorld(CoreWorld):
def _draw_scene_tree(self): def _draw_scene_tree(self):
"""绘制场景树面板""" """绘制场景树面板"""
with self.style_manager.begin_styled_window("场景树", self.showSceneTree): # 使用更少的限制性标志允许docking
flags = (imgui.WindowFlags_.no_collapse)
with self.style_manager.begin_styled_window("场景树", self.showSceneTree, flags):
self.showSceneTree = True # 确保窗口保持打开 self.showSceneTree = True # 确保窗口保持打开
imgui.text("场景层级") imgui.text("场景层级")
@ -577,7 +571,10 @@ class MyWorld(CoreWorld):
def _draw_property_panel(self): def _draw_property_panel(self):
"""绘制属性面板""" """绘制属性面板"""
with self.style_manager.begin_styled_window("属性面板", self.showPropertyPanel): # 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("属性面板", self.showPropertyPanel, flags):
self.showPropertyPanel = True # 确保窗口保持打开 self.showPropertyPanel = True # 确保窗口保持打开
imgui.text("对象属性") imgui.text("对象属性")
@ -605,7 +602,10 @@ class MyWorld(CoreWorld):
def _draw_console(self): def _draw_console(self):
"""绘制控制台面板""" """绘制控制台面板"""
with self.style_manager.begin_styled_window("控制台", self.showConsole): # 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("控制台", self.showConsole, flags):
self.showConsole = True # 确保窗口保持打开 self.showConsole = True # 确保窗口保持打开
imgui.text("控制台输出") imgui.text("控制台输出")
@ -645,7 +645,10 @@ class MyWorld(CoreWorld):
def _draw_script_panel(self): def _draw_script_panel(self):
"""绘制脚本管理面板""" """绘制脚本管理面板"""
with self.style_manager.begin_styled_window("脚本管理", self.showScriptPanel): # 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("脚本管理", self.showScriptPanel, flags):
self.showScriptPanel = True # 确保窗口保持打开 self.showScriptPanel = True # 确保窗口保持打开
imgui.text("脚本列表") imgui.text("脚本列表")

View File

@ -19,37 +19,75 @@ Size=745,76
Collapsed=0 Collapsed=0
[Window][Dear ImGui Demo] [Window][Dear ImGui Demo]
Pos=948,19 Pos=241,149
Size=550,680 Size=832,127
Collapsed=1 Collapsed=0
[Window][工具栏] [Window][工具栏]
Pos=250,20 Pos=287,20
Size=1300,40 Size=832,32
Collapsed=0 Collapsed=0
DockId=0x00000007,0
[Window][场景树] [Window][场景树]
Pos=0,20 Pos=0,20
Size=250,846 Size=285,578
Collapsed=0 Collapsed=0
DockId=0x00000001,0
[Window][属性面板] [Window][属性面板]
Pos=1550,20 Pos=1121,20
Size=300,423 Size=259,214
Collapsed=1 Collapsed=0
DockId=0x00000005,0
[Window][控制台] [Window][控制台]
Pos=0,866 Pos=0,600
Size=1850,150 Size=1380,150
Collapsed=0 Collapsed=0
DockId=0x0000000A,0
[Window][脚本管理] [Window][脚本管理]
Pos=1550,443 Pos=1121,236
Size=300,423 Size=259,362
Collapsed=0 Collapsed=0
DockId=0x00000006,0
[Window][中文显示测试] [Window][中文显示测试]
Pos=60,60 Pos=60,60
Size=135,263 Size=135,263
Collapsed=0 Collapsed=0
[Window][WindowOverViewport_11111111]
Pos=0,20
Size=1380,730
Collapsed=0
[Window][测试窗口1]
Pos=60,60
Size=121,82
Collapsed=0
[Window][测试窗口2]
Pos=60,60
Size=121,82
Collapsed=0
[Window][测试窗口3]
Pos=60,60
Size=93,65
Collapsed=0
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=1380,730 Split=Y
DockNode ID=0x00000009 Parent=0x08BD597D SizeRef=1380,578 Split=X
DockNode ID=0x00000003 Parent=0x00000009 SizeRef=1119,730 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=285,730 HiddenTabBar=1 Selected=0xE0015051
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=832,730 Split=Y
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1380,32 HiddenTabBar=1 Selected=0x43A39006
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1380,696 CentralNode=1 Selected=0x5E5F7166
DockNode ID=0x00000004 Parent=0x00000009 SizeRef=259,730 Split=Y Selected=0x5DB6FF37
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=259,270 HiddenTabBar=1 Selected=0x5DB6FF37
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=259,458 HiddenTabBar=1 Selected=0x3188AB8D
DockNode ID=0x0000000A Parent=0x08BD597D SizeRef=1380,150 HiddenTabBar=1 Selected=0x5428E753

52
test_docking.py Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""
测试ImGui docking功能
"""
from direct.showbase.ShowBase import ShowBase
import p3dimgui
from imgui_bundle import imgui, imgui_ctx
class DockingTest(ShowBase):
def __init__(self):
ShowBase.__init__(self)
# Install Dear ImGui
p3dimgui.init()
# 启用ImGui Docking功能
imgui.get_io().config_flags |= imgui.ConfigFlags_.docking_enable
print("✓ ImGui Docking功能已启用")
# 添加任务
self.taskMgr.add(self.__newFrame, "imgui-new-frame")
def __newFrame(self, task):
# 创建全屏DockSpace在第一帧之后创建
if imgui.get_frame_count() > 0:
viewport = imgui.get_main_viewport()
imgui.dock_space_over_viewport(0, viewport, imgui.DockNodeFlags_.passthru_central_node)
# 测试窗口
if imgui.get_frame_count() > 10: # 等待几帧后显示
# 窗口1
with imgui_ctx.begin("测试窗口1", True):
imgui.text("这是第一个测试窗口")
imgui.text("你可以拖拽标题栏来移动窗口")
imgui.text("也可以拖拽到其他窗口边缘来停靠")
# 窗口2
with imgui_ctx.begin("测试窗口2", True):
imgui.text("这是第二个测试窗口")
imgui.text("尝试将这个窗口停靠到第一个窗口")
imgui.text("或者创建标签页")
# 窗口3
with imgui_ctx.begin("测试窗口3", True):
imgui.text("这是第三个测试窗口")
imgui.text("自由调整窗口大小和位置")
return task.cont
if __name__ == "__main__":
test = DockingTest()
test.run()