Java:如何在 ScrollPane 视口上绘制非滚动覆盖?

2024-04-19

我想使用 ScrollPane 在其视口中显示图像,并且在图像上覆盖网格(或框,或任何其他类型的注册/位置标记)。我需要覆盖层在滚动时保持固定(这意味着图像似乎在覆盖层“下方”移动)。我将以固定速率滚动视口中的视图以提供平滑的运动,而叠加层将提供对视口内某个位置的引用。从概念上讲,想象一下在视口中滚动的大地图,并且视口有一个不移动(相对于视口本身)的矩形,该矩形标记了可以根据某些用户操作放大的区域。

我假设(但尚未确认)ScrollPane 实现可以有效地处理视图的渲染(从后备存储,不必为每个新的部分曝光重新绘制整个视图(甚至 ViewPort)),因此宁愿不必重写paint()方法。

我研究过 LayerPane,虽然没有掌握它,但似乎这是一种蛮力方法。 ScrollPane 是 SplitPane 的一个组件,可以移动/调整大小。我希望我必须使用绝对定位手动维护 ViewPort 和 LayerPane 之间的正确关系。我远不是 GUI 设计和实现方面的专家,我确​​信我错过了经验丰富的人会知道的从明显到晦涩和优雅的可能性。

我愿意接受任何建议,而不仅仅是我已经开始的道路。我是否应该(可以)将 JPanel 添加为 SplitPane 中的一个组件,然后将 LayerPane 添加到包含我的 ScrollPane 和 LayerPane 上不同层上的覆盖层(另一个 JPanel)的组件中? ScrollPane 中有直接支持此功能的功能吗?我已经查看了 Java Swing 教程和 API 文档,但还没有看到任何内容。

Thanks.

UPDATE:

感谢您的链接,垃圾之神。这比我预想的要容易得多。不需要 LayerPane、GlassPane、基于异或的合成...我不知道为什么我没有想到尝试重写 JViewport.paint() 来绘制我的叠加层 - 但通过下面的代码我验证了这个概念给我我正在寻找的东西。只需使用 JViewport 的子类,它就会执行我想要的操作(在本例中,在视口的中心覆盖一个矩形,而图像在下面滚动)。我不是 GUI 专家,而且 Java API 非常广泛;我不知道你们是如何把这一切记在脑子里的——但是谢谢!

class MyViewport extends JViewport {
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLACK);
        g2.drawRect(getWidth()/4,getHeight()/4,getWidth()/2,getHeight()/2);
    }
}

通常,“Swing 程序应该覆盖paintComponent()而不是覆盖paint(),”如中提到的在 AWT 和 Swing 中绘制:绘制方法 https://www.oracle.com/java/technologies/painting.html#callbacks。基于ScrollPanePaint https://stackoverflow.com/a/3518047/230513,绘制出below滚动内容,以下示例覆盖paint()画画above滚动内容。

import java.awt.*;
import javax.swing.*;

/**
 * @see https://stackoverflow.com/a/10097538/230513
 * @see https://stackoverflow.com/a/2846497/230513
 * @see https://stackoverflow.com/a/3518047/230513
 */
public class ScrollPanePaint extends JFrame {

    private static final int TILE = 64;

