进程以退出代码 -1073741819 (0xC0000005) Python Tkinter GUI Canvas 更新完成

Posted

技术标签:

【中文标题】进程以退出代码 -1073741819 (0xC0000005) Python Tkinter GUI Canvas 更新完成【英文标题】:Process finished with exit code -1073741819 (0xC0000005) Python Tkinter GUI Canvas Update 【发布时间】:2021-02-03 16:41:14 【问题描述】:

我需要在线程计时器的每次迭代中更新 TKagg Canvas 图。该图显示在计时器的第一次迭代中,然后程序暂停并输出 - '进程完成,退出代码 -1073741819 (0xC0000005)'

我这几天一直在努力让这段代码正常工作。任何帮助,将不胜感激。代码按原样运行,并且应该输出相同的退出代码。我不知道如何附加我的测试矩阵,但它只是一个 401x401 numpy 数组,包含 0.0-0.05 之间的值

import threading
from tkinter import *
from tkinter import ttk
import tkinter as tk
import numpy as np
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
matplotlib.use('Agg')
from matplotlib import cm, colors
import os
import os.path


class APP(tk.Tk):
    update_interval = 0.2
    dwell_time = np.array([20., 20., 20.])
    current_count = 0
    colormap = 'jet'

    window_height = 480
    window_width = 720

    num_columns = 20
    num_rows = 20

    canvas_width = window_width / num_columns * 13
    canvas_height = window_height / num_rows * 16

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # create a container
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=False)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # initialize an empty array of frames
        self.frames = 

        # iterate through the tuple of page frames - basically creates/configures an empty frame for each page
        for F in (Page1, Page2):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="NSEW")

            frame.grid_rowconfigure(0, weight=1)  # fills the whole window
            frame.grid_columnconfigure(0, weight=1)  # fills the whole window

        self.show_frame(Page1)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def resource_path(relative_path):
        return os.path.join(os.path.dirname(os.path.abspath(__file__)), relative_path)

    filename = "22222222_20210203083122.csv"
    filepath = resource_path('PDT_Patient_Treatment_Maps/' + filename)
    dose_map = np.load(resource_path('test.npy'))
    print(dose_map)

