问题标签 [doublebuffered]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
2356 浏览

c# - 为什么要进行手动双缓冲?

我正在使用 C# 开发游戏(2.0 或 3.5 尚未决定)。游戏将在带有六边形网格的地图上进行。我很欣赏这张地图的 UI 应该使用双缓冲(很多层,所以绘制速度很慢)。我知道我可以通过样式启用双缓冲,或者创建自己的缓冲区并自己处理。我在网上找到的大多数建议都是自己处理。我想知道为什么?显然,这使我可以避免控制双缓冲中固有的假设,但我不知道这些假设是什么。

同样,我不是在寻找代码来解释如何双缓冲我的控件,而是为什么我要自己构建它而不是使用双缓冲样式并允许 CLR/Control 类来处理它?

0 投票
1 回答
20067 浏览

c# - Winforms 双缓冲

我将此添加到表单的构造函数代码中:

但是当它加载控件时,它仍然会显示丑陋的工件,只要它们发生变化(表单及其组件经常变化(需要更新))。

我需要做些什么不同的事情?

0 投票
3 回答
915 浏览

c# - 在没有子类面板的情况下禁用 OnPaintBackground?

有没有办法在不继承 Panel 并覆盖 OnPaintBackground 的情况下禁用面板的擦除?

我正在尝试在不继承 Panel 的情况下实现双缓冲效果。我知道这可能是一件奇怪的事情,但我至少想知道我是否可以。以下代码示例说明了这一点:

这会导致闪烁,大概是因为它在每个绘画周期都在擦除面板。

0 投票
1 回答
2894 浏览

windows - 了解 IDirect3DDevice9::Present 阻塞 vsync 时的行为

我正在开发一个科学应用程序,它必须估计(尽可能好地)在视频后台缓冲区中绘制的对象与该对象实际在屏幕上可见的点之间的时间差。换句话说,Windows XP+ 上的 DirectX 如何处理显示器的垂直刷新周期。

我将首先说我的视频例程基于 SDL 1.3 库。因此,我无法立即访问 DirectX API,但如有必要,可以进行更改。DirectX 在全屏模式下使用 D3DSWAPEFFECT_DISCARD、D3DPRESENT_INTERVAL_ONE 和 BackBufferCount = 1 进行初始化。这些似乎是最关键的参数,但如果需要更多信息,我很乐意深入研究其余的 SDL 代码。

D3DPRESENT_INTERVAL_ONE 标志确保后缓冲区和前缓冲区在每个刷新周期交换不超过一次,并且永远不会在刷新中间(它基本上启用 vsync)。实际上,如果我有一个简单的循环,它只是不断调用 IDirect3DDevice9::Present(在我的例子中是 SDL_RenderPresent),这个函数将阻塞两个刷新周期之间的毫秒数(60Hz 为 16.67ms,100Hz 为 10ms,等等) .

这是我的问题...假设我在后台缓冲区中绘制一个白色方块并调用 SDL_RenderPresent,它会阻塞 16.67 毫秒(假设 60Hz 刷新)。当对 SDL_RenderPresent 的调用返回时,我可以对监视器上可见图像的状态得出什么结论?在我看来,以下是可能性:

  1. 白色方块刚刚绘制在监视器上。
  2. 白色方块即将被绘制(不到 1 毫秒)。
  3. 之前的前缓冲区刚刚绘制;在我的白色方块出现之前需要另一个刷新周期(16.67 毫秒)(再次调用 SDL_RenderPresent 将使我进入案例 1)。
  4. 前一个前缓冲区是在最后 16.67 毫秒内绘制的,接下来是我的白色方块,但下一次刷新的确切时间是未知的。

从我所做的所有阅读中,我倾向于选项 3,但我找不到任何针对 4 的保证。在我的配置中,只有在第二次调用 Present 函数时才应该阻塞在两个刷新周期之间暂停。由于目标是交换前缓冲区和后缓冲区,因此第二次调用可以执行此操作的最早时间点是在刷新监视器之后(刚刚绘制了前一个前缓冲区)。到那时,包含我的白色方块的后缓冲区可以移动到前面,但它必须等待(最多)16.67 毫秒,然后监视器才能真正读取并显示缓冲区内容。理想情况下,我希望听到该函数应始终在上一个刷新周期完成后立即返回。

任何对 DirectX 更有经验的人可以提供有关此主题的任何见解吗?我的假设是正确的还是我遗漏了什么?对于任何支持 DirectX 的系统,这些假设是否总是正确的,或者逻辑是否会根据视频卡、显示器或其他一些东西而改变?

