python 笔记 PySimpleGUI 图形界面15-PySimpleGUI调试器

PySimpleGUI调试器

整理 PySimpleGUI 官方网站
原文google翻译过来的

https://pysimplegui.readthedocs.io/en/latest/
您将找到有关Elements的信息,所有其他类和函数都位于本手册结尾处。它们位于自述文件的大部分中,按字母顺序排列以便于查找。本节对Elements的讨论旨在教您如何工作。另一部分包含详细的呼叫签名和参数定义。
如果您是高级程序员,请调试一些真正毛茸茸的东西另一个时代喜欢这种调试方式的程序员希望在代码中具有“ X射线视觉”的程序员被要求使用调试器来收集信息正在运行一个缺少任何调试器的平台调试仅在调试器环境之外发生的问题*发现自己说“但在运行PyCharm时它可以工作”

从2019年6月1日开始imwatchingyou,PySimpleGUI的每个副本均已提供内置版本的调试器。它在很大程度上被用来评估添加的代码和添加的功能以及使用几个键是否会弄乱任何用户。从那时起,已有30,000多位用户安装了PySimpleGUI,并且没有提交任何问题,也没有进行评论/投诉,因此对于普通用户来说似乎足够安全…到目前为止。

到目前为止,还没有人报告有关调试器的任何信息。假定它正在安静地处于休眠状态,等待您按BREAK或CONTROL+ BREAK键。奇怪的是没有人意外地这样做并吓坏了,记录了一个问题。

普通的PySimpleGUI模块具有内置的调试器。对于其他端口,请使用包imwatchingyou。

它是什么?为什么要使用它?有没有搞错?我已经有一个IDE。

该调试器为您提供了大多数典型的Python开发人员所独有的功能,并能够在代码运行时 “查看”并与您的代码进行交互。您可以在代码继续运行的同时更改变量值。

报表打印凉爽,但也许你厌倦了看到的打印输出event和values:

Push Me {0: 'Input here'}
Push Me {0: 'Input here'}
Push Me {0: 'Input here'}

并且希望看到该窗口在显示器的右上角连续更新:

注意到它是多么容易,单独使用这个窗口,让您PySimpleGUI包是从哪里来的位置肯定的,没有任何猜测。希望这个窗口在您的调试未来,因为它会不时被要求。

准备运行调试器

如果您的程序正在运行并带有阻塞Read调用,那么您将需要为读取添加超时。这是因为调试器通过从这些异步调用中窃取一点时间来获得周期…但是只有当您打开这些调试器窗口之一时,这样才不会浪费CPU时间,因为根本没有浪费时间。

您的事件循环将通过以下阻止进行修改:

while True:
    event, values = window.read()

对于此非阻塞:

while True:
    event, values = window.read(timeout=200)
    if event == sg.TIMEOUT_KEY:
        continue

这3行绝对不会改变您的应用程序的外观和性能。您可以对使用阻塞读取的任何PySimpleGUI应用执行此操作,并且不会发现任何差异。之所以是NOP(无操作),是因为发生超时时,envent将设置为sg.TIMEOUT_KEY。如果将超时作为事件返回,则代码将简单地忽略它并通过执行一条continue语句重新启动循环。

此超时值为200,表示如果什么都没发生,调试器GUI将每秒更新5次。如果这对您的应用程序增加了过多的“拖动”,则可以增加超时时间。尝试使用500或1000而不是100。

如果不添加超时怎么办

假设您处在一个非常间歇的错误刚刚发生并且调试器可以真正为您提供帮助的情况下,但是您的windows.read()通话没有超时。没关系。回想一下,调试器获取其“周期”的方式是从您的Read调用中借用的。您需要做的是在使用调试器与随后通过事件循环生成另一遍之间进行替换。

也许这是一个确定按钮,它将导致您的循环再次执行(不退出)。如果是这样,您可以使用它来帮助调试器前进。

是的,这是一个很大的麻烦,但是还不错,在危机时期没有任何帮助,这很可能是您的“救星”,可以挽救您的屁股,几次按“确定”按钮对你来说什么都不是。您只想转储包含类实例的变量的值!