class Page1(tk.Frame):
    f = Figure()
    update_interval = 0.2
    dwell_time = np.array([20., 20., 20.])
    current_count = 0
    colormap = 'jet'

    window_height = 480
    window_width = 720

    num_columns = 20
    num_rows = 20

    canvas_width = window_width / num_columns * 13
    canvas_height = window_height / num_rows * 16

    plt = f.add_subplot(111)

    def start_treatment(self):

        counts_per_each_diffuser = (APP.dwell_time / APP.update_interval).astype(int)
        self.cumulative_count = counts_per_each_diffuser.cumsum()
        self.total_count = self.cumulative_count[-1]
        self.max_count = counts_per_each_diffuser.max()
        self.current_map = np.zeros(APP.dose_map.shape)  # initialize detection map
        self.timer_update()

    def timer_update(self):
        """update detector map and progress bar"""
        timer = threading.Timer(APP.update_interval, self.timer_update)
        timer.start()
        if APP.current_count >= self.total_count:
            timer.cancel()
            APP.current_count = 0

        else:
            self.update_det_map()
            self.current_count += 1
            current_percentage = self.current_count / self.total_count
            current_percentage = current_percentage if current_percentage <= 1 else 1
            self.progress['value'] = round(current_percentage, 3) * 100
            self.style.configure('text.Horizontal.TProgressbar', text=':.1%'.format(current_percentage))

    def update_det_map(self):
        self.show_det_map(self.current_map, self.det_canvas, self.plt)

    def show_det_map(self, map_data, canvas, ax):
        """convert 2d map data into PhotoImage RGB data and draw it on detector canvas"""

        self.gray2rgb = cm.get_cmap(self.colormap)
        img = (np.delete(self.gray2rgb(map_data), 3, 2) * 255).astype(np.uint8)
        ax.clear()
        ax.imshow(img, cmap=self.gray2rgb)
        canvas.draw()

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        # initializes grid to have evenly weighted rows and columns for the page
        # self.dose_map = dose_map
        cols = 0
        while cols < 20:
            self.grid_columnconfigure(cols, weight=1)
            self.grid_rowconfigure(cols, weight=1)
            cols += 1

        self.det_canvas = FigureCanvasTkAgg(self.f, self)
        self.det_canvas.draw()
        self.det_canvas.get_tk_widget().grid(row=0, column=6, rowspan=16, columnspan=13, padx=5, pady=10, sticky='NSEW')
        self.det_canvas._tkcanvas.grid(sticky='nsew', pady=10, padx=10)
        self.det_canvas._tkcanvas.config(highlightbackground='grey64', highlightthickness=1)

        # progress bar
        self.style = ttk.Style(self)
        self.style.layout('text.Horizontal.TProgressbar',
                          [('Horizontal.Progressbar.trough',
                            'children': [('Horizontal.Progressbar.pbar',
                                           'side': 'left', 'sticky': 'ns')],
                             'sticky': 'nsew'),
                           ('Horizontal.Progressbar.label', 'sticky': 'ns')])
        self.style.configure('text.Horizontal.TProgressbar', text='0.0 %', font=('Times', 12))
        self.progress = ttk.Progressbar(self, orient=HORIZONTAL, mode='determinate')
        self.progress.configure(style='text.Horizontal.TProgressbar')
        self.progress.grid(row=18, column=0, rowspan=1, columnspan=20, padx=10, pady=5, sticky='NSEW')

        # inserts space between lumeda logo and username label
        self.grid_rowconfigure(17, weight=1)  # weight controls number of spaces
        self.grid_rowconfigure(19, weight=1)  # weight controls number of spaces

        style = ttk.Style()
        style.configure('green.TButton', background='green4', font='bold', foreground='green4', highlightcolor='green4')
        self.start_btn = ttk.Button(self, text="START", style='green.TButton',
                                    command=lambda: self.start_treatment())
        self.start_btn.grid(row=20, column=5, rowspan=1, columnspan=1, pady=10, padx=5, sticky='nsew')


class Page2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)


if __name__ == '__main__':
    root = APP()
    root.geometry("720x460")
    root.resizable(0, 0)
    root.mainloop()

【问题讨论】:

我害怕将线程用于 tkinter 的定时进程,但一直无法让它工作。而是发现递归使用after 方法更容易。 我发现它与计时器和在 tkagg 画布上绘图有关。如果我注释掉 canvas.draw,程序会按预期完成执行,但不会更新图形。如果我将计时器更改为循环并保持 canvas.draw 图形得到更新。我的程序由计时器控制,所以我需要保留它。 @Andrew Allaire 我需要保留计时器,因为它控制在后端运行的函数的进度,链接到我的绘图和 GUI 的其他元素。我在应用程序的任何其他方面都没有遇到计时器和 GUI 的问题,只是这个 tkagg 画布绘制 而不是计时器更好地使用after - Tkinter 类似于许多其他 GUI 不喜欢更新 threads 中的小部件。在timer_update 的末尾你应该运行root.after(APP.update_interval, self.timer_update) 您可以使用command=self.start_treatment 代替command=lambda: self.start_treatment() - 没有lambda 和没有() 【参考方案1】:

最终使用 after() 函数,一切正常。谢谢!

【讨论】:

以上是关于进程以退出代码 -1073741819 (0xC0000005) Python Tkinter GUI Canvas 更新完成的主要内容,如果未能解决你的问题,请参考以下文章

进程以退出代码 -1073741571 结束

如果进程以退出代码 0 结束,我应该调用 Process.destroy() 吗?

进程以退出代码 1 Spring Boot Intellij 结束

进程以退出代码 -1073741515 (0xC0000135) 结束

这是啥错误,我该如何解决?进程以退出代码 -1073740791 (0xC0000409) 结束

进程以python中的退出代码1错误完成[重复]