作为最后一个小问题,回到我一遍又一遍地调用 SDL_RenderPresent 的循环,我注意到前 3 或 4 个调用立即返回,而所有后续调用都在等待刷新周期。我是否正确假设 D3DPRESENT_INTERVAL_ONE 限制在第一次刷新之前被简单地忽略(与我期望的超过 2 个缓冲区发生的某种排队相反)?

换句话说,假设循环进入约 8 毫秒,直到下一个刷新周期。在此期间,它可能能够交换 4 次前后缓冲区。在第一次刷新发生之前,SDL_RenderPresent 将立即返回(因为从技术上讲,我们现在没有任何前缓冲区,只有 2 个后缓冲区),但是一旦其中一个缓冲区显示在屏幕上,阻塞就会开始发生. 这是一个有效的解释吗?

[编辑]

根据下面的回复,很明显我使用 vsync 和 Present 的方法不起作用。我想我找到了另一种方法来达到预期的结果,所以我把它贴在这里,以防有人发现我的想法有错误,或者只是为了给其他从事类似问题工作的人提供信息。

第一步是摆脱 D3DPRESENT_INTERVAL_ONE。这将禁用 vsync 并确保对 SDL_RenderPresent 的任何调用都将立即返回。接下来,您可以使用 IDirect3DDevice9::GetRasterStatus 获取有关当前监视器状态的信息。它提供了一个布尔字段,在两个刷新周期之间的暂停期间设置为 true,另一个字段告诉您在活动刷新期间的当前扫描线。使用这两条信息,可以实现您自己的垂直同步例程,尽管通过运行一个不断轮询监视器状态的循环,从而消耗 100% 的 CPU。这对我的需要是可以接受的。

还有缓冲的问题——当我调用 SDL_RenderPresent 时,我怎么知道要在屏幕上绘制哪一帧?我想我找到了一种方法来确定这一点,这取决于我知道显示器上当前正在绘制哪条线的能力。这是基本逻辑:

  1. 等待新的刷新周期开始(暂停 = 假,扫描线 = 0)。
  2. 用红色填充下一个后台缓冲区并调用 Present。
  3. 等待扫描线达到 32。
  4. 用绿色填充下一个后台缓冲区并调用 Present。

等等……在我的演示实现中,我使用了红色、绿色、蓝色,最后是黑色。这个想法是,只有在 GetRasterStatus 提供有关刷新状态的准确信息时,您才会看到 RGB 颜色模式,并且在调用 SDL_RenderPresent 时会立即翻转前后缓冲区。如果不满足其中任何一个条件,您可能看不到任何东西,颜色可能会交换或重叠等。另一方面,如果您在每一帧的屏幕顶部看到一个恒定的 RGB 图案,那么这证明您可以直接控制绘制的图像。

我应该补充一点,我今天在工作中的几台计算机上测试了这个理论。大多数确实显示了图案,但至少有一个将整个屏幕涂成红色。少数会出现色带上下跳跃,表明在交换缓冲区时存在一些不一致。这通常发生在较旧的机器上。我认为这是一个很好的校准测试,可以确定硬件是否适合我们的测试目的。

0 投票
2 回答
1411 浏览

delphi - 使用带有 VCL 控件的双缓冲区

我的应用程序有许多图形和视觉组件......所以我尽可能在每个组件中打开 doublebufferd = true 。

后来我想使用面板来容纳一些组件(它使对齐变得容易)但同时面板必须具有透明属性(然后只有我可以在面板下方显示图形)

所以我在我的托盘中找到了一个具有透明属性的面板“TJVPanel”,所以我使用了它,并设置了 transparent = true ;对齐 = 对(好吧);

一切都很好,但是当我调整大小时,jvpanel 和 jvpanel 中的组件正在闪烁

所以我搜索了双缓冲但没有成功

谁能告诉我解决方案或向我推荐另一个组件
,但我更喜欢使用 jvpanel 并进行一些修改

0 投票
2 回答
2865 浏览

java - Why is the paint() method not executing update() or paint() methods?

I'm having this problem where the paint() or update() methods in a class isn't getting called when I execute repaint(). Here's the code:

This class is implemented in this:

...Which is then implemented in a JFrame.

The output when I run it, is:

And so forth. I'm also not able to see any images on the Canvas (I'm assuming they are never drawn in the first place). It seems to completely skip the repaint method; the debug statements "Updating... " and "Repainting... " never show up. However, repaint also seems to be executing; the loop repeats without problems. Why isn't the repaint method calling the paint() or update() methods?

