如何为SWT文本框实现支持内容复制的鼠标悬停提示?
嘿,我来帮你搞定这个SWT文本框的悬停复制功能!针对Eclipse Oxygen的RCP应用,我给你准备了完整的实现示例,还有Eclipse编辑器里同类功能的实现思路,往下看:
一、SWT文本框悬停可复制的实现示例
如果你的RCP应用里用的是纯SWT Text控件,我们可以通过监听鼠标轨迹事件,自定义一个带复制功能的悬停窗口来实现。核心思路是:
- 监听鼠标进入文本框的事件,弹出无标题的工具窗口作为悬停框
- 悬停框内放置只读文本控件(默认选中全部内容)和复制按钮
- 监听鼠标离开事件,销毁悬停框
下面是完整的ViewPart实现示例(RCP中常用的视图组件):
import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.part.ViewPart; public class HoverCopyView extends ViewPart { private Text mainText; private Shell hoverShell; @Override public void createPartControl(Composite parent) { parent.setLayout(new GridLayout(1, false)); // 初始化主文本框 mainText = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP); mainText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); mainText.setText("这是一段测试文本,鼠标悬停在这里会显示可复制的悬停框!"); // 添加鼠标轨迹监听器,处理悬停逻辑 mainText.addMouseTrackListener(new MouseTrackListener() { @Override public void mouseEnter(MouseEvent e) { // 先销毁已存在的悬停框,避免重复创建 if (hoverShell != null && !hoverShell.isDisposed()) { hoverShell.dispose(); } // 创建悬停窗口:TOOL风格+无标题栏,模拟悬浮效果 hoverShell = new Shell(parent.getShell(), SWT.TOOL | SWT.NO_TRIM); hoverShell.setLayout(new GridLayout(2, false)); // 悬停框内的只读文本控件,默认选中全部内容方便复制 Text hoverText = new Text(hoverShell, SWT.READ_ONLY | SWT.MULTI); hoverText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); hoverText.setText(mainText.getText()); hoverText.selectAll(); // 复制按钮:点击后将文本复制到系统剪贴板,然后关闭悬停框 Button copyBtn = new Button(hoverShell, SWT.PUSH); copyBtn.setText("复制"); copyBtn.addListener(SWT.Selection, event -> { Display.getDefault().getClipboard().setContents( new Object[]{hoverText.getText()}, null ); hoverShell.dispose(); }); // 设置悬停框位置:在鼠标当前位置下方偏移20px,避免遮挡鼠标 int displayX = mainText.toDisplay(e.x, e.y).x; int displayY = mainText.toDisplay(e.x, e.y).y + 20; hoverShell.setLocation(displayX, displayY); hoverShell.pack(); // 自动适配内容大小 hoverShell.open(); } @Override public void mouseExit(MouseEvent e) { // 鼠标离开主文本框时,销毁悬停框 if (hoverShell != null && !hoverShell.isDisposed()) { hoverShell.dispose(); hoverShell = null; } } }); } @Override public void setFocus() { mainText.setFocus(); } }
关键点说明:
- 用
SWT.TOOL | SWT.NO_TRIM创建的窗口没有标题栏,更像原生悬停提示 - 复制功能依赖
Display.getClipboard(),直接将文本内容设置到系统剪贴板 - 鼠标进入时先销毁旧悬停框,避免多个悬停框同时存在
二、Eclipse编辑器中同类功能的实现思路
如果你是在Eclipse文本编辑器(比如自定义代码编辑器)中实现类似功能,Eclipse已经提供了成熟的扩展机制,核心依赖JFace Text框架的悬停组件:
- 悬停提供者:实现
ITextHover或IAnnotationHover接口,定义悬停时要显示的内容和触发范围 - 信息控件:通过
IInformationControlCreator创建支持复制的信息控件,Eclipse默认的DefaultInformationControl已经内置了文本选择和复制功能 - 扩展点注册:在
plugin.xml中通过org.eclipse.ui.editors.text.hoverInformationControlCreator扩展点,将自定义悬停绑定到目标编辑器
下面是简化的实现示例:
自定义悬停类
import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextHoverExtension; import org.eclipse.jface.text.ITextViewer; import org.eclipse.swt.widgets.Shell; public class EditorTextHover implements ITextHover, ITextHoverExtension { @Override public String getHoverInfo(ITextViewer textViewer, org.eclipse.jface.text.IRegion hoverRegion) { // 获取鼠标悬停位置的文本内容,这里返回当前行的文本 try { return textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength()); } catch (Exception ex) { return "无法获取文本内容"; } } @Override public org.eclipse.jface.text.IRegion getHoverRegion(ITextViewer textViewer, int offset) { // 定义悬停触发的文本范围:这里返回光标所在的整行 return textViewer.getDocument().getLineInformationOfOffset(offset); } @Override public IInformationControlCreator getHoverControlCreator() { // 返回默认信息控件的创建器,第二个参数设为true开启文本选择/复制功能 return parent -> new DefaultInformationControl((Shell) parent, true); } }
在plugin.xml中注册悬停
<extension point="org.eclipse.ui.editors.text.hoverInformationControlCreator"> <hover class="com.yourpackage.EditorTextHover" id="com.yourpackage.editorHover" targetEditorId="org.eclipse.ui.DefaultTextEditor"> </hover> </extension>
思路说明:
- Eclipse编辑器的悬停功能是基于事件驱动的,当鼠标在文本上停留一定时间后触发
DefaultInformationControl支持通过快捷键(Ctrl+C)或右键菜单复制文本,无需自己实现复制逻辑- 可以通过继承
DefaultInformationControl自定义悬停框的样式和行为
内容的提问来源于stack exchange,提问作者EJoe
相关产品推荐
相关产品推荐