供我们使用的示例程序

现在您已经了解了如何将调试器添加到程序中,让我们制作一个简单的小程序,可以用来遵循以下示例:

import PySimpleGUI as sg

window = sg.Window('Testing the Debugger', [[sg.Text('Debugger Tester'), sg.In('Input here'), sg.B('Push Me')]])

while True:
    event, values = window.read(timeout=500)
    if event == sg.TIMEOUT_KEY:
        continue
    if event is None:
        break
    print(event, values)
window.close()

调试器Windows

“弹出调试器窗口”

有2个调试器窗口。一种叫做“弹出”调试器窗口。“弹出”窗口显示尽可能多的当前范围内的局部变量。该窗口不是交互式的。它意味着是您的变量的频繁更新的“仪表板”或“快照”。

弹出窗口中显示的一个“变量”是在调试Issues时经常要求提供的信息,并且该变量是sg(或在导入时将其命名为PySimpleGUI pacakge的任何名称)。假设您的导入为import PySimpleGUI as sg。如果您的导入不同,那么您将看到一个不同的变量。关键是这里显示了它。

可以通过红色的小X退出窗口,也可以使用点击菜单(rickt-click)菜单,该菜单也用作启动主调试器窗口的一种方法

启动弹出窗口的方法

有3种打开弹出窗口的方式。

  1. 按BREAK键盘上的键。
  2. 调用函数 show_debugger_popout_window(location=(x,y))
  3. Debug()在布局中添加按钮-在窗口中添加一些紫色和黄色的PySimpleGUI徽标

当询问您“ PySimpleGUI软件包或PySimpleGUI.py文件的位置”时,请执行此操作
如果您希望使用调试器查找此运行程序的PySimpleGUI程序包/PySimpleGUI.py文件的位置,那么您所需要做的就是:按下BREAK键盘上的键。有时被标记为Cancel按键可能也Pause印在按键上在某些美国键盘上,它位于按键旁边Scroll Lock和/或上方PageUp*这将打开一个位于屏幕右上角的窗口,看起来像这: 图片 *您要查找的信息显示sg在窗口的旁边。您无需修改​​程序即可使用此技术获取此信息。

如果变量的值太长且不合适,则需要使用“主调试器窗口”收集此信息

弹出调试器窗口中未列出的内容

弹出窗口是打开窗口时局部变量的“快照”。这意味着将不会显示创建Popout时不存在的任何变量。这个窗口不会不大小通过添加新的变量扩大。或许在将来。

“主调试器窗口”

现在我们正在谈论认真的Python调试!

曾经希望您有一个repl>>>提示,说您可以在程序运行时运行。好吧,这就是使用PySimpleGUI调试器主窗口所获得的!酷吧?如果您没有留下深刻的印象,请继续喝杯咖啡,然后继续分散注意力,因为我们在这里遇到了一些非常酷的事情……。

您会发现此窗口有2个标签,一个标签为标签,另一个标签Variables为REPL & Watches

打开主调试器窗口的方法
有3种方法可以打开Main Debugger窗口

  1. 在电脑键盘上按Control+Break
  2. 在弹出调试窗口中,右键单击并Debugger从右键菜单中选择
  3. 从您的代码调用 show_debugger_window(location=(x,y))

主调试器窗口的“变量”选项卡
在这里插入图片描述
请注意,此窗口周围的“框架”以蓝色标记为“自动监视”。像“弹出”窗口一样,此调试器窗口也“监视”变量,这意味着您可以连续调用它们不断更新它们Window.read。

您一次最多可以拥有9张“手表”。

选择要观察的变量
您只需单击“显示所有变量”按钮,监视到的变量列表将自动由查找到的前9个变量流行。或者,您可以单击“选择要自动查看的变量”按钮,从中可以分别选择要显示的变量和表达式。
在这里插入图片描述
在此窗口中,我们正在检查复选框以显示以下变量:

