Studio 使您能够创建自定义 小部件 并将它们用作工具和扩展。这些小部件在 Studio 中表现为自定义窗口/面板,您可以将它们停靠在界面内,或将它们作为独立窗口漂浮。
创建小部件 UI
所有 Studio 小部件都以 DockWidgetPluginGui 对象开始,您可以在其中填充 GuiObjects,例如文本标签和按钮。要创建一个空的小部件 GUI,请调用 CreateDockWidgetPluginGui() 函数,传入一个 ID 和一个 DockWidgetPluginGuiInfo 对象。
注意 DockWidgetPluginGuiInfo.new() 构造函数按 特定顺序 期待其参数,如下所示:
| # | 属性 | 类型 | 描述 |
|---|---|---|---|
| 1 | Enum.InitialDockState | 枚举 | Enum.InitialDockState 枚举之一。 |
| 2 | InitialEnabled | 布尔值 | 小部件 GUI 的初始启用(可见)状态。 |
| 3 | InitialEnabledShouldOverrideRestore | 布尔值 | 如果为 true, InitialEnabled 的值将覆盖以前保存的启用状态。 |
| 4 | FloatingXSize | 整数 | 当 InitialDockState 设置为 Enum.InitialDockState.Float 时 GUI 的初始宽度。 |
| 5 | FloatingYSize | 整数 | 当 InitialDockState 设置为 Enum.InitialDockState.Float 时 GUI 的初始高度。 |
| 6 | MinWidth | 整数 | GUI 的最小宽度,具有某些平台特定的变化。 |
| 7 | MinHeight | 整数 | GUI 的最小高度,具有某些平台特定的变化。 |
-- 创建新的 "DockWidgetPluginGuiInfo" 对象local widgetInfo = DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, -- 小部件将在浮动面板中初始化true, -- 小部件将最初启用false, -- 不要覆盖之前的启用状态200, -- 浮动窗口的默认宽度300, -- 浮动窗口的默认高度150, -- 浮动窗口的最小宽度150 -- 浮动窗口的最小高度)-- 创建新的小部件 GUIlocal testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)testWidget.Title = "测试小部件" -- 可选的小部件标题
自定义小部件 UI
创建小部件后,您可以使用 GuiObjects 例如信息丰富的 TextLabels 或交互式的 ImageButtons 自定义其用户界面。例如,以下代码将基本的 TextButton 添加到 GUI 窗口中:
-- 创建新的小部件 GUIlocal testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)testWidget.Title = "测试小部件" -- 可选的小部件标题local testButton = Instance.new("TextButton")testButton.BorderSizePixel = 0testButton.TextSize = 20testButton.TextColor3 = Color3.new(1,0.2,0.4)testButton.AnchorPoint = Vector2.new(0.5,0.5)testButton.Size = UDim2.new(1,0,1,0)testButton.Position = UDim2.new(0.5,0,0.5,0)testButton.SizeConstraint = Enum.SizeConstraint.RelativeYYtestButton.Text = "点击我"testButton.Parent = testWidget
更改 Studio 颜色主题
有效的 Studio 小部件理想情况下应该与 Studio 主题 设置相匹配,并在主题更改时动态调整。例如,如果开发者正在使用深色主题,小部件的背景颜色、图像和文本标签在 Studio 的本地主题颜色旁边应该看起来很好。
以下代码添加了利用 syncGuiColors() 函数,该函数最初与一个需要同步的 GUI 对象表一起调用。在该函数内,嵌套的 setColors() 函数遍历对象并使用 GetColor() 和 Enum.StudioStyleGuideColor 枚举同步其特定方面。此 setColors() 函数会立即运行以同步 Studio 主题,然后连接到 ThemeChanged 事件以检测未来的主题更改。
testButton.Parent = testWidget
local function syncGuiColors(objects)
local function setColors()
for _, guiObject in objects do
-- 同步背景色
guiObject.BackgroundColor3 = settings().Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainBackground)
-- 同步文本色
guiObject.TextColor3 = settings().Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainText)
end
end
-- 运行 'setColors()' 函数以最初同步颜色
setColors()
-- 将 'ThemeChanged' 事件连接到 'setColors()' 函数
settings().Studio.ThemeChanged:Connect(setColors)
end
-- 运行 'syncGuiColors()' 函数以同步所提供对象的颜色
syncGuiColors({testButton})
自定义鼠标光标
为了改善与小部件元素的预期交互,您可以为 GUI 事件设置特定于系统的 鼠标光标,例如 MouseEnter 和 MouseLeave。以下代码演示如何将功能连接到 testButton 的 MouseEnter 和 MouseLeave 事件以更改鼠标光标:
local function setCursor(cursorAsset)
plugin:GetMouse().Icon = cursorAsset
end
testButton.MouseEnter:Connect(function()
setCursor("rbxasset://SystemCursors/PointingHand")
end)
testButton.MouseLeave:Connect(function()
setCursor("")
end)
请参考以下表格以获取鼠标光标及其潜在用例的列表:
| 鼠标光标图标 | 资产 | 用例 |
|---|---|---|
| rbxasset://SystemCursors/Arrow | 默认点击和选择。 | |
| rbxasset://SystemCursors/PointingHand | 悬停在活动链接/按钮上。 | |
| rbxasset://SystemCursors/OpenHand | 悬停在可拖动项目上。 | |
| rbxasset://SystemCursors/ClosedHand | 拖动项目。 | |
| rbxasset://SystemCursors/IBeam | 悬停在文本字段中。 | |
| rbxasset://SystemCursors/SizeNS | 悬停在垂直调整大小手柄上。 | |
| rbxasset://SystemCursors/SizeEW | 悬停在水平调整大小手柄上。 | |
| rbxasset://SystemCursors/SizeNESW | 悬停在角落调整大小手柄上。 | |
| rbxasset://SystemCursors/SizeNWSE | 悬停在角落调整大小手柄上。 | |
| rbxasset://SystemCursors/SizeAll | 悬停在多方向调整大小手柄上。 | |
| rbxasset://SystemCursors/SplitNS | 悬停在垂直 "分割" 手柄上。 | |
| rbxasset://SystemCursors/SplitEW | 悬停在水平 "分割" 手柄上。 | |
| rbxasset://SystemCursors/Forbidden | 悬停在锁定/禁止的项目上。 | |
| rbxasset://SystemCursors/Wait | 表示某个操作正在进行中。 | |
| rbxasset://SystemCursors/Busy | 表示系统繁忙。 | |
| rbxasset://SystemCursors/Cross | 悬停在精准选择区域上。 |
收集用户输入
UI 元素如 TextBox 和 TextButton 在 Studio 小部件中正常工作,您可以像在 Roblox 上一样构建界面。但是,UserInputService 无法正常工作,因为这些服务期望主体验窗口处于聚焦状态。
一种处理通用输入事件的解决方法是创建一个透明的 Frame,并将其覆盖在整个屏幕上。以下代码示例创建一个框架,当用户点击框架时,GuiObject.InputBegan 事件会捕获框架上的键盘输入,直到用户点击其他地方:
local frame = Instance.new("Frame")
frame.BackgroundTransparency = 1 -- 隐藏框架
frame.Size = UDim2.new(1, 0, 1, 0) -- 覆盖整个屏幕
frame.Position = UDim2.new(0, 0, 0, 0)
frame.Parent = testWidget
local function onInputBegan(inputObject)
-- 在此处理输入对象,例如检测按键按下
end
frame.InputBegan:Connect(onInputBegan)
拖放交互
使用拖放交互是改善小部件数据流的简单方法。要创建此交互,您必须定义要拖动的元素,启动拖动,创建一个投放目标并处理投放操作。
创建拖动源
当用户在某个 UI 元素(通常是小部件中的 TextButton 或 ImageButton)上按下鼠标按钮时,您可以通过调用 Plugin:StartDrag() 开始拖动操作。以下代码示例创建一个窗口小部件,并在其中放置一个文本按钮。
-- 首先创建小部件local widgetInfo = DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, true, true, 300, 200)local dragSourceWidget = plugin:CreateDockWidgetPluginGui("拖动源", widgetInfo)dragSourceWidget.Title = "拖动源"-- 创建一个 TextButton,启动拖动local dragButton = Instance.new("TextButton")dragButton.Size = UDim2.new(1, 0, 1, 0)dragButton.Text = "拖动我!"dragButton.Parent = dragSourceWidget
启动拖动
当用户点击 TextButton 时,您可以通过 MouseButton1Down() 事件启动拖动,该事件在用户按下鼠标按钮时立即触发。
在连接的函数内,确定要拖动的数据。数据的 类型 应在 MimeType 键中反映,拖动的 内容 应在 Data 键中反映,而 发送者 应在 Sender 键中描述自己。有关更多详细信息,请参阅 Plugin:StartDrag() 页面。
local function onButton1Down()
local dragInfo = {
Data = "Hello, world", -- 拖动的数据
MimeType = "text/plain", -- 描述数据的 MIME 类型
Sender = "SomeDragSource", -- 描述数据来自何处
MouseIcon = "", -- 用于光标的图像内容
DragIcon = "", -- 在拖动期间光标下方渲染的图像内容
HotSpot = Vector2.zero -- 在 DragIcon 上光标的中心位置
}
plugin:StartDrag(dragInfo)
end
dragButton.MouseButton1Down:Connect(onButton1Down)
创建投放目标
PluginGui.PluginDragDropped 事件在用户在拖动期间释放鼠标时触发。当发生这种情况时,您需要定义一个 投放目标,例如带有 TextLabel 的第二个小部件以检测投放。
local dragTargetWidget = plugin:CreateDockWidgetPluginGui("投放目标", widgetInfo)dragTargetWidget.Title = "投放目标"-- 此 TextLabel 将显示被投放的内容local textLabel = Instance.new("TextLabel")textLabel.Size = UDim2.new(1, 0, 1, 0)textLabel.Text = "投放到这里..."textLabel.Parent = dragTargetWidget
处理投放操作
创建投放目标后,在投放目标小部件上连接 PluginGui.PluginDragDropped 事件:
local function onDragDrop(dragData)
print("PluginDragDropped")
if dragData.MimeType == "text/plain" then
textLabel.Text = dragData.Data
else
textLabel.Text = dragData.MimeType
end
end
dragTargetWidget.PluginDragDropped:Connect(onDragDrop)
在拖动仍在进行时,随着用户将鼠标移到小部件上,这三个事件将触发:
- PluginDragEntered – 当用户将鼠标悬停在窗口上时触发
- PluginDragMoved –当用户将鼠标移动到窗口上时反复触发。这对于显示 "投放到这里!" 消息很有用。
- PluginDragLeft – 当用户的光标离开窗口时触发。这对于隐藏 "投放到这里!" 消息很有用。















