UE中取色板SColorPicker界面关闭鼠标光标消失问题
前言
本文仅用于记录在使用UE的过程中遇到和解决的问题,如产生帮助,实属荣幸之至。可能也是本身比较小白导致的问题,欢迎指教。
一、问题描述
C++中实现一个打开取色板窗口的接口,供蓝图调用,蓝图调用后打开窗口,当关闭窗口的时候,鼠标光标消失,需要重新点击鼠标一下才能显示。
二、基本代码
1.打开取色板窗口接口
void UWebInterface::OpenColorPicker(const FString& ColorString)
{
FLinearColor InitialColor = FLinearColor::FromSRGBColor(FColor::FromHex(ColorString));
m_SelectedColor = InitialColor;//用于打开取色板时取色板显示
TSharedRef<SWindow> ColorWindow = SNew(SWindow)
.Title(LOCTEXT("ColorPickerTest-WindowTitle-StandardColor", "取色器"))
.ClientSize(FVector2D(429, 519)) // 初始大小为展开状态
.SupportsMaximize(false)
.SupportsMinimize(false)
.IsPopupWindow(false)
.FocusWhenFirstShown(true)
.SizingRule(ESizingRule::FixedSize); // 禁止调整大小
// 创建颜色选择器
TSharedPtr<SColorPicker> ColorPicker = SNew(SColorPicker)
.ParentWindow(ColorWindow)
.TargetColorAttribute_Lambda([InitialColor]() -> FLinearColor { return InitialColor; })
.UseAlpha(false)
.ExpandAdvancedSection(true) // 展开高级选项
.OnColorCommitted(FOnLinearColorValueChanged::CreateUObject(this, &UWebInterface::UpdateColor)) //点击确定更新颜色
.OnColorPickerWindowClosed(FOnWindowClosed::CreateUObject(this, &UWebInterface::OnColorPickerWindowClosed)); // 绑定窗口关闭事件
TSharedPtr<SBox> ColorPickerBox = SNew(SBox)
.Padding(10.0f)
[
ColorPicker.ToSharedRef()
];
ColorWindow->SetContent(ColorPickerBox.ToSharedRef());
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
if (ParentWindow.IsValid())
{
FSlateApplication::Get().AddModalWindow(ColorWindow, ParentWindow);
}
else
{
FSlateApplication::Get().AddWindow(ColorWindow);
}
}
三、解决方法
通过猜想和尝试,发现是由于释放鼠标光标的时候,ColorWindow 还未完全析构,占用鼠标光标。尝试在关闭窗口后的一些延迟操作来确保焦点和鼠标光标的恢复。
void UWebInterface::OnColorPickerWindowClosed(const TSharedRef<SWindow>& Window)
{
// 释放鼠标捕获
FSlateApplication::Get().ReleaseMouseCapture();
// 设置一个定时器来延迟执行恢复焦点和鼠标状态的操作
GWorld->GetTimerManager().SetTimerForNextTick(FTimerDelegate::CreateUObject(this, &UWebInterface::RestoreFocusAndMouse));
}
void UWebInterface::RestoreFocusAndMouse()
{
// 将焦点恢复到主窗口
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
if (ParentWindow.IsValid())
{
FSlateApplication::Get().SetKeyboardFocus(ParentWindow, EFocusCause::SetDirectly);
}
// 检查并重置鼠标捕获状态
FSlateApplication::Get().QueryCursor();
}
这样就成功解决问题啦。