event,sg,values,window,file
在这里插入图片描述
此外,您可以在窗口底部看到已定义“自定义监视”的信息。这可以是您想要的任何专业技能。假设您有一个包含很多值的窗口。而不是浏览values变量并找到您要查找的键的条目,而是显示特定键的values变量的条目。

在此示例中,输入的“定制手表”为values[0]。单击“确定”按钮后,表明已选择我们要观看的变量,这是显示的主窗口:
在这里插入图片描述
我们可以看到我们检查的变量以及定义的表达式values[0]。如果您将此窗口保持打开状态,则每次我们在示例代码中调用该行时,这些值都会不断进行动态更新window.read(timeout=500)。这意味着“主调试器窗口”和我们定义的这些变量将每500毫秒更新一次。

REPL和手表标签
在这里插入图片描述
提供此选项卡是一种与正在运行的程序进行实时交互的方式。

如果要快速查看变量的值(几乎是ANY变量),则将信息键入提供给“监视”变量或专业知识的3个空格之一。在此示例中,将变量窗口键入第一个慢速窗口。

输入字符“ w”后,立即显示右侧信息。无需单击任何按钮。您只需要输入有效的专业知识,它就会显示给您…它将以持续不断的刷新为基础进行显示。
在这里插入图片描述
如果输入字段右侧的区域太小,则可以单击“详细信息”按钮,您将看到一个弹出的滚动窗口,其所有信息都像打印出来一样显示。

我敢肯定您有打印对象的美好经历。单击window显示的变量旁边的“详细信息”按钮时,将显示以下窗口:
在这里插入图片描述
哦,Python,-叹气-。我只想看到我的window物品被打印出来。

Obj 救援按钮!
PySimpleGUI有一个有趣且非常有用的功能,在名为docs的文档ObjToString中进行了讨论,该功能接受一个对象并将其内容转换为格式良好的字符串。当您单击Obj按钮时,此功能用于创建文本输出。结果是这样,而不是前面显示的小窗口:

在这里插入图片描述

REPL提示

虽然不是真正的Python REPL提示,但此窗口的REPL >>>提示旨在尽可能地发挥作用。您也可以在此处输入专业知识和代码。

此提示的用途非常广泛,种类繁多,因此不会尝试将它们全部列出。

将您的“ X射线”和“内窥镜”插入程序

可以将这个提示视为获取有关正在运行的程序的特定诊断信息的一种方式。不能过分强调这个工具的功能和有用之处在于,它已经在您启动了运行程序之后对其进行了诊断。

执行代码

除了显示信息,获取程序包的路径,查找版本信息之外,您还可以从PySimpleGUI调试器的REPL >>>提示符下执行代码。您可以键入任何表达式以及任何可执行语句。

例如,要查看PopupError运行程序时的外观。在REPL提示符下,键入: sg.PopupError(‘This is an error popup’)

结果是将显示一个带有您提供的文本的弹出窗口。

了解有关程序问题的答案

使用此运行时工具,您可以对收集的数据充满信心。对?

没有比询问程序更好的方法来查找程序正在使用的程序包的版本。 这是真的。想一想。而不是进入PyCharm,而是查看项目的“虚拟环境”,按照某种路径进入一个窗口,该窗口列出了为该项目安装的软件包,得到了版本,您完成了,对吗?也许。但是,您确定您的程序正在使用该软件包的那个版本吗?

过去,人们肯定知道他们运行的是什么版本,这真是浪费时间。或者,他们不知道哪个版本,也找不到线索。不知道如何做是没有错的。我们都从这里开始。哎呀

一个真实的例子…

如何使用调试器查找软件包的版本号

让我们将我们现在所学到的所有内容汇总起来,并使用调试器解决经常发生的问题,有时如何找到答案根本不是很明显。

我们正在使用Matplotlib,并希望找到“版本”。

对于此示例,正在使用“供我们使用的示例程序”部分中的12行小程序。

该程序不会导入matplotlib。我们有两种选择,可以更改代码,也可以从调试器导入包。让我们使用debgger。

