Python 3.x 已解决:尝试使用GTK&;线程时出现错误;Pycairo(绘制窗口并从另一个线程发出信号) 解决方案 删除通道和相关代码 在窗口类中添加一个新的更新函数,该函数将新形状作为参数 修改类的初始化 调用update函数 解决方案的修改

Python 3.x 已解决:尝试使用GTK&;线程时出现错误;Pycairo(绘制窗口并从另一个线程发出信号) 解决方案 删除通道和相关代码 在窗口类中添加一个新的更新函数,该函数将新形状作为参数 修改类的初始化 调用update函数 解决方案的修改,python-3.x,multithreading,gtk3,pygtk,pycairo,Python 3.x,Multithreading,Gtk3,Pygtk,Pycairo,抱歉,但是差异降价似乎没有正确显示,希望您仍然能够了解解决方案的工作原理 窗口类 在类方法中init_ui self.connect("delete-event", Gtk.main_quit) + self.show_all() + a = self.darea.get_allocation() + print (a.x, a.y, a.width, a.height) + self.img = cairo.ImageS

抱歉,但是差异降价似乎没有正确显示,希望您仍然能够了解解决方案的工作原理

窗口类 在类方法中init_ui

         self.connect("delete-event", Gtk.main_quit)
+        self.show_all()
+        a = self.darea.get_allocation()
+        print (a.x, a.y, a.width, a.height)
+        self.img = cairo.ImageSurface(cairo.Format.RGB24, a.width, a.height)
一种新的类方法更新形状

+    def update_shapes(self, shapes):
+        self.shapes = shapes
+        cr = cairo.Context(self.img)
+        self.draw_background(cr)
+        for shape in self.shapes:
+            shape.draw(cr)
+        self.darea.queue_draw()
+        return True
主代码 问题: 窗口类
导入cairo
导入gi
输入数学
gi.require_版本('Gtk','3.0')
从gi.repository导入Gtk,GObject
类行():
定义初始(自身、开始、结束、厚度、颜色):
self.start=开始
self.end=结束
自身厚度=厚度
颜色
def抽取(自,cr):
cr.move_to(*自启动)
cr.line_至(*自结束)
cr.set_源_rgba(*自身颜色)
cr.set\U线条宽度(自身厚度)
cr.中风()
类多边形():
定义初始值(自身、点、线颜色、线厚度、填充颜色=无):
self.points=点#点应该是点的iterable
self.line\u color=line\u color
self.line\u厚度=line\u厚度
自填充颜色=填充颜色
def抽取(自,cr):
cr.move_to(*自身点[0])
对于自身中的点。点[1:]:
cr.line_至(*点)
cr.关闭_路径()
cr.set\U源\U rgba(*自身线条\U颜色)
cr.set线宽度(自线厚度)
cr.中风()
如果自填充颜色不是无:
cr.move_to(*自身点[0])
对于自身中的点。点[1:]:
cr.line_至(*点)
cr.关闭_路径()
cr.set\U源\U rgba(*自填充\U颜色)
cr.fill()
类窗口(Gtk.Window):
__G信号\uuuu={
“更新信号”:(GObject.signal\u RUN\u优先,无,
())
}
def do_更新_信号(自身):
打印(“调用更新信号”)
self.shapes=self.shapes\u channel.read()
打印(“新形状数:”,len(self.shapes))
self.show_all()
def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
超级(窗口,自我)。\uuuu初始化
self.width=窗口大小[0]
self.height=窗口大小[1]
self.background\u color=背景颜色
self.title=标题
self.shapes=[]
self.shapes\u channel=shapes\u channel
self.init_ui()
def初始用户界面(自身):
darea=Gtk.DrawingArea()
darea.connect(“绘制”,自绘制)
self.add(darea)
self.set_title(self.title)
self.resize(self.width、self.height)
自我设置位置(Gtk.WindowPosition.CENTER)
self.connect(“删除事件”,Gtk.main_退出)
def draw_背景(self,cr:cairo.Context):
cr刻度(自宽、自高)
cr.矩形(0,0,1,1)#矩形(x0,y0,x1,y1)
cr.set\U源\U rgba(*自身背景颜色)
cr.fill()
图纸上的定义(self、wid、cr:cairo.Context):
自绘制背景(cr)
对于self.shapes中的形状:
形状绘制(cr)
def运行(自):
Gtk.main()
def新建_窗口(形状_通道,
窗口大小=(10001000),
背景颜色=(1,1,1,1),
title=“3yp”):
返回窗口(U形通道,
窗口大小=窗口大小,
背景颜色=背景颜色,
头衔=头衔)
我正在尝试运行一个可以绘制我定义的形状(直线和多边形)的窗口

