You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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框架的悬停组件:

  1. 悬停提供者:实现ITextHover或IAnnotationHover接口,定义悬停时要显示的内容和触发范围
  2. 信息控件:通过IInformationControlCreator创建支持复制的信息控件,Eclipse默认的DefaultInformationControl已经内置了文本选择和复制功能
  3. 扩展点注册:在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:10:08