主頁 > 區塊鏈 > 如何使用JavaFxAnimationTimer制作流暢的基于時間的影片?

如何使用JavaFxAnimationTimer制作流暢的基于時間的影片?

2022-03-25 23:03:02 區塊鏈

我正在使用 JavaFX 制作一個非常簡單的影片。我的目標只是讓一個矩形在視窗中平滑移動。

我正在嘗試使用 來實作這一點AnimationTimer,這似乎適合該任務。我嘗試了不同的渲染方式,例如 a Rectanglein anAnchorPane或簡單地繪制到 a 上Canvas,但最終它總是歸結為相同的東西,具有相同的結果。

我基本上存盤我的矩形的位置,并在每一幀對其應用移動速率。

事實上,當我在我的handle方法中使用恒定移動速率時AnimationTimer,影片非常流暢。但是,這種技術存在兩個問題:

  1. 幀速率似乎與平臺有關,沒有簡單的方法來控制它。所以影片會在不同的機器上呈現不同的效果。
  2. 幀率有時會發生變化,例如在調整視窗大小時,它有時會下降一半,有時甚至會加倍,這會相應地改變影片速度。

所以我嘗試通過使用AnimationTimer.handle(long now). 它解決了不一致的問題,但影片現在很緊張!每秒幾次,矩形似乎會向前“跳躍”幾個像素,然后停頓一兩幀以恢復其預期位置。隨著速度的提高,它變得越來越明顯。

這是相關的代碼(簡化):

AnimationTimer anim = new AnimationTimer() {
  private long lastRun = 0;
  
  @Override
  public void handle(long now) {
    //Ignore first frame as I'm not sure of the timing here
    if (lastRun == 0) {
      lastRun = now;
      return;
    }
    //Now we've got a reference, so let's animate
    double elapsed = (now - lastRun) / 1e9; //Convert to seconds
    //Update position according to speed
    position = position.add(speed.multiply(elapsed)); //Apply speed in pixels/second
    lastRun = now; //Store current time for next loop
    draw();
  }
};

我試圖記錄時間差異、幀速率和位置。嘗試了一些不同的修復,使我的代碼總是更復雜但沒有任何結果。

根據您的評論編輯 2022-03-15(謝謝)

I've tried this on my usual computer (Win 10, Xeon processor, 2 Geforce 1050Ti GPUs), and also on a Microsoft Surface Go 3 tablet under Windows 11. I've tried it using Java 17.0.1 (Temurin) and JavaFX 17.0.1, as well as JDK 8u211 with the same results.

Using JVM argument -Djavafx.animation.pulse=10 has no effect whatsoever other than showing "Setting PULSE_DURATION to 10 hz" in stderr. -Djavafx.animation.framerate=10 doesn't do a thing.

End of edit

I can't figure out what I'm doing wrong here. Can you please help me out ?

Here's my entire code : (Edited on 2022-03-15 to include FPS-meter)

import java.math.BigDecimal;
import java.math.RoundingMode;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;

public class TestFxCanvas2 extends Application {

  // Set your panel size here
  private static final int FRAME_WIDTH = 800;
  private static final int FRAME_HEIGHT = 800;

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

  @Override
  public void start(Stage stage) throws Exception {
    BorderPane root = new BorderPane();
    MyAnimation2 myAnimation = new MyAnimation2();
    myAnimation.widthProperty().bind(root.widthProperty());
    myAnimation.heightProperty().bind(root.heightProperty());
    root.setCenter(myAnimation);
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.setWidth(FRAME_WIDTH);
    stage.setHeight(FRAME_HEIGHT);

    stage.show();
  }
}

class MyAnimation2 extends Canvas {

  private static final double SPEED = 500; // Speed value to be applied in either direction in px/s
  private static final Point2D RECT_DIMS = new Point2D(50, 50); // rectangle size
  // Canvas painting colors
  private static final Paint BLACK = Paint.valueOf("black");
  private static final Paint RED = Paint.valueOf("red");
  private static final Paint GREEN = Paint.valueOf("ForestGreen");

  // Defines rectangle start position
  private Point2D recPos = new Point2D(0, 300);
  // Stores previous position
  private Point2D oldPos = new Point2D(0, 0);

