为什么 .paintComponent() 定义在 JComponent 上?

2023-12-22

很抱歉,如果我的问题由于是理论上的问题而无法适应 Stack Overflow 的要求,但我不知道还能问哪里。

在过去的几周里,我一直在尝试更好地了解 Swing API 的工作原理及其组件,以便创建我自己的自定义组件。我读过大量的教程,在这里搜索过,我对 Java 的 swing 源代码很感兴趣,坦白说……我的脑子一片混乱。

据我了解,swing组件由3部分组成:

  • 模型:组件状态和数据的存储位置
  • UI delegate:绘制组件并
  • JComponent:它将所有内容联系在一起。

在本教程中https://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html https://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html有一段说:

PaintComponent 方法是所有自定义绘制发生的地方。 >此方法由 javax.swing.JComponent 定义,然后由您的 >子类覆盖以提供其自定义行为

为什么 JComponent 上有一个 PaintComponent 方法?它不应该是 UI 委托的独占方法吗?


Swing是基于AWT的。因此最初的限制基于 AWT 如何绘制它的组件。由于 Swing 是轻量级的,因此当绘制组件根组件时,需要通知子组件 Swing 组件它们也需要更新。这是通过调用来完成的paint受更新影响的所有子组件的方法(依次调用paintComponent方法)。

关于 Swing API 绘制链的许多决策都是基于定制的概念。它降低了所涉及的复杂性(通过阻止覆盖paint并将功能集中到paintComponent方法)。

Look and Feel API 基于“委托”模型。这意味着用于执行所述操作的功能被“委托”给某个其他对象。这意味着 UI 委托 UI 实际上并不知道组件何时“需要”绘制,而是由组件告诉它需要绘制。这使得它更加灵活,并且在许多情况下更容易定制。

根据您的上一个问题 https://stackoverflow.com/questions/47145979/custom-jtooglebutton-shape-but-with-default-colors一个习俗ButtonUI可能是更好的选择之一,这样您就可以更好地控制按钮的绘制方式。

尝试让按钮遵循当前的外观和感觉配色方案将非常困难,但您可以尝试看看src.jar它与 JDK 一起安装,其中包括许多外观和感觉的实现(如果您在 Windows 上,您也应该获得 Windows 外观和感觉,如果您在 Mac 上,那么您不会获得 Mac 或 Windows ????)

我首先看了一下BasicButtonUI and ButtonUI以便更好地了解这些属性。我把一些更有趣的方法拉到了自定义中ShapeButtonUI...

public class ShapeButtonUI extends BasicButtonUI {

    private Shape shape;

    public ShapeButtonUI(Shape shape) {
        this.shape = shape;
    }

    protected Color getSelectColor() {
        return UIManager.getColor(getPropertyPrefix() + "select");
    }

    protected Color getDisabledTextColor() {
        return UIManager.getColor(getPropertyPrefix()
                        + "disabledText");
    }

    protected Color getFocusColor() {
        return UIManager.getColor(getPropertyPrefix() + "focus");
    }

    @Override
    protected void installDefaults(AbstractButton b) {
        super.installDefaults(b);
    }

    @Override
    protected void uninstallDefaults(AbstractButton b) {
        super.uninstallDefaults(b);
    }

    @Override
    public void paint(Graphics g, JComponent c) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setClip(shape);
        Rectangle bounds = shape.getBounds();
        LinearGradientPaint lgp = new LinearGradientPaint(
                        new Point(bounds.x, bounds.y),
                        new Point(bounds.x, bounds.y + bounds.height),
                        new float[]{0, 1},
                        new Color[]{c.getBackground().brighter(), c.getBackground().darker()});
        g2d.setPaint(lgp);
        g2d.fill(shape);
        g2d.dispose();
        g2d = (Graphics2D) g.create();
        g2d.setColor(c.getForeground());
        g2d.draw(shape);
        g2d.dispose();
        super.paint(g, c);
    }

    @Override
    protected void paintButtonPressed(Graphics g, AbstractButton b) {
        super.paintButtonPressed(g, b);
    }

    @Override
    protected void paintFocus(Graphics g, AbstractButton b,
                    Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
        super.paintFocus(g, b, viewRect, textRect, iconRect);
    }

    @Override
    protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
        super.paintText(g, b, textRect, text);

