如何使用线程实现缓动函数

2023-12-02

我试图找到一种有效、正常或简单的方法来在我的 java 程序中实现缓动函数。我让缓动功能可以工作,但我觉得有一种更有效的方法来做到这一点;我看不到的,可能是因为视野狭隘。这是我的代码;有人可以告诉我应该采取哪些不同的做法,或者指出我需要研究的方向

public class slide extends JPanel implements Runnable {

    Thread ease = new Thread(this);
    float total = 0;
    float dur;

    slide() {

        ease.start();
        setLayout(null);

    }

    public float calc(float t, float b, float c, float d) {

        return c * t / d + b;

    }

    public void run() {
        while (true) {
            try {
                if (total < 50) {
                    total += 1;
                } else {
                    ease.stop();
                }
                setBounds(400, Math.round(200 * total / 50 + 0), 250, 150);
                repaint();
                System.out.println(total + " " + dur);
                ease.sleep(10);
            } catch (Exception e) {
            }
        }

    }
}

我尝试为我在网上找到的线性缓动函数实现 calc() 方法,但它实际上毫无用处,因为我被迫无法让它工作,除非将方程直接插入到


好的,动画是一个相当复杂和深入的主题,我不会在这里讨论,它还涉及很多我不太理解的数学,所以我们不会深入讨论深度或细节,有比我更好的人可以解释它,你可以在网上阅读它

首先,我们做出一些假设......

动画是随时间变化的,其中时间是可变的。缓动是(在本例中)速度随时间的变化。这意味着动画的速度对于任何给定的时间点都是可变的。

基本上,我们想要做的就是“正常化”一切。也就是说,在动画开始时,时间为 0,结束时为 1,其间的所有其他值都是这两个值之间的分数。

如果你能这样想,事情就变得容易多了。因此,根据时间线上的给定点,您可以决定应该做什么。例如,在 50% 的情况下,您应该位于起点和终点之间的中间位置

好吧,但是这一切对我们有什么帮助呢?如果我们要绘制缓入和缓出动画的图表,它看起来会像......

BellCurve

其中 x 轴是时间,y 轴是速度(两个轴上的值都在 0 和 1 之间)。因此,在沿 x(时间)的任何给定点,我们应该能够计算速度。

现在,我们可以使用贝塞尔脊柱/曲线的一些数学方法来完成此操作,并计算对象在时间轴上给定点的速度。

现在,我直接从Timing Framework借用了大部分代码,但如果你真的感兴趣,你也可以看看游戏的贝塞尔曲线:教程

(注:我实际上确实写了这样的东西,然后两天后,发现计时框架已经实现了......是一个有趣的练习......)

现在,关于此实现需要注意的重要一点是,它实际上不会返回对象的速度,但它会返回沿时间线 (0-1) 的时间进度,好吧,这听起来很奇怪,但它是什么允许您做的是计算起点和终点之间的当前位置(startValue + ((endValue - startValue) * progress))沿着时间线

我不会详细介绍这一点,因为我真的不懂数学,我只是知道如何应用它,但基本上,我们计算沿曲线的点 (x/y),我们然后将这些值标准化(0-1)以便于查找。

The interpolate方法使用二分搜索来查找给定时间段内最接近的匹配点,然后计算该点的速度/y 位置

public class SplineInterpolator {

    private final double points[];
    private final List<PointUnit> normalisedCurve;

    public SplineInterpolator(double x1, double y1, double x2, double y2) {
        points = new double[]{ x1, y1, x2, y2 };

        final List<Double> baseLengths = new ArrayList<>();
        double prevX = 0;
        double prevY = 0;
        double cumulativeLength = 0;
        for (double t = 0; t <= 1; t += 0.01) {
            Point2D xy = getXY(t);
            double length = cumulativeLength
                            + Math.sqrt((xy.getX() - prevX) * (xy.getX() - prevX)
                                            + (xy.getY() - prevY) * (xy.getY() - prevY));

            baseLengths.add(length);
            cumulativeLength = length;
            prevX = xy.getX();
            prevY = xy.getY();
        }

        normalisedCurve = new ArrayList<>(baseLengths.size());
        int index = 0;
        for (double t = 0; t <= 1; t += 0.01) {
            double length = baseLengths.get(index++);
            double normalLength = length / cumulativeLength;
            normalisedCurve.add(new PointUnit(t, normalLength));
        }
    }