  // Current speed
  private Point2D speed = new Point2D(SPEED, 0);

  public MyAnimation2() {

    AnimationTimer anim = new AnimationTimer() {
      private long lastRun = 0;

      long[] frameTimes = new long[10];
      long frameCount = 0;

      @Override
      public void handle(long now) {
        // Measure FPS
        BigDecimal fps = null;
        int frameIndex = (int) (frameCount % frameTimes.length);
        frameTimes[frameIndex] = now;
        if (frameCount > frameTimes.length) {
          int prev = (int) ((frameCount   1) % frameTimes.length);
          long delta = now - frameTimes[prev];
          double fr = 1e9 / (delta / frameTimes.length);
          fps = new BigDecimal(fr).setScale(2, RoundingMode.HALF_UP);
        }
        frameCount  ;
        // Skip first frame but record its timing
        if (lastRun == 0) {
          lastRun = now;
          return;
        }
        // Animate
        double elapsed = (now - lastRun) / 1e9;
        // Reverse when hitting borders
        if (hitsBorders())
          speed = speed.multiply(-1.);
        // Update position according to speed
        oldPos = recPos;
        recPos = recPos.add(speed.multiply(elapsed));
        lastRun = now;
        draw(oldPos, recPos, fps);
      }
    };

    // Start
    anim.start();
  }

  private void draw(Point2D oldPos, Point2D recPos, BigDecimal fps) {
    GraphicsContext gfx = this.getGraphicsContext2D();
    // Clear and draw border
    gfx.setStroke(BLACK);
    gfx.setLineWidth(1);
    gfx.clearRect(0, 0, getWidth(), getHeight());
    gfx.strokeRect(0, 0, getWidth(), getHeight());
    // Draw moving shape
    gfx.setFill(RED);
    gfx.fillRect(recPos.getX(), recPos.getY(), RECT_DIMS.getX(), RECT_DIMS.getY());
    // Draw FPS meter
    String fpsText = fps == null ? "FPS" : fps.toString();
    gfx.setTextAlign(TextAlignment.RIGHT);
    gfx.setFill(GREEN);
    gfx.setFont(Font.font(24));
    gfx.setTextBaseline(VPos.TOP);
    gfx.fillText(fpsText, getWidth() - 5, 5);
  }

  private boolean hitsBorders() {
    Rectangle2D frame = new Rectangle2D(0, 0, getWidth(), getHeight());
    Rectangle2D rect = new Rectangle2D(recPos.getX(), recPos.getY(), RECT_DIMS.getX(), RECT_DIMS.getY());
    if (speed.getX() < 0 && rect.getMinX() < frame.getMinX())
      return true;
    else if (speed.getX() > 0 && rect.getMaxX() > frame.getMaxX())
      return true;
    else if (speed.getY() < 0 && rect.getMinY() < frame.getMinY())
      return true;
    else if (speed.getY() > 0 && rect.getMaxY() > frame.getMaxY())
      return true;
    return false;
  }
}

Addition after testing same program in JavaScript

This JavaScript version runs smoothly on my devices

在此處查看比較兩個版本的視頻(頂部為 JavaScript,底部為 JavaFX):https ://www.ahpc??-services.com/dl/20220315_150431_edit1.mp4

const RED = 'red';
const GREEN = 'ForestGreen';
const BLACK = 'black';