//          ButtonModel model = b.getModel();
//          FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
//          int mnemIndex = b.getDisplayedMnemonicIndex();
//
//          /* Draw the Text */
//          if (model.isEnabled()) {
//              /**
//               * * paint the text normally
//               */
//              g.setColor(b.getForeground());
//          } else {
//              /**
//               * * paint the text disabled **
//               */
//              g.setColor(getDisabledTextColor());
//          }
//          SwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemIndex,
//                          textRect.x, textRect.y + fm.getAscent());

    }

    @Override
    public Dimension getMinimumSize(JComponent c) {
        Rectangle bounds = shape.getBounds();
        return new Dimension(bounds.x + bounds.width + 1, bounds.y + bounds.height + 1);
    }

    @Override
    public Dimension getPreferredSize(JComponent c) {
        Rectangle bounds = shape.getBounds();
        return new Dimension(bounds.x + bounds.width + 1, bounds.y + bounds.height + 1);
    }

    @Override
    public Dimension getMaximumSize(JComponent c) {
        Rectangle bounds = shape.getBounds();
        return new Dimension(bounds.x + bounds.width + 1, bounds.y + bounds.height + 1);
    }

}

其中大多数您可能不需要担心,但您至少应该知道它们存在,因为您稍后可能想要自定义一些其他属性/功能。

该委托旨在根据需要安装在按钮上,而不是将其安装为按钮的默认 UI 委托。这样做的原因是需要形状对象。如果您愿意,这允许每个按钮都有自己的形状。

您可以将单个形状植入UIManager的属性,并使用它来代替,但我并没有为这个例子而烦恼。

然后我创建了自己的形状/路径......

public class PointerPath extends Path2D.Double {

    public PointerPath() {
        moveTo(1, 1);
        lineTo(150, 1);
        lineTo(198, 100);
        lineTo(150, 198);
        lineTo(1, 198);
        lineTo(50, 100);
        closePath();
    }

}

并将其应用到按钮上......

ShapeButtonUI shapeUI = new ShapeButtonUI(new PointerPath());
JButton btn = new JButton("That way");
btn.setUI(shapeUI);

最终产生了类似的东西......

现在,这是一个非常基本的示例,实际上,按钮应该围绕文本调整自身大小(带有一些附加的填充/边距信息),但这需要多部分形状,因此我们知道哪些部分可以调整大小,哪些部分可以调整大小什么方向,所以,复杂。

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

