Java Swing - Repaint() 无法正常工作

2024-04-06

我从以下位置获取程序这个话题 https://stackoverflow.com/questions/8693342/drawing-a-simple-line-graph-in-java。我尝试在实时模式下编辑点。我将 MouseMotionListener 添加到构造函数中,并编写一些基本函数来接近鼠标点并编辑该点。当我在构造函数中得到 (x,y) 点时,repaint()工作起来很奇怪。当我得到 (x,y) 点时paintComponent, repaint()根本不起作用。所以,这是在构造函数和中获取 (x,y) 的图像paintComponent。我的错误在哪里?

package simplegrapher2;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleGrapher2 extends JPanel {

    private int width = 800;
    private int heigth = 400;
    private int padding = 25;
    private int labelPadding = 25;
    private Color lineColor = new Color(44, 102, 230, 180);
    private Color pointColor = new Color(100, 100, 100, 180);
    private Color gridColor = new Color(200, 200, 200, 200);
    private static final Stroke GRAPH_STROKE = new BasicStroke(2f);
    private int pointWidth = 4;
    private int numberYDivisions = 10;
    private List<Double> scores;
    private static double serieX = 0;
    public List<Point2D.Double> graphPoints;

    public SimpleGrapher2(List<Double> scores) {
        this.scores = scores;
        addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent me) {
                double x = me.getX();
                double y = me.getY();
                findNearPoint(x, y);
                editSerie(x, y);
                revalidate();
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent me) {}
        });

        double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
        double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

        graphPoints = new ArrayList<>();
        for (int i = 0; i < scores.size(); i++) {
            double x1 = (double) (i * xScale + padding + labelPadding);
            double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
            graphPoints.add(new Point2D.Double(x1, y1));
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        /*double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
        double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

        graphPoints = new ArrayList<>();
        for (int i = 0; i < scores.size(); i++) {
            double x1 = (double) (i * xScale + padding + labelPadding);
            double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
            graphPoints.add(new Point2D.Double(x1, y1));
        }*/

        // draw white background
        g2.setColor(Color.WHITE);
        g2.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding - labelPadding);
        g2.setColor(Color.BLACK);

        // create hatch marks and grid lines for y axis.
        for (int i = 0; i < numberYDivisions + 1; i++) {
            int x0 = padding + labelPadding;
            int x1 = pointWidth + padding + labelPadding;
            int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);
            int y1 = y0;
            if (scores.size() > 0) {
                g2.setColor(gridColor);
                g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1);
                g2.setColor(Color.BLACK);
                String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + "";
                FontMetrics metrics = g2.getFontMetrics();
                int labelWidth = metrics.stringWidth(yLabel);
                g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3);
            }
            g2.drawLine(x0, y0, x1, y1);
        }

        // and for x axis
        for (int i = 0; i < scores.size(); i++) {
            if (scores.size() > 1) {
                int x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding;
                int x1 = x0;
                int y0 = getHeight() - padding - labelPadding;
                int y1 = y0 - pointWidth;
                if ((i % ((int) ((scores.size() / 20.0)) + 1)) == 0) {
                    g2.setColor(gridColor);
                    g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding);
                    g2.setColor(Color.BLACK);
                    String xLabel = i + "";
                    FontMetrics metrics = g2.getFontMetrics();
                    int labelWidth = metrics.stringWidth(xLabel);
                    g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3);
                }
                g2.drawLine(x0, y0, x1, y1);
            }
        }

        // create x and y axes 
        g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding);
        g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding);

        Stroke oldStroke = g2.getStroke();
        g2.setColor(lineColor);
        g2.setStroke(GRAPH_STROKE);
        for (int i = 0; i < graphPoints.size() - 1; i++) {
            double x1 = graphPoints.get(i).x;
            double y1 = graphPoints.get(i).y;
            double x2 = graphPoints.get(i + 1).x;
            double y2 = graphPoints.get(i + 1).y;
            g2.draw(new Line2D.Double(x1, y1, x2, y2));
        }

        g2.setStroke(oldStroke);
        g2.setColor(pointColor);
        for (int i = 0; i < graphPoints.size(); i++) {
            double x = graphPoints.get(i).x - pointWidth / 2;
            double y = graphPoints.get(i).y - pointWidth / 2;
            int ovalW = pointWidth;
            int ovalH = pointWidth;
            //g2.fillOval(x, y, ovalW, ovalH);
        }
    }

    public void findNearPoint(double x, double y) {
        double delta = 0;
        for (int j = 0; j < graphPoints.size(); j++) {
            double sx = graphPoints.get(j).x;
            double sy = graphPoints.get(j).y;
            double root = sqrt((x-sx)*(x-sx) + (y-sy)*(y-sy));
            if (j == 0) {
                delta = root;
                serieX = sx;
            }
            else if (root < delta) {
                serieX = sx;
                delta = root;
            }
        }
    }

    public void editSerie(double x, double y) {
        double tmpSerieX = serieX;
        int ind = 0;
        for (int i = 0; i < graphPoints.size(); i++) {
            if (graphPoints.get(i).x == tmpSerieX) {
                ind = i;
            }
        }
        graphPoints.remove(ind);
        graphPoints.add(ind, new Point2D.Double(x, y));
        serieX = x;
    }

    private double getMinScore() {
        double minScore = Double.MAX_VALUE;
        for (Double score : scores) {
            minScore = Math.min(minScore, score);
        }
        return minScore;
    }

    private double getMaxScore() {
        double maxScore = Double.MIN_VALUE;
        for (Double score : scores) {
            maxScore = Math.max(maxScore, score);
        }
        return maxScore;
    }

    public void setScores(List<Double> scores) {
        this.scores = scores;
        invalidate();
        this.repaint();
    }

    public List<Double> getScores() {
        return scores;
    }

    private static void createAndShowGui() {
        List<Double> scores = new ArrayList<>();
        Random random = new Random();
        int maxDataPoints = 40;
        int maxScore = 10;
        for (int i = 0; i < maxDataPoints; i++) {
            scores.add((double) random.nextDouble() * maxScore);
        }
        SimpleGrapher2 mainPanel = new SimpleGrapher2(scores);
        mainPanel.setPreferredSize(new Dimension(800, 600));
        JFrame frame = new JFrame("DrawGraph");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

当您计算时,问题出在您的构造函数中x/yScale...

public SimpleGrapher2(List<Double> scores) {
    //...
    double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
    double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());
    //...
}

