wx (Python) 小部件的 GUI 更新缓慢?

2024-01-14

考虑这个例子(在 python2.7、Ubuntu 11.04 上尝试过):

import wx
import wx.lib.agw.knobctrl as KC

# started from: http://wxpython.org/Phoenix/docs/html/lib.agw.knobctrl.html

class MyFrame(wx.Frame):

  def __init__(self, parent):

    wx.Frame.__init__(self, parent, -1, "KnobCtrl Demo")

    self.panel = wx.Panel(self)

    self.knob1 = KC.KnobCtrl(self, -1, size=(100, 100))
    self.knob1.SetTags(range(0, 151, 10))
    self.knob1.SetAngularRange(-45, 225)
    self.knob1.SetValue(45)

    # explicit sizes here - cannot figure out the expands ATM
    self.text_ctrl_1 = wx.TextCtrl(self, -1, "0", size=(50, -1))
    self.slider_1 = wx.Slider(self, -1, 0, -12, 12, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_INVERSE, size=(150, -1))
    self.text_ctrl_2 = wx.TextCtrl(self, -1, "0", size=(50, -1))

    main_sizer = wx.BoxSizer(wx.VERTICAL)
    main_sizer.Add(self.knob1, 0, wx.EXPAND | wx.ALL, 20)
    main_sizer.Add(self.text_ctrl_1, 0, wx.EXPAND, 20)
    main_sizer.Add(self.slider_1, 0, wx.EXPAND , 20)
    main_sizer.Add(self.text_ctrl_2, 0, wx.EXPAND, 20)

    self.panel.SetSizer(main_sizer)
    main_sizer.Layout()
    self.knob1.Bind(KC.EVT_KC_ANGLE_CHANGED, self.OnAngleChanged)
    self.slider_1.Bind(wx.EVT_SCROLL, self.OnSliderScroll)

  def OnAngleChanged(self, e):
    theknob = e.EventObject
    x = theknob._mousePosition.x
    y = theknob._mousePosition.y
    ang = theknob.GetAngleFromCoord(x, y)
    self.text_ctrl_1.SetValue("%.2f" % (ang))
    self.text_ctrl_1.Refresh() # no dice
  def OnSliderScroll(self, e):
    obj = e.GetEventObject()
    val = obj.GetValue()
    self.text_ctrl_2.SetValue(str(val))

# our normal wxApp-derived class, as usual

app = wx.App(0)

frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()

app.MainLoop()

结果是这样的:

事实是:如果您非常快地移动滑块,您会注意到最底部的文本框更新也相当快;但是如果您非常快地移动旋钮,它的文本框(位于其下方)似乎会以大大降低的频率发生变化?!

为什么是这样;是否可以让旋钮文本框的响应速度与滑块文本框的响应速度一样快?


好吧,我想我有一些工作,但我不是 100% 确定,所以更博学的答案将不胜感激。首先,请注意:

  • The wx.Slider小部件(我认为)是用 C 实现的;所以Python“知道”有关其执行的唯一时间是当小部件广播事件时
  • The wx.lib.agw.knobctrl.KnobCtrl用Python实现;因此,Python 解释器“知道”(因为它必须运行它)小部件执行的每一行代码。

所以,我所做的就是尝试跟踪执行情况:

python -m trace --trace --timing test.py > test.pylog

我能注意到的是:OnSliderScroll出现在日志中显然不是由鼠标事件触发的,而多个OnMouseEvents会出现在knubctrl.py(鼠标悬停)中,并且只有一些会触发SetTrackPosition()最终调用OnAngleChanged()。但更重要的是,有一个ton of _gdi_.DC_DrawLine在日志中!然后,看着knobctrl.py源码中,我意识到渐变实际上是用Python绘制的for逐行循环:

def DrawDiagonalGradient(self, dc, size):
...
    for ii in xrange(0, maxsize, 2):
        currCol = (r1 + rf, g1 + gf, b1 + bf)                
        dc.SetPen(wx.Pen(currCol, 2))
        dc.DrawLine(0, ii+2, ii+2, 0)
...