window.addEventListener('DOMContentLoaded', e => {
  const animArea = document.querySelector('#anim-area');
  const ctx = animArea.getContext('2d');
  const cWidth = animArea.clientWidth;
  const cHeight = animArea.clientHeight;
  adjustCanvasSize();
  window.addEventListener('resize', adjustCanvasSize);

  const rect = {
    x: 0,
    y: 50,
    width: 50,
    height: 50
  }
  const speed = {
    x: 500,
    y: 0
  }

  const frameTiming = {
    frameCount: 0,
    frameTimes: Array(10),
    lastRun: 0,
  }

  requestAnimationFrame(animate);

  function animate() {
    const now = Date.now();

    requestAnimationFrame(animate);

    //Count FPS
    let fps;
    const frameIndex = frameTiming.frameCount % frameTiming.frameTimes.length;
    frameTiming.frameTimes[frameIndex] = now;
    if (frameTiming.frameCount > frameTiming.frameTimes.length) {
      const prev = (frameTiming.frameCount   1) % frameTiming.frameTimes.length;
      const delta = now - frameTiming.frameTimes[prev];
      fps = Math.round(100 * 1000 * frameTiming.frameTimes.length / delta) / 100;
    }
    frameTiming.frameCount  ;
    //Ignore first frame
    if (frameTiming.lastRun == 0) {
      frameTiming.lastRun = now;
      return;
    }
    //Animate
    const elapsed = (now - frameTiming.lastRun) / 1e3;
    // Reverse when hitting borders
    if (hitsBorders()) {
      speed.x *= -1;
      speed.y *= -1;
    }
    // Update position according to speed
    const oldRect = Object.assign({}, rect);
    rect.x  = speed.x * elapsed;
    rect.y  = speed.y * elapsed;
    frameTiming.lastRun = now;
    draw();

    function draw() {
      // Clear and draw border
      ctx.clearRect(0, 0, animArea.width, animArea.height);
      ctx.strokeStyle = BLACK;
      ctx.strokeRect(0, 0, animArea.width, animArea.height);
      // Draw moving shape
      ctx.fillStyle = RED;
      ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
      // Draw FPS meter
      const fpsText = fps == undefined ? "FPS" : `${fps}`;
      ctx.textAlign = 'right';
      ctx.fillStyle = GREEN;
      ctx.font = "24px sans-serif";
      ctx.textBaseline = 'top';
      ctx.fillText(fpsText, animArea.width - 5, 5);
    }

    function hitsBorders() {
      if (speed.x < 0 && rect.x < 0)
        return true;
      else if (speed.x > 0 && rect.x   rect.width > animArea.width)
        return true;
      else if (speed.y < 0 && rect.y < 0)
        return true;
      else if (speed.y > 0 && rect.y   rect.height > animArea.height)
        return true;
      return false;
    }
  }

  function adjustCanvasSize() {
    if (window.innerWidth < cWidth   30)
      animArea.style.width = (window.innerWidth - 30)   "px";
    else
      animArea.style.width = "";
    if (window.innerHeight < cHeight   30)
      animArea.style.height = (window.innerHeight - 30)   "px";
    else
      animArea.style.height = "";
    animArea.width = animArea.clientWidth;
    animArea.height = animArea.clientHeight;
  }

});
html,
body {
  margin: 0;
  padding: 0;
}

#anim-area {
  width: 800px;
  height: 800px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Moving square</title>
</head>

<body>
  <div class="content-wrapper">
    <canvas id="anim-area"></canvas>
  </div>
</body>

</html>

uj5u.com熱心網友回復:

我自己想通了。事實證明,JavaFX 沒有考慮顯示幕的實際重繪 率。它以大約 67Hz 的平均頻率呼叫AnimationTimer.handle(盡管變化很大),而典型的顯示幕重繪 頻率約為 60Hz。

這會導致某些幀延遲渲染(呼叫與螢屏顯示幀有很大的偏移),并且某些幀會以各種長度報告,而螢屏實際上會以恒定速率顯示它們,因此不一致我觀察到的運動。

我可以通過測量螢屏的重繪 率并根據要顯示的下一幀計算我的矩形的移動率來補償這一點(我不知道確切的時間,但恒定的偏移量就可以了)。

所以這里是代碼部分:

1.獲取螢屏重繪 率

stage.setOnShown(e -> {
  Screen screen = Screen.getScreensForRectangle(stage.getX(), stage.getY(), stage.getWidth(), stage.getHeight())
      .get(0);
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice d = ge.getScreenDevices()[Screen.getScreens().indexOf(screen)];

  int r = d.getDisplayMode().getRefreshRate();
  System.out.println("Screen refresh rate : "   r);
  //Calculate frame duration in nanoseconds
  this.frameNs = 1_000_000_000L / refreshRate; //Store it as it better suits you
});

請注意,此方法給出了int重繪 率,而螢屏重繪 率通常不是整數(我的當前是 60.008 Hz)。但這似乎是一個足夠好的近似值,從結果來看