为什么 .paintComponent() 定义在 JComponent 上? 的相关文章

  • 序列的排列?

    我有具体数量的数字 现在我想以某种方式显示这个序列的所有可能的排列 例如 如果数字数量为3 我想显示 0 0 0 0 0 1 0 0 2 0 1 0 0 1 1 0 1 2 0 2 0 0 2 1 0 2 2 1 0 0 1 0 1 1 0
  • Mockito:如何通过模拟测试我的服务?

    我是模拟测试新手 我想测试我的服务方法CorrectionService correctPerson Long personId 实现尚未编写 但这就是它将执行的操作 CorrectionService将调用一个方法AddressDAO这将
  • 如何通过 javaconfig 使用 SchedulerFactoryBean.schedulerContextAsMap

    我使用 Spring 4 0 并将项目从 xml 移至 java config 除了访问 Service scheduleService 带注释的类来自QuartzJobBean executeInternal 我必须让它工作的 xml 位
  • Java 枚举与创建位掩码和检查权限的混淆

    我想将此 c 权限模块移植到 java 但是当我无法将数值保存在数据库中然后将其转换为枚举表示形式时 我很困惑如何执行此操作 在 C 中 我创建一个如下所示的枚举 public enum ArticlePermission CanRead
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • org.apache.hadoop.security.AccessControlException:客户端无法通过以下方式进行身份验证:[TOKEN,KERBEROS] 问题

    我正在使用 java 客户端通过 Kerberos 身份验证安全访问 HDFS 我尝试打字klist在服务器上 它显示已经存在的有效票证 我收到的异常是客户端无法通过以下方式进行身份验证 TOKEN KERBEROS 帮助将不胜感激 这是一
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 如何在用户输入数据后重新运行java代码

    嘿 我有一个基本的java 应用程序 显示人们是成年人还是青少年等 我从java开始 在用户输入年龄和字符串后我找不到如何制作它它们被归类为 我希望它重新运行整个过程 以便其他人可以尝试 的节目 我一直在考虑做一个循环 但这对我来说没有用
  • Spring Boot Data JPA 从存储过程接收多个输出参数

    我尝试通过 Spring Boot Data JPA v2 2 6 调用具有多个输出参数的存储过程 但收到错误 DEBUG http nio 8080 exec 1 org hibernate engine jdbc spi SqlStat
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • 如何使用 jUnit 将测试用例添加到套件中?

    我有 2 个测试类 都扩展了TestCase 每个类都包含一堆针对我的程序运行的单独测试 如何将这两个类 以及它们拥有的所有测试 作为同一套件的一部分执行 我正在使用 jUnit 4 8 在 jUnit4 中你有这样的东西 RunWith
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • Spring Boot 无法更新 azure cosmos db(MongoDb) 上的分片集合

    我的数据库中存在一个集合 documentDev 其分片键为 dNumber 样本文件 id 12831221wadaee23 dNumber 115 processed false 如果我尝试使用以下命令通过任何查询工具更新此文档 db