通过CONTROL+BREAK按键拉出主调试器窗口。然后单击“ REPL *手表”选项卡。在>>>提示符下,我们将首先通过输入以下内容导入软件包: import matplotlib as m

不返回任何内容的Python调用返回的结果是值None。您将在输出区域中看到输入的命令,后跟“ None”,表示成功。

最后,输入: m.version

整个操作集显示在此窗口中:
在这里插入图片描述
按照惯例,您会发现许多模块的变量__version__都具有软件包的版本号。PySimpleGUI有一个。如您所见,matplotlib有一个。该requests模块有这个变量。

为了获得最大的兼容性,PySimpleGUI不仅使用__version__,而且还将其版本包含在另一个变量中version,该变量具有版本号,因为在某些情况下,__version__该version变量不可用,但该变量可用。

建议您使用该变量version来获取PySimpleGUI版本,因为到目前为止它是最成功的方法。

tkinter,但是不是…。当然…遵循此约定。不,要获得tkinter版本,您需要查看变量: TkVersion

这是调试器中REPL的输出,显示了tkinter版本:

>>> import tkinter as t
None
>>> t.TkVersion
8.6
>>> t.__version__
Exception module 'tkinter' has no attribute '__version__'

扩展PySimpleGUI

PySimpleGUI不会也不能提供基础GUI框架中的所有可用设置。并非所有的tkinter选项都可用于TextElement。与PySimpleGUIQt和其他端口相同。

原因有很多。

  1. 时间和资源限制-PySimpleGUI开发团队的规模非常小
  2. PySimpleGUI提供了“统一API”。从理论上讲,这意味着该代码可在所有PySimpleGUI端口上移植,而无需更改用户代码(导入除外)
  3. 通过设计,PySimpleGUI意味着简单,可以覆盖80%的GUI问题。

但是,PySimpleGUI程序并不是死胡同!!编写PySimpleGUI代码,然后达到您确实需要扩展列表框以包含更改“选定”颜色的能力的地步。也许这对您的项目至关重要。也许您后来才发现基本的PySimpleGUI代码没有公开tkinter的功能。不要怕!这条路确实还在!!

小部件访问

大多数用户扩展/增强功能都处于“元素”级别。您希望某些Element做一些技巧,而这是使用现有PySimpleGUI API所无法完成的。只是不可能。该怎么办?

您需要访问底层GUI框架的“小部件”。好消息是,您已经为PySimpleGUI的所有端口(而不仅仅是tkinter端口)访问并等待着您。

Element.Widget 是GUI小部件
类变量Widget包含tkinter,Qt,WxPython或Remi小部件。使用该变量,您可以直接修改该小部件。

您必须先访问窗口Read或Finalize窗口,然后才能访问Widget类变量

达到Finalize要求的原因是,在未读取或确定窗口之前,实际上不会创建该窗口并使用GUI Widget进行填充。当您执行这两个操作时,将创建GUI窗口小部件。

旁注-您可以停止使用.Finalize()添加到窗口创建finalize中的Window调用,而可以在调用中使用参数。

旧方法:

window = sg.Window('Window Title', layout).Finalize()

新方法:

window = sg.Window('Window Title', layout, finalize=True)

对于未必受过连锁调用工作原理培训的初学者,它更干净,更省力。Py 简单的 GUI。

使用示例 Element.Widget

到目前为止,已有2种使用此功能的功能。已经提到的一项功能是添加一项新功能。使用它的另一种方法是修复错误或解决古怪行为。

最近发布的一个问题是,在tkinter中切换选项卡时,焦点始终设置在选项卡上的按钮上。用户不希望发生这种情况,因为这是在其精心制作的图形按钮周围放置了一条难看的黑线。

目前,PySimpleGUI中没有“禁用焦点”元素的方法。本质上就是需要的,能够告诉tkinter这个小部件永远不要集中注意力。

有一种方法可以告诉tkinter小部件不应获得焦点。缺点是,如果您使用Tab键进行导航,则该元素将永远无法获得焦点。因此,它不仅会阻止自动解决此问题的焦点,而且会阻止所有用途。当然,您仍然可以单击该按钮。