它還依賴于awt我寧愿擁有純 JavaFX 解決方案的地方,并且我假設兩個系統以相同的順序報告螢屏,這遠不能保證:所以在生產中謹慎使用它!

2. 更改影片回圈以考慮此重繪 率

AnimationTimer anim = new AnimationTimer() {
  private long lastRun = 0;

  @Override
  public void handle(long now) {
    // Skip first frame but record its timing
    if (lastRun == 0) {
      lastRun = now;
      return;
    }
    // If we had 2 JFX frames for 1 screen frame, save a cycle
    if (now <= lastRun)
      return;
    // Calculate remaining time until next screen frame (next multiple of frameNs)
    long rest = now % frameNs;
    long nextFrame = now;
    if (rest != 0) //Fix timing to next screen frame
      nextFrame  = frameNs - rest;
    // Animate
    double elapsed = (nextFrame - lastRun) / 1e9;
    // Reverse when hitting borders
    if (hitsBorders())
      speed = speed.multiply(-1.);
    // Update position according to speed
    oldPos = recPos;
    recPos = recPos.add(speed.multiply(elapsed));
    log.println(String.format("%d\t: %d", frameCount, (now - lastRun) / 1_000_000));
    lastRun = nextFrame;
    draw();
  }
};

通過這些改動,影片運行流暢

完整代碼(改進了一點)

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class TestFxAnimationCanvas extends Application {

  // Set your panel size here
  private static final int FRAME_WIDTH = 1024;
  private static final int FRAME_HEIGHT = 480;

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

  @Override
  public void start(Stage stage) throws Exception {
    BorderPane root = new BorderPane();
    SmootherAnimation myAnimation = new SmootherAnimation();
    myAnimation.widthProperty().bind(root.widthProperty());
    myAnimation.heightProperty().bind(root.heightProperty());
    root.setCenter(myAnimation);
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.setWidth(FRAME_WIDTH);
    stage.setHeight(FRAME_HEIGHT);

    // Get screen refresh rate and apply it to animation
    stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> {
      Screen screen = Screen.getScreensForRectangle(
          stage.getX(), stage.getY(), stage.getWidth(), stage.getHeight()
          ).get(0);
      if (screen == null)
        return;
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      // /!\ Does ge.getScreenDevices really return same order as Screen.getScreens?
      GraphicsDevice d = ge.getScreenDevices()[Screen.getScreens().indexOf(screen)];
      int r = d.getDisplayMode().getRefreshRate(); // /!\ r is an int whereas screen refresh rate is often not an integer
      myAnimation.setRefreshRate(r);
      //TODO: re-assess when window is moved to other screen
    });

    stage.show();
  }
}

class SmootherAnimation extends Canvas {

  private static final double SPEED = 500; // Speed value to be applied in either direction in px/s
  private static final Point2D RECT_DIMS = new Point2D(50, 50); // rectangle size
  // Canvas painting colors
  private static final Paint BLACK = Paint.valueOf("black");
  private static final Paint RED = Paint.valueOf("red");
  private static final Paint GREEN = Paint.valueOf("ForestGreen");
  private static final Paint BLUE = Paint.valueOf("SteelBlue");

  // Defines rectangle start position, stores current position
  private Point2D recPos = new Point2D(0, 50);
  // Defines initial speed, stores current speed
  private Point2D speed = new Point2D(SPEED, 0);

  //Frame rate measurement
  private long frameCount = 0;
  private BigDecimal fps = null;
  long[] frameTimes = new long[120]; //length defines number of rendered frames to average over
  //Frame duration in nanoseconds according to screen refresh rate
  private long frameNs = 1_000_000_000L / 60; //Default to 60Hz