    public ScrollPanePaint() {
        JViewport viewport = new MyViewport();
        viewport.setView(new MyPanel());
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewport(viewport);
        this.add(scrollPane);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    private static class MyViewport extends JViewport {

        public MyViewport() {
            this.setOpaque(false);
            this.setPreferredSize(new Dimension(6 * TILE, 6 * TILE));
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(Color.blue);
            g.fillRect(TILE, TILE, 3 * TILE, 3 * TILE);
        }
    }

    private static class MyPanel extends JPanel {

        public MyPanel() {
            this.setOpaque(false);
            this.setPreferredSize(new Dimension(9 * TILE, 9 * TILE));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.lightGray);
            int w = this.getWidth() / TILE + 1;
            int h = this.getHeight() / TILE + 1;
            for (int row = 0; row < h; row++) {
                for (int col = 0; col < w; col++) {
                    if ((row + col) % 2 == 0) {
                        g.fillRect(col * TILE, row * TILE, TILE, TILE);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ScrollPanePaint();
            }
        });
    }
}

Note:设置不透明组件(例如JTable http://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html)作为滚动窗格的视图会产生奇怪的视觉错误,例如滚动时移动固定的蓝色框。使用setOpaque(false)在视图组件上修复该问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java:如何在 ScrollPane 视口上绘制非滚动覆盖? 的相关文章

随机推荐

  • 添加 firebase crashlytics 后,React 本机应用程序卡在启动屏幕上?

    我正在开发 React Native 应用程序 该应用程序运行良好 但是 当我导入 firebase crashlytics 时 如果我再次删除它 它会卡在启动屏幕上 应用程序工作正常吗 由于我是新手 我无法找到此问题的根本原因 我正在尝试
  • 使用 jquery UI 确认表单提交

    我正在尝试确认使用 ruby on Rails 创建的提交表单 但在提交之前 我有一个条件 即打开一个确认弹出窗口 询问用户是否真的想要这样做 这与默认的确认浏览器框一起使用 但现在我尝试使用 Jquery UI 来做到这一点 但它不起作用
  • 如何在 BigQuery 中构建“星级”报告(或迷你图或颜色渐变)

    假设我有以下示例输入 WITH Ratings AS SELECT A name 2 score UNION ALL SELECT B name 0 score UNION ALL SELECT C name 5 score UNION A
  • Firebase 控制台中不存在下载 URL

    firebase 存储的文件位置中不存在 url 相反 它提供了一个存储路径 请帮忙 在此输入图像描述 https i stack imgur com JFWAJ png 只需点击图片即可看到您的网址 要通过 Flutter 获取 URL
  • 如何可移植地乘以 64 位操作数并获得 128 位结果?

    对于 x64 我可以使用这个 uint64 t hi lo hi lo 64bit x 64bit multiply of c 0 and b 0 asm mulq 3 n t d hi a lo a c 0 rm b 0 cc a 0 h
  • 将 Archetype 新闻项目迁移到 Dexterity 内容类型

    我正在尝试将新闻项目中的内容复制到我编写的其他内容类型 在我的脚本中我有news项目和project物品 第二 project 是使用 Dexterity 定义的内容类型 如果我可以复制图像和正文 那就太好了news to project在
  • 如何使用端口 1025-5000 作为临时端口来解决 WinXP 问题?

    如果您使用端口 0 而不是非零端口创建 TCP 客户端套接字 则操作系统会为您选择任何空闲的临时端口 大多数操作系统选择临时端口IANA 动态端口范围 http www iana org assignments port numbers49
  • 为什么这个游戏无法开始,它正在循环[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我已经检查了这段代码的每一寸 我无法找出是什么导致它进入循环 一旦我按下按键开始 它就会播放开始噪音 然后它会转到结束屏幕 并说按按键再次
  • 调用 GC.Collect 和 GC.WaitForPendingFinalizers 时会发生死锁吗?

    鉴于以下情况 GC Collect GC MaxGeneration GC WaitForPendingFinalizers GC Collect GC MaxGeneration 考虑到多线程和垃圾收集模式 什么情况下会出现死锁WaitF
  • (1U << X) 有什么作用?

    我找到了这段代码 enum IsDynamic 1U lt lt 0 IsSharable 1U lt lt 1 IsStrong 1U lt lt 2 什么是 1U lt lt X do 它设置位掩码 1U lt lt 0 1 1U lt
  • 如何在mongoengine中通过oid搜索文档

    我需要通过 oid 从 db 获取文档 例如 Docs objects id 4f4381f4e779897a2c000009 但如何做到这一点 如果 id 需要 ObjectId 对象 即使我尝试从 pymongo 设置 ObjectId
  • 时间计算类型不匹配

    我正在尝试计算seconds两个日期之间的差异保留两位小数 但是 每当我执行代码时 都会收到错误 13 类型不匹配 我在网上搜索并尝试了许多变体 但总是以类型不匹配而告终 我不知道如何解决这个问题 有人可以教我怎么做吗 INFO 最初使用的
  • 使用“make-series”运算符而不定义确切的日期范围

    我在用make series创建一个错误仪表板 以指定的时间间隔显示给定时间段内的事件 如下所示 make series dcount id default 0 on timestamp from ago 30d to now step 8
  • 使用 pyinstaller 在所有系统上保留字体

    我使用 tkinter 制作了一个 GUI 我用 pyinstaller 创建了 onefile exe 但设置的字体 font freesans ttf 不适用于其他计算机 我想我需要添加字体 但在与我类似的情况下 我不明白 pygame
  • 球体表面上测地线(最短距离路径)之间的交点

    我进行了广泛的搜索 但尚未找到该问题的合适答案 给定球体上的两条线 每条线由起点和终点定义 确定它们是否相交以及相交的位置 我找到了这个网站 http mathforum org library drmath view 62205 html
  • PowerShell 未启动

    由于某种原因 PowerShell 不再在我的计算机上打开 打开 PowerShell 会显示以下内容 但永远不会完成打开并且永远不会显示提示 Windows PowerShell Copyright C Microsoft Corpora
  • Android 模拟器上的 Mockito

    Android 新手尝试在 Android 中使用我最喜欢的 Java 测试工具 我正在尝试使用 Mockito 1 9 5 如以下博客文章中所述 但无法在我的模拟器上运行测试 我目前没有用于测试的物理设备 Mockit Android 教
  • Android 版百度地图:访问键无法用于位置搜索

    我正在为中国客户创建一个 Android 应用程序 他们需要地图集成 因此 Google 地图不是一个选择 因为所有 Google 服务在中国都被屏蔽 我正在尝试使用百度地图 它被称为百度LBS 基于位置的服务 云 获得没有叠加层的基本地图
  • GetMessage() 在主消息循环中会返回 -1 吗?

    根据获取消息API http msdn microsoft com en us library ms644936 28VS 85 29 aspx从 MSDN 库来看 出现错误时可能会返回 1 该文档提供了应避免的常见错误的代码片段 whil
  • Java:如何在 ScrollPane 视口上绘制非滚动覆盖?

    我想使用 ScrollPane 在其视口中显示图像 并且在图像上覆盖网格 或框 或任何其他类型的注册 位置标记 我需要覆盖层在滚动时保持固定 这意味着图像似乎在覆盖层 下方 移动 我将以固定速率滚动视口中的视图以提供平滑的运动 而叠加层将提