在构建组件时,组件的大小为0x0。在计算点之前,您需要等到组件以某种有意义的方式调整大小......

这也是有问题的,因为当组件首次在屏幕上实现时,可能会快速连续地多次调整其大小。

我过去所做的是使用 SwingTimer设置为较小的延迟以允许在较小的时间范围内多次调整组件的大小。当一切都安顿下来之后Timer将触发,您可以执行所需的操作,例如...

public SimpleGrapher2(List<Double> scores) {
    //...
    addComponentListener(new ComponentAdapter() {

        private Timer initTimer = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                initTimer.stop();
                double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
                double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

                graphPoints = new ArrayList<>();
                for (int i = 0; i < scores.size(); i++) {
                    double x1 = (double) (i * xScale + padding + labelPadding);
                    double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
                    graphPoints.add(new Point2D.Double(x1, y1));
                }
                repaint();
            }
        });

        @Override
        public void componentResized(ComponentEvent e) {
            if (graphPoints == null) {
                initTimer.restart();
            }
        }

    });

}

这一切所做的就是等待,直到计时器之间compoentResized事件超过 200 毫秒(您可以使用此值使其更接近您想要的值,但我发现大约 250 毫秒是合理的延迟)

您将需要更正paintComponent允许graphPoints been null以及。

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

Java Swing - Repaint() 无法正常工作 的相关文章

  • Grails 3.x bootRun 失败

    我正在尝试在 grails 3 1 11 中运行一个项目 但出现错误 失败 构建失败并出现异常 什么地方出了错 任务 bootRun 执行失败 进程 命令 C Program Files Java jdk1 8 0 111 bin java
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项