    public double interpolate(double fraction) {
        int low = 1;
        int high = normalisedCurve.size() - 1;
        int mid = 0;
        while (low <= high) {
            mid = (low + high) / 2;

            if (fraction > normalisedCurve.get(mid).getPoint()) {
                low = mid + 1;
            } else if (mid > 0 && fraction < normalisedCurve.get(mid - 1).getPoint()) {
                high = mid - 1;
            } else {
                break;
            }
        }
        /*
         * The answer lies between the "mid" item and its predecessor.
         */
        final PointUnit prevItem = normalisedCurve.get(mid - 1);
        final double prevFraction = prevItem.getPoint();
        final double prevT = prevItem.getDistance();

        final PointUnit item = normalisedCurve.get(mid);
        final double proportion = (fraction - prevFraction) / (item.getPoint() - prevFraction);
        final double interpolatedT = prevT + (proportion * (item.getDistance() - prevT));
        return getY(interpolatedT);
    }

    protected Point2D getXY(double t) {
        final double invT = 1 - t;
        final double b1 = 3 * t * invT * invT;
        final double b2 = 3 * t * t * invT;
        final double b3 = t * t * t;
        final Point2D xy = new Point2D.Double((b1 * points[0]) + (b2 * points[2]) + b3, (b1 * points[1]) + (b2 * points[3]) + b3);
        return xy;
    }

    protected double getY(double t) {
        final double invT = 1 - t;
        final double b1 = 3 * t * invT * invT;
        final double b2 = 3 * t * t * invT;
        final double b3 = t * t * t;
        return (b1 * points[2]) + (b2 * points[3]) + b3;
    }

    public class PointUnit {

        private final double distance;
        private final double point;

        public PointUnit(double distance, double point) {
            this.distance = distance;
            this.point = point;
        }

        public double getDistance() {
            return distance;
        }

        public double getPoint() {
            return point;
        }

    }

}

如果我们做类似的事情...

SplineInterpolator si = new SplineInterpolator(1, 0, 0, 1);
for (double t = 0; t <= 1; t += 0.1) {
    System.out.println(si.interpolate(t));
}

我们得到类似...

0.0
0.011111693284790492
0.057295031944523504
0.16510933001160544
0.3208510585798438
0.4852971690762217
0.6499037832761319
0.8090819765428142
0.9286158775101805
0.9839043020410436
0.999702

好吧,现在您可能会想,“等一下,这是一个线性级数!”,但事实并非如此,如果您将其绘制成图表,您会发现前三个和后三个值非常接近,而其他值则分散不同程度地出现,这是我们的“进步”值,我们应该沿着时间线走多远

所以现在,你的头应该快要爆炸了(我的是)——这就是为什么我说,使用框架!

但你会如何使用它?这是有趣的部分,现在记住,一切都是可变的,动画的持续时间,对象随时间的速度,刻度或更新的数量,都是可变的......

这很重要,因为这就是这样的东西的力量所在!例如,如果动画由于某些外部因素而停止,则此实现能够简单地跳过这些“帧”,而不是遇到瓶颈和令人震惊。这听起来可能是一件坏事,但相信我,这都是为了欺骗眼睛“认为”某些东西正在发生变化;)

(下面大概是8fps,所以相当蹩脚)