0 投票
4 回答
29861 浏览

java - Java:如何在 Swing 中进行双缓冲?

编辑两个

为了防止尖刻的评论和单行的答案漏掉了重点:IFF它就像调用setDoubleBuffered(true)一样简单,那么我如何访问当前的离线缓冲区,以便我可以开始弄乱 BufferedImage 的底层像素数据缓冲区?

我花时间编写了一段正在运行的代码(看起来也很有趣),所以我非常感谢实际回答(多么令人震惊;)我的问题并解释这是什么/如何工作而不是单行和刻薄的注释 ;)

这是一段在 JFrame 上反弹一个正方形的工作代码。我想知道可用于转换这段代码的各种方法,以便它使用双缓冲。

请注意,我清除屏幕并重新绘制正方形的方式不是最有效的,但这实际上不是这个问题的目的(在某种程度上,为了这个例子,它有点慢更好)。

基本上,我需要不断地修改 BufferedImage 中的很多像素(因为有某种动画),并且我不想看到由于屏幕上的单缓冲而导致的视觉伪影。

我有一个 JLabel,它的 Icon 是一个包装 BufferedImage 的 ImageIcon。我想修改那个 BufferedImage。

必须做什么才能使其成为双缓冲?

我知道当我在"image 2"上绘图时,会以某种方式显示"image 1 " 。但是,一旦我完成了“图像 2”的绘制,我如何“快速”将“图像 1”替换为“图像 2”

这是我应该手动做的事情吗,比如说,通过自己交换 JLabel 的 ImageIcon ?

我是否应该总是在同一个 BufferedImage 中绘制,然后在 JLabel 的 ImageIcon 的 BufferedImage 中对 BufferedImage 的像素进行快速“blit”?(我想不,我不知道如何将其与显示器的“垂直空白行”“同步”[或平面屏幕中的等效项:我的意思是,在不干扰显示器本身刷新它的时刻的情况下进行“同步”像素,以防止剪切])。

“重绘”订单呢?我应该自己触发这些吗?我应该在哪个/什么时候调用repaint()或其他什么?

最重要的要求是我应该直接在图像的像素数据缓冲区中修改像素。

编辑

不是针对全屏 Java 应用程序,而是针对常规 Java 应用程序,在其自己的(有点小)窗口中运行。

0 投票
1 回答
1901 浏览

c++ - 在远程会话上运行时,LVS_EX_DOUBLEBUFFER 是否正确地没有双缓冲?

一个应该在本地运行时使用双缓冲,但当窗口在远程会话上时不使用双缓冲,如果想要获得每种模式的最佳性能。

ListView 控件具有扩展样式 ,LVS_EX_DOUBLEBUFFER它会自动对 ListView 的内容进行双重缓冲。

是否需要注册以收到本地和远程会话之间更改的通知,并相应地更新此标志?还是 ListView 会自动执行此操作?

0 投票
0 回答
897 浏览

winforms - c# 4.0 Winform 应用程序 - 调整大小或扩展/最小化/调整大小时闪烁

将我的 WinForm 应用程序从 .net 3.5 迁移到 4.0 后,我注意到一些控件出现令人讨厌的闪烁

  1. 调整窗口大小,尤其是在最小化窗口并稍后再次最大化/显示时
  2. 打开时在模态对话框窗体上

这不是错误,应用程序运行良好,只是令人不安。不幸的是,它也很难描述。

  1. 看起来像运行多个刷新周期
  2. 对话框打开,闪烁2-3次后稳定
  3. 尤其是显示图像的控件会受到影响,例如带有表单的控件不会显示此效果
  4. 仅在 .net 4 中,在 3.5 中不明显

我试图将一些控件设置为双缓冲,但没有成功。我只是想知道是否有人注意到了同样的情况,甚至有解决方案。

可能相关:

  1. 在任务栏上绘制图像时 Winforms 闪烁
  2. 如何在我的 SDI 应用程序中避免闪烁?
0 投票
1 回答
489 浏览

c# - 双缓冲非矩形分配

我在 Panel 中绘图Windows.Forms
当我在这里使用双缓冲时,我只能分配矩形区域。

当我画圆或椭圆时,剩余的空间被黑色填充。
请帮我弄清楚我做错了什么或如何解决这个问题。
提前致谢!:)

我试图this.DoubleBuffered = true防止闪烁。这没有用。

Var p是Panel 在上面画一些东西。