……所以我想,这一定是很浪费时间吧!因此,下面的代码中所做的就是派生一个子类KnobCtrl, where DrawDiagonalGradient()因此它使用普通填充而不是渐变,这样工作速度要快得多。

因此,下面的代码使用相同的事件处理程序和相同的文本字段来比较原始变体和派生变体;你可以在以下网址观看视频https://vid.me/kM8V https://vid.me/kM8V,看起来像这样:

您会注意到,当转动原始旋钮时,textctrl 几乎没有变化(即使打印输出以预期的速度发出);但当具有“普通”背景的派生旋钮转动时(几乎与滑块一样快),更新得相当不错。我认为,当重载方法中没有任何类型的绘制时,“普通”速度会更快,但旋钮点之前的位置不会被删除。我的猜测是,原始旋钮渐变的绘制在分配的绘制时间范围内占用了太多时间,以至于 Python 需要删除该帧的其他排队更新,这里特别是文本控件的更新。

请注意,旋钮会发出两种信号:KC.EVT_KC_ANGLE_CHANGING(这不会刷新抽奖除非e.Skip()存在于处理程序中),并且KC.EVT_KC_ANGLE_CHANGED;然而,据我所知,它们总是相互跟随,所以下面*CHANGED用于两者。

当然,如果我误解了问题和解决方案,我很想知道......

import wx
import wx.lib.agw.knobctrl as KC

# started from: http://wxpython.org/Phoenix/docs/html/lib.agw.knobctrl.html

class KnobCtrlPlain(KC.KnobCtrl):
  def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
               size=wx.DefaultSize,
               agwStyle=KC.KC_BUFFERED_DC):
    super(KnobCtrlPlain, self).__init__(parent, id, pos, size, agwStyle)
  def DrawDiagonalGradient(self, dc, size):
    col1 = self._startcolour
    r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
    sizex, sizey = size
    # must have a filled draw here, to erase previous draws:
    dc.SetPen(wx.TRANSPARENT_PEN)
    dc.SetBrush(wx.Brush(col1, wx.SOLID))
    #~ dc.DrawCircle(self.Width/2, self.Height/2, sizex)
    dc.DrawRectangle(0, 0, sizex, sizey) # same effect as circle; prob. faster?


class MyFrame(wx.Frame):
  def __init__(self, parent):
    wx.Frame.__init__(self, parent, -1, "KnobCtrl DemoB")
    self.panel = wx.Panel(self)
    self.knob1 = KC.KnobCtrl(self.panel, -1, size=(100, 100))
    self.knob1.SetTags(range(0, 151, 10))
    self.knob1.SetAngularRange(-45, 225)
    self.knob1.SetValue(45)
    self.knob2 = KnobCtrlPlain(self.panel, -1, size=(100, 100))
    self.knob2.SetTags(range(0, 151, 10))
    self.knob2.SetAngularRange(-45, 225)
    self.knob2.SetValue(45)
    self.text_ctrl_1 = wx.TextCtrl(self.panel, -1, "0", size=(50, -1))
    self.slider_1 = wx.Slider(self.panel, -1, 0, -12, 12, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_INVERSE, size=(150, -1))
    self.text_ctrl_2 = wx.TextCtrl(self.panel, -1, "0", size=(50, -1))
    main_sizer = wx.BoxSizer(wx.VERTICAL)
    main_sizer.Add(self.knob1, 0, wx.EXPAND | wx.ALL, 20)
    main_sizer.Add(self.text_ctrl_1, 0, wx.EXPAND, 20)
    main_sizer.Add(self.knob2, 0, wx.EXPAND | wx.ALL, 20)
    main_sizer.Add(self.slider_1, 0, wx.EXPAND , 20)
    main_sizer.Add(self.text_ctrl_2, 0, wx.EXPAND, 20)
    self.panel.SetSizer(main_sizer)
    main_sizer.Layout()
    self.knob1.Bind(KC.EVT_KC_ANGLE_CHANGED, self.OnAngleChanged)
    self.knob2.Bind(KC.EVT_KC_ANGLE_CHANGED, self.OnAngleChanged)
    self.slider_1.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
  def OnAngleChanged(self, e):
    theknob = e.EventObject
    x = theknob._mousePosition.x
    y = theknob._mousePosition.y
    ang = theknob.GetAngleFromCoord(x, y)
    strval = str("%.2f" % (ang))
    print("ac: " + strval)
    self.text_ctrl_1.SetValue(strval)
  def OnSliderScroll(self, e):
    obj = e.GetEventObject()
    val = obj.GetValue()
    strval = str(val)
    print("ss: " + strval)
    self.text_ctrl_2.SetValue(strval)