Animate

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private int startAt = 0;
        private int endAt;
        private int x = startAt;
        private Timer timer;
        private SplineInterpolator splineInterpolator;
        private long startTime = -1;
        private long playTime = 5000; // 5 seconds

        public TestPane() {
            splineInterpolator = new SplineInterpolator(1, 0, 0, 1);
            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime < 0) {
                        startTime = System.currentTimeMillis();
                    }
                    long now = System.currentTimeMillis();
                    long duration = now - startTime;
                    double t = (double) duration / (double) playTime;
                    if (duration >= playTime) {
                        t = 1;
                    }

                    double progress = splineInterpolator.interpolate(t);

                    x = startAt + ((int) Math.round((endAt - startAt) * progress));
                    repaint();
                }
            });
            timer.setInitialDelay(0);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (!timer.isRunning()) {
                        startTime = -1;
                        startAt = 0;
                        endAt = getWidth() - 10;
                        timer.start();
                    }
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.fillRect(x, (getHeight() / 2) - 5, 10, 10);
            g2d.dispose();
        }

    }

    public static class SplineInterpolator {

        private final double points[];
        private final List<PointUnit> normalisedCurve;

        public SplineInterpolator(double x1, double y1, double x2, double y2) {
            points = new double[]{x1, y1, x2, y2};

            final List<Double> baseLengths = new ArrayList<>();
            double prevX = 0;
            double prevY = 0;
            double cumulativeLength = 0;
            for (double t = 0; t <= 1; t += 0.01) {
                Point2D xy = getXY(t);
                double length = cumulativeLength
                                + Math.sqrt((xy.getX() - prevX) * (xy.getX() - prevX)
                                                + (xy.getY() - prevY) * (xy.getY() - prevY));

                baseLengths.add(length);
                cumulativeLength = length;
                prevX = xy.getX();
                prevY = xy.getY();
            }

            normalisedCurve = new ArrayList<>(baseLengths.size());
            int index = 0;
            for (double t = 0; t <= 1; t += 0.01) {
                double length = baseLengths.get(index++);
                double normalLength = length / cumulativeLength;
                normalisedCurve.add(new PointUnit(t, normalLength));
            }
        }

        public double interpolate(double fraction) {
            int low = 1;
            int high = normalisedCurve.size() - 1;
            int mid = 0;
            while (low <= high) {
                mid = (low + high) / 2;

                if (fraction > normalisedCurve.get(mid).getPoint()) {
                    low = mid + 1;
                } else if (mid > 0 && fraction < normalisedCurve.get(mid - 1).getPoint()) {
                    high = mid - 1;
                } else {
                    break;
                }
            }
            /*
             * The answer lies between the "mid" item and its predecessor.
             */
            final PointUnit prevItem = normalisedCurve.get(mid - 1);
            final double prevFraction = prevItem.getPoint();
            final double prevT = prevItem.getDistance();

            final PointUnit item = normalisedCurve.get(mid);
            final double proportion = (fraction - prevFraction) / (item.getPoint() - prevFraction);
            final double interpolatedT = prevT + (proportion * (item.getDistance() - prevT));
            return getY(interpolatedT);
        }

        protected Point2D getXY(double t) {
            final double invT = 1 - t;
            final double b1 = 3 * t * invT * invT;
            final double b2 = 3 * t * t * invT;
            final double b3 = t * t * t;
            final Point2D xy = new Point2D.Double((b1 * points[0]) + (b2 * points[2]) + b3, (b1 * points[1]) + (b2 * points[3]) + b3);
            return xy;
        }

        protected double getY(double t) {
            final double invT = 1 - t;
            final double b1 = 3 * t * invT * invT;
            final double b2 = 3 * t * t * invT;
            final double b3 = t * t * t;
            return (b1 * points[2]) + (b2 * points[3]) + b3;
        }

        public class PointUnit {

            private final double distance;
            private final double point;

            public PointUnit(double distance, double point) {
                this.distance = distance;
                this.point = point;
            }

            public double getDistance() {
                return distance;
            }

            public double getPoint() {
                return point;
            }

        }

    }

}

所以,除了SplineInterpolator,魔法发生在里面ActionListener为了javax.swing.Timer(以及一些在mouseClicked事件处理程序)

基本上,这计算了时间量(duration)动画已经播放,这成为我们的标准化时间t or fraction值(0-1)在时间线上,然后我们用它来计算我们在时间线上的“进度”SplineInterpolator并根据对象的开始位置和结束位置之差乘以当前“进度”来更新对象的位置

