gtk 图像突然不刷新没有任何错误或警告

Posted

技术标签:

【中文标题】gtk 图像突然不刷新没有任何错误或警告【英文标题】:gtk image suddenly do not refresh without any errors or warnings 【发布时间】:2019-02-18 03:58:40 【问题描述】:

我开发了一个工具来从相机捕获图像并在窗口中显示捕获的图像。 GUI 窗口基于 GTK 2.4。开始时,该工具运行正常,并且从相机捕获图像并实时显示在窗口上。过了一会儿,窗口上的图像突然不再刷新,但仍然是从相机中捕获的。没有错误或警告。有人遇到过这样的情况吗?谢谢。

Ubuntu 18.04、GTK 2.4

  // loop to call the following code to refresh the image on the window
  pixbuf_ = Gdk::Pixbuf::create_from_data(
      final_img_buf_.data, Gdk::COLORSPACE_RGB, false, 8, final_img_buf_.cols,
      final_img_buf_.rows, static_cast<int>(final_img_buf_.step));
  gtk_image_.set(pixbuf_);

编辑于 2019-02-27 感谢您的回复。我已将 GTK 升级到 GTK+ 3,但仍然出现。

  // loop to call the following code to refresh the image on the window
  pixbuf_ = Gdk::Pixbuf::create_from_data(
      final_img_buf_.data, Gdk::COLORSPACE_RGB, false, 8, final_img_buf_.cols,
      final_img_buf_.rows, static_cast<int>(final_img_buf_.step));
  // ensure the image is normally updating
  //std::this_thread::sleep_for (std::chrono::milliseconds(30));
  gtk_image_.set(pixbuf_);
  Glib::RefPtr<Gdk::Pixbuf> pixbuf = gtk_image_.get_pixbuf();
  std::string filename = std::string("./debug/") + std::to_string(CurTimestampMicrosecond()) + std::string(".jpg");
  pixbuf->save(filename, "jpeg");

运行一段时间后,窗口不再刷新图像,但图像仍然正确保存。

于 2019-02-28 编辑

// The initialization code
gtk_main_.reset(new Gtk::Main(argc, argv));
ctrl_window_.reset(new CtrlWindow(screen, ctrl_rect)); // inherited from Gtk::Window
thread_ = std::thread([this]() 
  Gtk::Main::run(*ctrl_window_);

【问题讨论】:

这个问题可以通过以下方式避免,但是我还是不知道为什么。 pixbuf_ = Gdk::Pixbuf::create_from_data(final_img_buf_.data, Gdk::COLORSPACE_RGB, false, 8, final_img_buf_.cols, final_img_buf_.rows, static_cast(final_img_buf_.step)); // 休眠 20ms 以确保图像正常更新 std::this_thread::sleep_for (std::chrono::milliseconds(20)); gtk_image_.set(pixbuf_); 确保您没有泄漏一些图像内存。如果可能,请尝试重用相同的像素缓冲区,因为图像将始终具有相同的特征。顺便说一句,GTK+ 2.4 已经快 15 年了。如果您不维护旧的大型代码库,那么您真的应该切换到 GTK+ 3。 你循环的方式也很重要,你是使用线程,还是像 g_idle_add 或 g_timeout 这样的 GSource? @liberforce 感谢您的回复。我已经更新了我的问题。您还有其他建议吗? @liberforce 非常感谢您的友好回复。我在主线程中添加以下代码,而不是在另一个线程中调用更新函数。 Glib::signal_timeout().connect(sigc::mem_fun(*this, &ImageWindow::UpdateGtkImage), 40); 目前还可以。我会继续测试稳定性,稍后报告测试结果。再次感谢您。 【参考方案1】:

看起来g_timeout_addg_idle_add 都可能由于其他事件源的处理而延迟,因此在需要精确计时的上下文中不是最佳选择,例如在帧更新之前将图像绘制到屏幕上。我注意到在 2D 图形上下文中使用 g_timeout_add 会完全冻结应用程序,如果它无法以指定的 fps 加载帧。

gtk_widget_add_callback() 可能更适合您的需求,因为它会尽可能快地绘制缓冲区,而不会挂起,基本上会为您完成混乱的同步。

【讨论】:

谢谢。现在我使用 GLib::Dispatcher 注册事件和发送信号,而不是 g_timeout_add 或 g_idle_add,到目前为止它可以工作,并且平均负载更低。

以上是关于gtk 图像突然不刷新没有任何错误或警告的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 数据库突然丢失,返回默认值,没有错误或警告

脚本突然停止爬行,没有错误或异常

如何在没有任何错误或警告的情况下找到构建失败的原因

应用程序自动退出,没有任何警告或错误

Logcat 只显示警告,不显示错误

Google API OAuth2 刷新令牌突然被撤销