# our normal wxApp-derived class, as usual
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

wx (Python) 小部件的 GUI 更新缓慢? 的相关文章

  • 如何正确地将 MIDI 刻度转换为毫秒?

    我正在尝试将 MIDI 刻度 增量时间转换为毫秒 并且已经找到了一些有用的资源 MIDI Delta 时间刻度到秒 http www lastrayofhope co uk 2009 12 23 midi delta time ticks
  • Python模块可以访问英语词典,包括单词的定义[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 python 模块 它可以帮助我从英语词典中获取单词的定义 当然有enchant 这可以帮助我检查该单词是否存在于英语中
  • 从 ffmpeg 获取实时输出以在进度条中使用(PyQt4,stdout)

    我已经查看了很多问题 但仍然无法完全弄清楚 我正在使用 PyQt 并且希望能够运行ffmpeg i file mp4 file avi并获取流式输出 以便我可以创建进度条 我看过这些问题 ffmpeg可以显示进度条吗 https stack
  • 如何使用 imaplib 获取“消息 ID”

    我尝试获取一个在操作期间不会更改的唯一 ID 我觉得UID不好 所以我认为 Message ID 是正确的 但我不知道如何获取它 我只知道 imap fetch uid XXXX 有人有解决方案吗 来自 IMAP 文档本身 IMAP4消息号
  • if 语句未命中中的 continue 断点

    在下面的代码中 两者a and b是生成器函数的输出 并且可以评估为None或者有一个值 def testBehaviour self a None b 5 while True if not a or not b continue pri
  • Pandas 数据帧到 numpy 数组 [重复]

    这个问题在这里已经有答案了 我对 Python 很陌生 经验也很少 我已经设法通过复制 粘贴和替换我拥有的数据来使一些代码正常工作 但是我一直在寻找如何从数据框中选择数据 但无法理解这些示例并替换我自己的数据 总体目标 如果有人真的可以帮助
  • 在Python中调整图像大小

    我有一张尺寸为 288 352 的图像 我想将其大小调整为 160 240 我尝试了以下代码 im imread abc png img im resize 160 240 Image ANTIALIAS 但它给出了一个错误TypeErro
  • 对图像块进行多重处理

    我有一个函数必须循环遍历图像的各个像素并计算一些几何形状 此函数需要很长时间才能运行 在 24 兆像素图像上大约需要 5 小时 但似乎应该很容易在多个内核上并行运行 然而 我一生都找不到一个有据可查 解释充分的例子来使用 Multiproc
  • 从 python 发起 SSH 隧道时出现问题

    目标是在卫星服务器和集中式注册数据库之间建立 n 个 ssh 隧道 我已经在我的服务器之间设置了公钥身份验证 因此它们只需直接登录而无需密码提示 怎么办 我试过帕拉米科 它看起来不错 但仅仅建立一个基本的隧道就变得相当复杂 尽管代码示例将受
  • 如何设置 Celery 来调用自定义工作器初始化?

    我对 Celery 很陌生 我一直在尝试设置一个具有 2 个独立队列的项目 一个用于计算 另一个用于执行 到目前为止 一切都很好 我的问题是执行队列中的工作人员需要实例化一个具有唯一 object id 的类 每个工作人员一个 id 我想知
  • 首先对列表中最长的项目进行排序

    我正在使用 lambda 来修改排序的行为 sorted list key lambda item item lower len item 对包含元素的列表进行排序A1 A2 A3 A B1 B2 B3 B 结果是A A1 A2 A3 B
  • Seaborn Pairplot 图例不显示颜色

    我一直在学习如何在Python中使用seaborn和pairplot 这里的一切似乎都工作正常 但由于某种原因 图例不会显示相关的颜色 我无法找到解决方案 因此如果有人有任何建议 请告诉我 x sns pairplot stats2 hue
  • Pandas 根据 diff 列形成簇

    我正在尝试使用 Pandas 根据表示时间 以秒为单位 的列中的差异来消除数据框中的一些接近重复项 例如 import pandas as pd numpy as np df pd DataFrame 1200 1201 1233 1555
  • 如何在 python 中没有 csv.reader 迭代器的情况下解析单行 csv 字符串?

    我有一个 CSV 文件 需要重新排列和重新编码 我想跑 line line decode windows 1250 encode utf 8 在由 CSV 读取器解析和分割之前的每一行 或者我想自己迭代行 运行重新编码 并仅使用单行解析表单
  • 无法在 osx-arm64 上安装 Python 3.7

    我正在尝试使用 Conda 创建一个带有 Python 3 7 的新环境 例如 conda create n qnn python 3 7 我收到以下错误 Collecting package metadata current repoda
  • 使用 Firefox 绕过弹出窗口下载文件:Selenium Python

    我正在使用 selenium 和 python 来从中下载某些文件web page http www oceanenergyireland com testfacility corkharbour observations 我之前一直使用设
  • 迭代 my_dict.keys() 并修改字典中的值是否会使迭代器失效?

    我的例子是这样的 for my key in my dict keys my dict my key mutate 上述代码的行为是否已定义 假设my dict是一本字典并且mutate是一个改变其对象的方法 我担心的是 改变字典中的值可能
  • 字典和数组作为类变量与实例变量

    这是赚取积分的简单方法 请解释以下内容 class C a b 0 c def init self self x def d self k v self x k v self a k v self b v self c append v d
  • 迭代 pandas 数据框的最快方法?

    如何运行数据框并仅返回满足特定条件的行 必须在之前的行和列上测试此条件 例如 1 2 3 4 1 1 1999 4 2 4 5 1 2 1999 5 2 3 3 1 3 1999 5 2 3 8 1 4 1999 6 4 2 6 1 5 1
  • Scrapy Spider不存储状态(持久状态)

    您好 有一个基本的蜘蛛 可以运行以获取给定域上的所有链接 我想确保它保持其状态 以便它可以从离开的位置恢复 我已按照给定的网址进行操作http doc scrapy org en latest topics jobs html http d

随机推荐

  • 使用表达式模板自动微分 C++

    介绍 我正在尝试了解表达式模板 因为它似乎是一种适用于各种计算的非常强大的技术 我在网上查看了不同的例子 例如维基百科 https en wikipedia org wiki Expression templates 我编写了一堆执行不同计
  • 如何解决Python中的语法错误

    由于 Stack Overflow 上有很多问题涉及SyntaxError在 Python 中 我们可能想知道 我们如何应对SyntaxError 有没有可以普遍应用的策略 0 错误出现之前 语法高亮和代码格式化 甚至在遇到一个Syntax
  • 如何伪造Python requests/beautifulsoup中启用的javascript

    我正在尝试抓取一个网站 该网站返回一条错误消息 表明您的 js 已禁用 并且您可能是机器人 我试图在网络浏览器中看到相同的行为 是的 相同的响应 但是如果启用了 JavaScript 它不会影响原始响应 我的意思是原始响应不依赖于 JS 所
  • R 查找元组的“组”[重复]

    这个问题在这里已经有答案了 我试图找到 组 id3 基于两个变量 id1 id2 df data frame id1 c 1 1 2 2 3 3 4 4 5 5 id2 c a b a c c d x y y z id3 c rep gro
  • 使用 WCF 在 Silverlight 中共享服务接口和模型

    假设我有以下接口 希望在我的服务器 常规 Web 服务 和客户端 silverlight 2 0 应用程序 之间共享 public interface ICustomerService Customer GetCustomer string
  • 将大字符串分配给 textview.settext 会挂起 UI

    我试图在 textview 中显示非常大的文本 长度为 850879 不幸的是 当我将文本分配给 textview 时 UI 挂起 8 15 秒 我们如何解决这个问题 任何想法 使用 Webview 而不是 textview Textvie
  • 序列化名为“return”的 JSON 对象

    我正在尝试针对 Mt Gox 的 Http API 编写一个代码 它返回如下 JSON result success return high value 5 70653 value int 570653 display 5 70653 cu
  • z-index 和 iframe 问题 - 下拉菜单

    嘿 我的下拉菜单和 iframe 有一个相当令人费解的问题 我已将 1000 的 z index 应用于下拉菜单 但是包含 youtube 视频的 iframe 仍然出现在菜单上方 请自行查看下面 检查 简码 菜单 http www mat
  • F#:字典、哈希表和映射之间的区别

    我是 NET 编程新手 抱歉 如果这个问题之前已被问过 我目前正在学习F 字典 哈希表和映射之间有什么区别 我应该什么时候使用它们 我还有一个问题 标题中没有提到 我什么时候应该使用Async RunSynchronously 这对我来说似
  • 覆盖不可修改域 Java 类中的 JAXB 绑定

    我花了一整天的时间试图解决这个问题 包括在这个网站上进行广泛的搜索 但我找不到问题的答案 我正在努力实现这一目标 在 XML 和一些我无法控制的现有 Java 对象之间进行转换 结果 源 XML 中的元素名称与 Java 类的属性名称不同
  • 实施面向 3.5 和 4.0 的 .Net 项目

    我们有一个项目 日志记录库 由标准 asp net 应用程序 4 0 框架 和 sharepoint 解决方案 3 5 框架 使用 有没有办法定义两个目标 以便在构建项目时构建两个版本 另外 有人实现了类似的东西并通过 nuget 分发它吗
  • Flutter 在 iOS 设备上出现“连接到服务协议时出错:HttpException...”错误

    对于网络连接我使用dio并用于检查连接状态Connectivity 在这里我检查网络状态 override Widget build BuildContext context bloc checkConnectivity Connectiv
  • jQuery 片段用动画交换两组元素

    是否有一些 jQuery 代码可以用动画交换 2 组元素 我只发现使用 jQuery 将列表项移动到无序列表的顶部 https stackoverflow com questions 1625960 move list item to to
  • 固定表格标题仅水平和垂直滚动 CSS

    首先 是否可以仅使用 CSS 来实现这一点 我已经构建了一个可以水平和垂直滚动的表格 但是 我希望将标题封装在其容器内 而不是出现在包装器之外 这样 当您水平滚动时 相应的标题与其指定列的内容一致 使用不同的变体position absol
  • JBoss AS7自动加载JPA

    我有一个使用 JPA Hibernate 和 Google Guice 的应用程序 Guice 是在一个ServletContextListener它设置了EntityManagerFactory itself 该应用程序在 Tomcat
  • python:numpy 数组的矩阵列表?

    我有一个包含 numpy 矩阵的列表 无论如何 我可以将整个事情变成一个漂亮的干净的 numpy 数组吗 From matrix 1 matrix 1 99387871 matrix 2 53564618 matrix 4 39125807
  • 出现错误 mysqli::real_connect(): (HY000/2002): 当我尝试访问实时服务器上的项目时没有这样的文件或目录[重复]

    这个问题在这里已经有答案了 我已将我的网站上传到服务器 然后尝试访问 但代码点火器向我返回错误 我找不到任何答案 为什么会发生这种情况 我的配置数据库设置如下 db default array dsn gt hostname gt loca
  • JavaScript 中按名称读取 cookie 的最短函数是什么?

    在 JavaScript 中读取 cookie 的最短 准确且跨浏览器兼容的方法是什么 很多时候 在构建独立脚本 我不能有任何外部依赖项 时 我发现自己添加了一个读取 cookie 的函数 并且通常会依赖于QuirksMode orgrea
  • PostgreSQL ANSI、Python SQL、utf-8' 编解码器无法解码字节 0xa0

    我正在尝试在 python 中运行 sql 查询 在 python 2 中 这曾经有效 但现在我使用 python 3 这不再有效 我收到错误UnicodeDecodeError utf 8 codec can t decode byte
  • wx (Python) 小部件的 GUI 更新缓慢?

    考虑这个例子 在 python2 7 Ubuntu 11 04 上尝试过 import wx import wx lib agw knobctrl as KC started from http wxpython org Phoenix d