if (startTime < 0) {
    startTime = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long duration = now - startTime;
double t = (double) duration / (double) playTime;
if (duration >= playTime) {
    t = 1;
}

double progress = splineInterpolator.interpolate(t);

x = startAt + ((int) Math.round((endAt - startAt) * progress));
repaint();

瞧,我们有一个缓入和缓出动画!

现在,去使用动画框架吧!这真是太简单了:P

  • 对于“快进/慢出”,您可以使用0, 0, 1, 1
  • 对于“慢入/快出”,您可以使用0, 1, 0, 0
  • 对于“慢速”,您可以使用1, 0, 1, 1
  • 对于“慢出”,您可以使用0, 0, 0, 1

(或者至少这些是我使用的值)

实验看看你会得到什么

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

如何使用线程实现缓动函数 的相关文章

  • H.323,如何制作一个没有媒体的简单环。该脚本遵循 Q.931 设置,但仍然无法正常工作

    谁能帮我解决这个问题吗 当我发送此请求时 我在wireshark中看到数据包将发送到1720 tcp端口中的SJPhone 但 SJPhone 仍然没有响铃 我想让它响起 无论媒体 我非常感谢您的支持 我一定缺少消息协议细节来实现这个 请给
  • 如何实现具有LinkedHashMap类似功能的ConcurrentHashMap?

    我用过LinkedHashMap with accessOrdertrue 并同时允许最多 500 个条目作为数据的 LRU 缓存 但由于可扩展性问题 我想转向一些线程安全的替代方案 ConcurrentHashMap在这方面似乎不错 但缺
  • Glassfish:在部署期间修改 EAR 的部署描述符

    经过几天的搜索 尝试和摇头 我将这个问题发布到 SO 尽管它seems已经得到答复 这是场景 我有一个 EAR 应用程序 目前 包含一个 WAR 和一个 EJB 模块 EJB 模块使用 JPA persistence xml 并且一些无状态
  • 如何将抽象工厂与单例模式结合起来? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在用 java 编码 并且对这些模式很陌生 谁能给我一个也使用单例的工厂抽象的例子 这是一个实现类的示例单例模式 这个实现也是线程安全
  • 构建应用程序时出现 BufferOverflowException

    每次我想运行我的 Android 应用程序时 我都会收到错误 2013 11 02 13 05 36 Dex Loader Unable to execute dex java nio BufferOverflowException Che
  • 如何为java注释处理器编写自动化单元测试?

    我正在尝试使用 java 注释处理器 我可以使用 JavaCompiler 编写集成测试 事实上我现在正在使用 hickory 我可以运行编译过程并分析输出 问题 即使我的注释处理器中没有任何代码 单个测试也会运行大约半秒 对于以 TDD
  • 强制 Java 最低版本以“java -version:”运行在 Windows 上不起作用

    我想强制应用程序运行的 JVM 最低版本为 1 6 或更高版本 即 1 6 我的理解是 您可以使用 version 命令行参数来执行此操作 我尝试了一下 在Linux下似乎可以正常工作 但在Windows下却不行 LINUX 我在 Linu
  • Java 中的 MP4 容器编写器

    我想找到一个免费的 Java MP4 容器 编写器 我不需要编码器 只需要能够根据预期值写入正确原子的编码器 Bonus对于这样一个库 也可以编写 有效 F4V 我更喜欢纯 Java 解决方案 而不是使用 JNI 或外部可执行文件的解决方案
  • 无法自动装配 org.springframework.mail.javamail.JavaMailSender

    尝试运行我的应用程序时遇到以下问题 所有的东西都调试过了 还是一无所获 IDE 毫无问题地找到了 bean 所以我对这里发生的情况感到非常困惑 SEVERE Exception sending context initialized eve
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • Java 不可变对象 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在学习不变性的概念 据我了解 一旦创建对象 不可变对象就无法更改其值 但我不明白不可变对象的以下用途 They are 自动是线程
  • Java LRU 缓存使用 LinkedList

    堆栈溢出的新手 所以请不要介意我以菜鸟的方式问这个问题 我正在尝试使用链表实现 LRU 缓存 我在这里看到了使用 linkedHashMap 和其他数据结构的其他实现 但对于这种情况 我正在尝试使用链表创建最佳优化版本 正如我在技术期间被问
  • Java 验证日期为 yyyyMMddHHmmss

    我想在java中验证给定的日期格式为yyyyMMddHHmmss 状况 应符合格式 yyyyMMddHHmmss 它应该验证当前日期 它应该验证与当前小时有 3 小时或 3 小时差异的小时数 如果满足所有三个条件 Java 方法应返回 tr
  • while 之后无法访问的语句[重复]

    这个问题在这里已经有答案了 我只是修改代码 在以下代码中出现错误 int x 1 System out println x x while true x System out println x x 错误在最后一行 我可以知道错误 错误 无
  • ASTParser:解析绑定后查找声明节点

    我创建了一个启用了绑定的 AST 当我稍后解析绑定时 我得到了一个有效的 ITypeBinding 但是 当我想要获取绑定的声明 Node 时 它 总是返回 null 除非 ITypeBinding 在 sourceFile 中声明 这是我
  • 如何在 Log4j2 - JSON 布局中自定义或删除默认属性

    In Spring Boot 2我已配置的应用程序Log4j2 with JsonLayout像下面这样
  • 如何创建具有同等时间元素的 JavaFX 转换?

    我正在尝试 JavaFX 和动画 尤其是PathTransition 我正在创建一个简单的程序 使球 弹跳 而不使用QuadCurveTo班级 到目前为止 这是我的代码 Ellipse ball new Ellipse 375 250 10
  • 获取Java中ResultSet返回的行数

    我用过一个ResultSet返回一定数量的行 我的代码是这样的 ResultSet res getData if res next System out println No Data Found while res next code t
  • 使用 PDFBox 在 Android 中创建 PDF

    我正在尝试通过我的 Android 应用程序创建 PDFPDFBoxapi 但出现以下错误 java lang NoClassDefFoundError org apache pdfbox pdmodel PDDocument 我已经将以下
  • Java 可变 BigInteger 类

    我正在使用 BigIntegers 进行计算 该计算使用一个调用 multiply 大约 1000 亿次的循环 并且从 BigInteger 创建新对象使其非常慢 我希望有人编写或找到了 MutableBigInteger 类 我在 jav

随机推荐

  • 检查 SharePoint 365 中的工作簿是否已锁定进行编辑

    我在 SharePoint 365 中有一个文档库 我使用本地 Excel 宏文件通过 VBA 在线打开 SharePoint 中的工作簿 这适用于类似的代码 location https mycompany sharepoint com
  • 尝试使用 Python 和 Selenium 迭代地滚动和抓取网页

    我最近问了一个问题 参考这里 Python Web 抓取 Beautiful Soup Selenium 和 PhantomJS 仅抓取整个页面的一部分 这有助于确定我在抓取滚动时动态更新的页面的所有内容时遇到的问题 然而 我仍然无法使用
  • 使用pip在django中安装错误

    我是 Django 世界的新手 我想将其从 pip 安装到我的 Windows 中 但在安装时出现此错误 C Users xxxx gt pip install django Collecting django Could not inst
  • 在 Jdbc 中执行带有绑定变量的 SQL 查询

    我有一个这样的sql查询 select DEPT DEPTNO as DEPTNO1 DEPT DNAME as DNAME1 DEPT LOC as LOC1 EMP COMM as COMM1 EMP EMPNO as EMPNO1 E
  • Android:在 webview 中下载在 Oreo 中不起作用,它在 Oreo 设备中强制关闭

    下载管理器代码在 Android 中不起作用WebView适用于 Oreo 设备 但它适用于旧版本 如果不是 Oreo 设备 它会提示 正在下载文件 并被下载 但如果是 Oreo 它会强制关闭 崩溃 下面是我正在使用的代码 片段 webVi
  • 数字后跟大写 L

    什么是512L意思是 或者可能是任何数字后跟大写 L example uint sec然后是一些带有表达式的代码 sec 512L 取出来的XV6代码 mkfs c L代表long 这创建了一个类型的文字long l也可以 但看起来像1 所
  • 连接表上的 where 子句

    对于下表 ROOM ID NAME 1 ROOM 1 2 ROOM 2 房间状态 ID ROOM ID OPEN DATE 1 1 1 2000 01 01 00 00 00 2 2 1 2000 01 01 00 00 00
  • 向现有列添加自动增量,而不影响当前记录值

    我想将列类型更改为AUTO INCREMENT在现有的MyISAM1数据库表 数据库目前有数千条记录 其中列值非常重要 当前值不受影响至关重要 我想从最新的最高值开始递增 我在 phpmyadmin 中尝试了此操作 由 phpmyadmin
  • 编译 SCSS 时出现误报“未定义变量”错误

    使用 ruby compass gem 编译 SCSS 时收到错误消息 run var lib gems 1 8 gems compass 0 12 2 bin compass compile out unchanged sass part
  • 从 python dataframe 列中删除非 json 对象行

    我有一个数据框 该列包含 json 对象和字符串 我想删除不包含 json 对象的行 下面是我的数据框的样子 import pandas as pd df pd DataFrame A hello world a 5 b 6 c 8 usa
  • 仅支持横向界面方向

    我有使用横向右方向的应用程序 在视图控制器中我使用 BOOL shouldAutorotateToInterfaceOrientation UIInterfaceOrientation interfaceOrientation Return
  • 系统 python 版本处于活动状态,而不是本地 pyenv 版本

    激活虚拟环境后如何检查使用的python版本是否正确 我尝试了which python3和which python 但两个输出都指示系统python版本而不是本地pyenv版本 它仍在使用我的本地版本还是我的安装有问题 这是命令行输出 Do
  • 如何根据 ViewModel 属性值添加淡入/淡出动画?

    我有一个视图模型它公开了字符串属性页面工具栏可见这可以是true or false private string pageToolBarVisible public string PageToolBarVisible get return
  • 有什么方法可以修改 JavaScript 中的“this”吗?

    我找到了这个答案 如何在javascript中修改 this 但我不喜欢它 肯定有办法somehow modify this 这是一个例子 function var a function v v 10 a function console
  • 标题栏颜色变化问题

    我想动态更改标题栏的颜色 即 有人单击按钮 它会更改颜色 但是 我似乎无法让它填满整个标题栏 这种情况在模拟器和 Nexus One 上都会发生 有任何想法吗
  • 在 Spark 中提取 hive 表分区 - java

    Spark 有没有办法只提取分区列名称 我使用的解决方法是运行 show extended table like table name using HiveContext 你可以使用类HiveMetaStore客户端直接查询HiveMeta
  • Pandas:对 NaN 值进行“或”运算

    我有一个包含 3 列的 DataFrame 每列的值为NaN 我想根据这 3 列填充第四列 这样or操作应用于列 如果第一个不是NaN 取其值 否则检查第二个 依此类推 自从一个NaN值不是一个False the or运算符不能按原样使用
  • 如何检测区域上方和下方的点?

    我有这个图像 其中红点是划分该阿拉伯语词段的不同字母的坐标 我想检测点之间区域上方或下方的点 点是 从左到右 81 183 80 217 83 275 83 314 现在字母上方有一个点 81 183 and 80 217 同样 上面的部分
  • 输入要读取的自定义文件名?

    我想允许用户键入要读取 写入的任何 txt 文件的名称 这是我的代码 printf Enter txt file name n scanf s fname FILE inputf inputf fopen fname w 问题是此方法不起作
  • 如何使用线程实现缓动函数

    我试图找到一种有效 正常或简单的方法来在我的 java 程序中实现缓动函数 我让缓动功能可以工作 但我觉得有一种更有效的方法来做到这一点 我看不到的 可能是因为视野狭隘 这是我的代码 有人可以告诉我应该采取哪些不同的做法 或者指出我需要研究