随机推荐

  • 什么会导致 Hibernate InvalidStateException

    即使我的模型类中没有验证约束 所有成员变量都已正确设置 但我仍然在对象创建时遇到此异常 我还是收到此错误 我该如何调试这个错误 javax el ELException org hibernate validator InvalidStat
  • 如何覆盖MUI芯片中的标签样式

    我正在将 React 与 MUI 库一起使用 我使用的 MUI 组件是 Chip 而在这个Chip 有标签属性 您可以选择在芯片中显示文本字段 就像下面这样 我一直在尝试覆盖 阿凡达 文本的样式 在Chip通过使用假定的 MUI 全局样式
  • 即使类不可用, NSClassFromString() 也会返回一个类

    我目前正在运行 iOS 4 0 的 iPhone 3G 上测试一个应用程序 我有以下代码来检查该类是否可用 if NSClassFromString CLGeocoder 在文档中 它指出 CLGeocoder 可用于 iOs 5 0 及更
  • 在iOS中查找rootViewController

    在 ShareKit 中 代码需要确定 rootViewController 的位置 以便它可以显示模式视图 由于某种原因 代码在 iOS 5 中失败 Try to find the root view controller program
  • Java JTable 使用 TableCellRenderer 排序

    我对 Java 有点陌生 并且遇到了一些问题JTable与排序和TableCellRenderer 我有一个包含 15 列的表 其中填充了值 在某些列上我使用TableCellRenderer根据单元格上的值将前景颜色更改为绿色或红色 一切
  • RSpec & Rails:用于翻译助手的存根 @virtual_path 来测试应用程序助手

    我有一个帮手page title default in ApplicationHelper def page title default options t title options end 现在我想像这样测试它 describe pag
  • 格式化 JEditorPane 的光标、工具提示、链接

    现在 我正在使用 Java Swing 创建 JEditorPane 主要是因为它具有超链接的能力 我已经成功地能够显示链接并让它们在单击时执行行为 但是我遇到了一些格式问题 如何设置光标 使其通常为箭头 但将鼠标悬停在文本上时更改为文本光
  • Angular $state.go {reload: true} 不应重新初始化抽象父控制器

    我正在使用 ui route 进行导航 我有一个叫做父亲的国家main 这是一个abstract状态 网址 main 和子状态products and users urls 主要产品 and 主 用户 app config statePro
  • 方程编号与 Rmarkdown 中的预览到 pdf?

    在 Rmarkdown 中 编织为 PDF 如果我写一个等式 begin equation y x 2 end equation 然后我在 PDF 输出中得到一个编号方程 如果我写一个等式 y x 3 那么方程就没有编号 我喜欢能够控制哪些
  • 如何阅读/改进 PHP 计算的 C.R.A.P 指数

    我刚刚开始使用 PHPUnit 及其丰富多彩的代码覆盖率报告 我了解所有的数字和百分比 除了一个 C R A P 指数 谁能给我一个可靠的解释 解释它的含义 如何分析它以及如何降低它 Toader Mihai 提供了可靠的解释 https
  • 如何使用 docker-compose 重启单个容器

    我有一个docker compose yml包含 4 个容器的文件 redis postgres api and worker 在开发过程中worker容器 我经常需要重新启动它才能应用更改 有什么好的方法可以重新启动单个容器 例如work
  • 如何检查一个字符是否等于一个空格?

    这是我所得到的 private static int countNumChars String s for char c s toCharArray if Equals c 但该代码表示 找不到该方法的符号 我记得 Java 有一个这样的比
  • 基本路径覆盖有什么意义?

    文章位于onjava http www onjava com pub a onjava 2007 03 02 statement branch and path coverage testing in java html page 2似乎意
  • 无法在 Win 7 Prof 上以 64 位模式运行 CMD

    我已经完成了我的作业 诚实地尝试了我能想到的一切 但似乎每次我打开 CMD 时 我都会得到 32 位版本 无论我从哪里打开它 我努力了 Windows 启动 orb gt CMD gt 输入 输入 C Windows System32 cm
  • 尝试启动 TunnelProvider 网络扩展时出现 NEVPNErrorDomain 错误 1

    我正在尝试通过从 TunnelProvider 的 XCode 模板开始 然后将代码添加到主机应用程序来配置并启动它来制作自定义 TunnelProvider 网络扩展 我正在使用 NETunnelProviderManager 的实例来配
  • 如何使用冒泡排序在 Python 3 中对列表进行排序和子排序

    我正在为我正在学习的课程解答一个额外问题 假设我们有一个列表 例如mylist a1 b2 a3 c1 b1 a5 b3 c9 我想使用基本的Python而不导入任何东西 我想首先按字母顺序对列表进行排序 然后对于每个字母 我按数字排序 因
  • 拖放到桌面图标上

    我想这应该很简单 我在这里看过类似的问题 但我的旧大脑并不清楚它应该如何工作 我有一个 Windows 窗体应用程序 我的用户想要将文件拖到桌面上的应用程序图标上 并使用该文件执行程序 所以我想做的是 接受图标上放置的文件 启动应用程序并将
  • App Engine 从 JsonProperty 返回 JSON

    我喜欢如何JsonProperty当属性放入数据存储时 自动将 Python 结构编码为 JSON 并在检索时自动解码 但是 最好将该 JSON 数据发送到 Web 浏览器 而无需再次对其进行编码 有没有办法获取原始 JSON 数据 即阻止
  • 线程本地存储开销

    假设有一些不可重入函数使用全局变量 int i void foo void modify i 然后 我想在多线程代码中使用这个函数 所以我可以这样更改代码 void foo int i modify i 或者 通过使用 gcc thread
  • Java Swing - Repaint() 无法正常工作

    我从以下位置获取程序这个话题 https stackoverflow com questions 8693342 drawing a simple line graph in java 我尝试在实时模式下编辑点 我将 MouseMotion