随机推荐

  • 在 Access 2013 中使用 VBA 打开 Word 文档

    我正在使用 Access 2013 并在表单上创建了一个帮助按钮 我想打开带有说明的 Word 文档 这是我尝试过的代码 Private Sub cmdHelp Click Dim wrdApp As Word Application Di
  • 如何在单元格中显示进度?

    我使用代码didSelectRowAt indexPath 要开始在单元格上下载文件 请单击 我使用代码cellForRowAt indexPath 显示现在下载文件的进度 class TableViewController UITable
  • 过渡在 IE 中不起作用

    我正在开发自己的网站 它的 功能 之一是当我将鼠标悬停在标题上时 它会向下滑动 这在所有主流浏览器上都运行良好 但是 对于 IE 10 情况并非如此 这是页面来源 这是包含的头文件
  • C 函数参数中的 __cdecl 有什么用

    我正在学习C语言 在学习的过程中我发现了一行对我来说全新且陌生的代码void PullDown char int void cdecl void 我只知道第一个和第二个参数 我想知道第三个参数 cdecl 之后的两个星号有什么用 我从这个语
  • 通过 WordPress 简码将自定义文本添加到联系表单 7

    我正在使用联系表单 7 需要在表单的某处添加自定义文本 我从高级自定义字段的子字段中使用 PHP 获取自定义文本 我知道 有一个名为 Contact Form 7 Dynamic Text Extension 的额外插件 https de
  • 使用 FileReader 的 readAsBinaryString 和 readAsText 之间的区别

    举个例子 当我读到 字符时 u03C0 从使用 FileReader API 的文件中 当我使用以下命令读取它时 我会得到 pi 字符FileReader readAsText blob 这是预期的 但是当我使用FileReader rea
  • 在 JavaScript 中将 RSS pubDate 解析为 Date 对象

    我该怎么做 2010 年 2 月 2 日星期二 19 34 21 等 GMT 它开箱即用 JavaScript 中的 Date 对象可以通过传递一些标准时间格式来设置 RSS 中使用的格式就是其中之一 Example var pubDate
  • Java 函数的递归版本在第一次调用时比迭代慢,但之后更快。为什么是这样?

    对于一项作业 我目前正在尝试测量矩阵链问题的迭代解决方案与递归解决方案之间的性能 空间 时间 差异 问题的要点和我用于迭代版本的解决方案可以在这里找到 http www geeksforgeeks org dynamic programmi
  • R 日期时间序列缺失值

    我正在从 chr 转换为格式为 Y m d H M S 的 POSIXct 但是 数据集中的某些时间没有秒部分 S 因此当我转换为DateTime 不带秒的时间将作为空单元格返回 NA我如何确保这种情况不会发生 我希望它们全部作为 Date
  • 使用实体框架 Code First 进行事务处理

    有一个答案here https stackoverflow com questions 815586 entity framework using transactions or savechangesfalse and acceptall
  • 使用签名检测 PDF 更改

    我正在开发一个 Web 应用程序 允许用户下载 PDF 文件 他们必须使用其证书使用 Adob e Acrobat 对该文件进行签名 然后上传回网络 我在用着C and itextsharp 5 5 9 0用于所有与 PDF 相关的工作 现
  • 链接服务器“(null)”的 OLE DB 提供程序“Microsoft.ACE.OLEDB.12.0”

    我正在尝试运行以下语句 但收到下面的错误消息 我无休无止地研究答案 但没有一个对我有用 我正在运行 Office 365 64 位 我已经加载了 Microsoft Access 数据库引擎 64 位 这是在带有 SSDT 的 Visual
  • Octave 中行向量的转置导致字符串转义字符出现问题

    在 Sublime 中 我尝试对 Octave 文件中的行向量进行转置 如下所示 y 4 5 6 y transpose y 但是每当我尝试在 Octave 中运行它时 它的行为就好像转置运算符 的引入是字符串的开头 并且忽略以下代码行 我
  • Openssl 显示不同的服务器证书,而浏览器显示正确

    我正在使用 openssl s client showcerts connect test abc com 443 state debug 检查服务器证书 服务器使用的是nginx 但是当我请求上述 openssl 时 服务器证书显示为 x
  • 应用程序因 DispatchSemaphore wait() 冻结

    我创建了一个函数 getFriends 它从 firestore 读取用户的好友列表 并将每个好友放入 LocalUser 对象 这是我的自定义用户类 中 以便在表格视图中显示好友列表 我需要 DispatchSemaphore wait
  • CAML 查询:如何从结果集中过滤文件夹?

    我使用 caml 查询来选择用户修改或添加的所有文档 查询在指定网站集的所有子网站上递归运行 现在的问题是我无法删除也是结果集一部分的文件夹 现在我正在从结果数据表中过滤它们 但我想知道 是否可以仅使用 caml 从结果集中过滤掉文件夹 这
  • 适用于 iPhone 的 Sparrow 或 Cocos2D 2D 游戏?

    我想为 iPhone 开发一款游戏 对于 iPhone 中的 2D 游戏开发 从长远来看 哪一个会更好 Sparrow 还是 Cocos2D 我看到 Sparrow 框架的文档很少 但 Sparrow 论坛表示与 Cocos2D 相比 在
  • 有没有办法加快 MATLAB 中的串联速度?

    我想沿着三维连接 z cat 3 A B C 很多很多次 如果我沿着第二个维度这样做的话 z A B C 会比 z cat 2 A B C 可以在三维空间上完成类似的事情吗 或者有其他方法可以加快速度吗 有一些索引选项可以获得比cat 3
  • Kubernetes 检查“silent”pod 是否完成执行

    假设我定义了一个 pod 它只运行几段代码 然后退出 我需要确保该 Pod 退出 然后才能允许其他 Pod 运行 实现这一点的最佳方法是什么 我曾经通过执行网络请求来检查 pod 是否准备好 例如一旦准备好 一些 webapps pod 将
  • 为什么 .paintComponent() 定义在 JComponent 上?

    很抱歉 如果我的问题由于是理论上的问题而无法适应 Stack Overflow 的要求 但我不知道还能问哪里 在过去的几周里 我一直在尝试更好地了解 Swing API 的工作原理及其组件 以便创建我自己的自定义组件 我读过大量的教程 在这