以前,当我向它提供一个形状列表并在应用程序结束时运行它时,它工作得很好

但是,我正在尝试添加交互性,并在调用update_信号时让它重新绘制一个形状列表,并在作为构造函数一部分的shapes_通道中传递一个新形状列表

主代码 以下是我的主代码中的相关位:

shapes\u channel=channel()
iter_num=0
def优化(chan、prob、信号员):
def打印编号(xk):
全球国际热核聚变实验堆
iter_num+=1
问题更新位置(xk)
概率更新梯度(雅可比(xk))
新形状=转换网格(prob.grid,building\u size=1.0/网格大小)
chan.write(新形状)
信号员发出(“更新信号”)
打印(“迭代”,iter_num,“完成…”)
尝试:
sol=minimize(objective,x0,bounds=all_bounds,constraints=constraints,options={'maxiter':MAX_ITER,'disp':True},callback=print_ITER_num,jac=jacobian)
问题更新位置(sol.x)
例外情况除外,如e:
打印(“遇到错误”,e)
窗口=新窗口(形状通道=形状通道)
线程(target=optimize,args=(shapes\u channel,optim\u problem,window))
x、 开始()
window.run()
如你所见:

  • 将创建一个名为shapes\u Channel的Channel()对象
  • 创建一个新窗口,通过中间函数new\u window将shapes\u通道传递到构造函数中
  • 此窗口被传递给另一个线程,以便另一个线程 可发出相关信号(“更新信号”)
  • 另一个线程正在运行
  • 窗口在主线程中运行,我得到以下控制台输出:
  • 调用更新信号
    新形状数:31
    Gdk消息:01:27:14.090:main.py:X服务器上的致命IO错误0(成功):0。
    
    从控制台输出中,我们可以推断信号被成功调用,新形状被传递到窗口并正确存储,但在行
    self.show_all()
    中失败

    这是一个以前运行良好的对象,并生成图形输出,我只能想到2个位置
    +    def update_shapes(self, shapes):
    +        self.shapes = shapes
    +        cr = cairo.Context(self.img)
    +        self.draw_background(cr)
    +        for shape in self.shapes:
    +            shape.draw(cr)
    +        self.darea.queue_draw()
    +        return True
    
    - shapes_channel = Channel()
      iter_num = 0
    - def optimize(chan, prob, signaller):
    + def optimize(prob, signaller):
          def print_iter_num(xk):
              global iter_num
              iter_num += 1
              prob.update_positions(xk)
              prob.update_grads(jacobian(xk))
              new_shapes = convert_grid(prob.grid, building_size=1.0/GRID_SIZE)
    -         chan.write(new_shapes)
    -         signaller.emit("update_signal")
    +         GLib.idle_add(signaller.update_shapes, new_shapes)
              print("Iteration", iter_num, "complete...")
          try:
              sol = minimize(objective, x0, bounds = all_bounds, constraints=constraints, options={'maxiter': MAX_ITER, 'disp': True}, callback=print_iter_num, jac=jacobian)
              prob.update_positions(sol.x)
          except Exception as e:
              print("ran into an error", e)
    
    - window = new_window(shapes_channel=shapes_channel)
    + window = new_window()
    - x = threading.Thread(target=optimize, args=(shapes_channel, optim_problem, window))
    + x = threading.Thread(target=optimize, args=(optim_problem, window))
      x.start()
      window.run()