该用户的使用方法是直接修改tkinter小部件,并告诉它不要获得焦点。只需一行代码即可完成:

window[button_key].Widget.config(takefocus=0)

此解决方案的绝对优势在于,无需将tkinter导入到用户程序中即可运行此语句。Python已经知道什么是对象.Widget,因此可以向您展示该对象的各种方法和类变量。大多数tkinter选项都是字符串,因此您无需导入tkinter即可获取任何枚举。

查找元素的小部件类型

当然,为了调用方法或访问对象的类变量,您需要知道所使用的基础Widget的类型。该文档可能会列出所有内容,但缺点是小部件可能会更改类型(对于已经使用.Widget的人来说不是一件好事!)。它还可以节省空间和时间,以使本文档出版并向您提供。

因此,这是获取元素的小部件类型的方法:

print(type(window[your_element_key].Widget))

在上面的按钮示例中,打印的内容是:

<class 'tkinter.Button'>

我认为这可能更清晰。这时的工作是查看tkinter文档,以了解tkinter Button小部件的方法。

窗口级访问

为此,您暂时需要一些特定的变量,因为没有Window类变量在使用的GUI库中保存窗口的表示形式。

对于tkinter,此刻,窗口的根对象是这样的:

sg.Window.TKroot

在PySimpleGUI中,类型将有所不同。可能是: tkinter.Tk() tkinter.Toplevel()

无论哪种方式,您都可以使用相同的Window变量进行访问sg.Window.TKroot

将来在此空间中查看此对象的更标准化的变量名称。可能是Window.WidgetElements所用之类的东西Window.GUIWindow。

具有约束力的“事件”

如果您希望直接从tkinter接收事件,但以PySimpleGUI方式进行,则可以这样做,并通过标准Window.read()调用将这些事件返回给您。

Elements和Window对象都有一个称为的方法bind。您可以为此功能指定2个参数。一个是用于告诉tkinter绑定哪些事件的字符串。另一个是Elements的“键修饰符”,而对于Windows是一个“键”。

将key_modifier在Element.bind调用是添加到您的关键的东西。如果您的密钥是字符串,则此修饰符将附加到密钥,并且事件将是单个字符串。

如果元素的键不是字符串,则将返回一个元组作为事件(your_key,key_modifier)

这将使您能够继续使用怪异的非字符串键。请注意,在这种情况下,您将取回一个元组而不是密钥。

发生这种情况的最佳示例是在扫雷游戏中,其中每个按钮已经是按钮(x,y)位置的元组。正常的左键点击将返回(x,y)。由于绑定调用而产生的右键单击将是((x,y),key_modifier)。

用户解析这些事件将很棘手,但是如果您正在使用此功能并且还使用非字符串键,则假定您是高级用户。

如bind方法的文档中所示,还添加了两个成员变量。此添加的变量包含tkinter特定的事件信息。换句话说,tkinter通常在发生回调时发回的“事件”。

这是示例代码,显示了如何进行这些调用。

绑定了三个事件。

  1. 窗口中的任何按钮单击都会从window.read()返回事件“窗口单击”。
  2. 右键单击“执行”按钮将从window.read()返回事件“执行+右键单击+”。
  3. 当输入元素获得焦点时,将从window.read()返回事件“ -IN- + FOCUS +”
import PySimpleGUI as sg

sg.theme('Dark Green 2')

layout = [  [sg.Text('My Window')],
            [sg.Input(key='-IN-'), sg.Text(size=(15,1), key='-OUT-')],
            [sg.Button('Go'), sg.Button('Exit')]
              ]

window = sg.Window('Window Title', layout, finalize=True)

window['-IN-'].bind("<FocusIn>", '+FOCUS+')
window.bind("<Button-1>", 'Window Click')
window['Go'].bind("<Button-3>", '+RIGHT CLICK+')

while True:             # Event Loop
    event, values = window.read()
    print(event, values)
    if event in (None, 'Exit'):
        break

window.close(); del window

目前无法“解除绑定”和事件。(对不起,发布之前没想到)

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值