  public SmootherAnimation() throws IOException {

    AnimationTimer anim = new AnimationTimer() {
      private long previousFrame = 0;

      @Override
      public void handle(long now) {
        // Skip first frame but record its timing
        if (previousFrame == 0) {
          previousFrame = now;
          frameTimes[0] = now;
          frameCount  ;
          return;
        }
        
        // If we had 2 JFX frames for 1 screen frame, save a cycle by skipping render
        if (now <= previousFrame)
          return;
        
        // Measure FPS
        int frameIndex = (int) (frameCount % frameTimes.length);
        frameTimes[frameIndex] = now;
        if (frameCount > frameTimes.length) {
          int prev = (int) ((frameCount   1) % frameTimes.length);
          long delta = now - frameTimes[prev];
          double fr = 1e9 / (delta / frameTimes.length);
          fps = new BigDecimal(fr).setScale(2, RoundingMode.HALF_UP);
        }
        frameCount  ;
        
        // Calculate remaining time until next screen frame (next multiple of frameNs)
        long rest = now % frameNs;
        long nextFrame = now;
        if (rest != 0) //Fix timing to next screen frame
          nextFrame  = frameNs - rest;
        
        // Animate
        updateWorld(previousFrame, nextFrame);
        previousFrame = nextFrame; //Saving last execution
        draw();
      }
    };

    // Start
    anim.start();
  }

  /**
   * Save frame interval in nanoseconds given passed refresh rate
   * @param refreshRate in Hz
   */
  public void setRefreshRate(int refreshRate) {
    this.frameNs = 1_000_000_000L / refreshRate;
  }
  
  /**
   * Perform animation (calculate object positions)
   * @param previousFrame previous animation frame execution time in ns
   * @param nextFrame next animation frame execution time in ns
   */
  private void updateWorld(long previousFrame, long nextFrame) {
    double elapsed = (nextFrame - previousFrame) / 1e9; //Interval in seconds
    // Reverse when hitting borders
    if ( rectHitsBorders(   recPos.getX(), recPos.getY(),
                            RECT_DIMS.getX(), RECT_DIMS.getY(),
                            speed.getX(), speed.getY()) ) {
      speed = speed.multiply(-1.);
    }
    // Update position according to speed
    recPos = recPos.add(speed.multiply(elapsed));
  }

  /**
   * Draw world onto canvas. Also display calculated frame rate and frame count
   */
  private void draw() {
    GraphicsContext gfx = this.getGraphicsContext2D();
    // Clear and draw border
    gfx.setStroke(BLACK);
    gfx.setLineWidth(1);
    gfx.clearRect(0, 0, getWidth(), getHeight());
    gfx.strokeRect(0, 0, getWidth(), getHeight());
    // Draw moving shape
    gfx.setFill(RED);
    gfx.fillRect(recPos.getX(), recPos.getY(), RECT_DIMS.getX(), RECT_DIMS.getY());
    // Draw FPS meter
    String fpsText = fps == null ? "FPS" : fps.toString();
    gfx.setTextAlign(TextAlignment.RIGHT);
    gfx.setTextBaseline(VPos.TOP);
    gfx.setFill(GREEN);
    gfx.setFont(Font.font(24));
    gfx.fillText(fpsText, getWidth() - 5, 5);
    // Draw frame counter
    gfx.setTextAlign(TextAlignment.LEFT);
    gfx.setFill(BLUE);
    gfx.fillText(""   frameCount, 5, 5);
  }

  /**
   * Tells whether moving rectangle is hitting canvas borders
   * @param x considered rectangle horizontal coordinate (top-left from left)
   * @param y considered rectangle vertical coordinate (top-left from top)
   * @param width considered rectangle width
   * @param height considered rectangle height
   * @param speedX speed component in x direction
   * @param speedY speed component in y direction
   * @return true if a canvas border is crossed in the direction of movement
   */
  private boolean rectHitsBorders(double x, double y, double width, double height, double speedX, double speedY) {
    Rectangle2D frame = new Rectangle2D(0, 0, getWidth(), getHeight());
    Rectangle2D rect = new Rectangle2D(x, y, width, height);
    if (speedX < 0 && rect.getMinX() < frame.getMinX())
      return true;
    else if (speedX > 0 && rect.getMaxX() > frame.getMaxX())
      return true;
    else if (speedY < 0 && rect.getMinY() < frame.getMinY())
      return true;
    else if (speedY > 0 && rect.getMaxY() > frame.getMaxY())
      return true;
    return false;
  }

}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/449632.html

標籤:爪哇 动画 javafx

上一篇:關鍵幀影片:懸停不遵守滑鼠移出影片的“緩出”部分

下一篇:SwiftUI:在標簽欄中影片標簽項添加/洗掉

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more