如何避免长时间操作后 GUI 冻结

How to avoid GUI freezing after run of long ops

提问人:Egor Richman 提问时间:11/9/2019 更新时间:11/9/2019 访问量:55

问:

我有一个很长的操作,从曝光事件或用户单击按钮后开始。我还有一个进度条,当我尝试更新它的状态时,它可以完美地工作。但是当我单击按钮时,我看到我的 GUI 是如何挂起的......

<?php

abstract class FractalDrawingWindow extends GtkWindow {

  public function FractalDrawingWindow() {
    parent::__construct();

    $this->set_title($this->getName());
    $this->connect_simple('destroy', array('gtk', 'main_quit'));

    $drawingArea = new GtkDrawingArea();
    $drawingArea->connect('expose_event',array($this,'onExpose'));
    $drawingArea->set_size_request(640,480);

    $updateButton = new GtkButton('Update');
    $updateButton->connect('clicked', array($this,'update'), $drawingArea);

    $progress = new GtkProgressBar();

    $vbox = new GtkVBox(false,0);
    $vbox->pack_start($drawingArea,false,false,0);
    $vbox->pack_start($progress, false, false, 0);
    $vbox->pack_start($updateButton,false,false,0);
    $this->add($vbox);

    $this->set_position(GTK::WIN_POS_CENTER);

    Gtk::timeout_add(200,array($this,'updateProgress'), $progress);

    $this->show_all();
  }

  function onExpose($drawingArea, $event){
    $context = $drawingArea->window->cairo_create();
    $this->onDraw($context); // here I have a long ops wasting time...
  }

  function update($widget, $drawingArea){
    $this->set_title($this->getName());
    $drawingArea->queue_draw(); // after that onExpose event created
  }

  // simple update the progress
  function updateProgress($progress){
    $progress->set_fraction($this->getState());
    return true;
  }

  abstract public function getName();
  abstract public function getState();
  abstract protected function onDraw($context);
}
?>

那么,有没有办法避免冻结并看到进展正在上升?

开罗 php-gtk

评论

0赞 Progman 11/9/2019
编辑您的问题,以包含您拥有的完整源代码,作为最小的可重现示例,可以由其他人编译和测试。
0赞 Egor Richman 11/9/2019
我的代码要大得多。你可以从这个链接得到它。只需运行fractal_drawer.php,并尝试将分形类型更改为任何类型(对于某些分形Math_Complex需要库)。然后按下“提交”按钮。
0赞 Progman 11/9/2019
这回答了你的问题吗?在PyGtk中单击按钮时GUI冻结(是的,我知道它是python,但原因是一样的)
0赞 Egor Richman 11/10/2019
不幸的是,这无济于事,因为我找不到使用 php 在线程中运行 GTK 函数的方法。使用 pthreads 对于我的操作系统来说有点棘手(我使用的是 Ubuntu 18.04)。常见的方法(使用fork)由于错误而无法正常工作。我正在寻找一种变体,以获得更优雅的救赎。我发现php-gtk有两个函数:threads_enter()threads_leave()。但是我的php解释器不认识它。这是f#king很难。

答: 暂无答案