python - WxPython,在简单的 GUI 中使用缓冲 DC 和面板刷新(转速计数器和条形图)

标签 python wxpython wxwidgets onpaint

我刚刚开始用 Python 编程,因此尝试了一个由仪表(转速计数器)和条形图组成的简单 GUI。这一切都有效(代码附在下面)。然而,由于屏幕刷新(Windows XP),我的闪烁非常严重。我知道我需要使用缓冲 DC,但是我无法从所有帖子中找出我实际需要做什么。

但是我的假设是:

  1. 首先创建一个内存 DC 供缓冲图像“驻留”,然后
  2. 实例化缓冲 DC
  3. 将 On Paint 绑定(bind)到缓冲 DC。

为了提供相关的仪表面(刻度),我将其全部绘制在 Autocad 中,然后将其转换为 jpg (HMIV0.2.bmp),在其上叠加条形图和仪表针。

正如您所注意到的,我在循环末尾使用了“刷新”,我想知道这是否是“不好的做法”。然而,我的目的是让程序自由运行并在循环的每次传递中“拾取”相关值(转数)。从而没有外部事件来触发绘制。

非常感谢任何正确方向的建议或指示...我购买了 Cody Precord 的“Wx.Python 2.8 应用程序开发手册”,希望能得到一些灵感,但可惜。

import wx
import random
import time
import math

def Data():
    data_value =random.randint(0,400)
    return data_value

def Pointer():
    meter_value =float(random.randint(0,260))
    Needle_centre_x = 253
    Needle_centre_y = 239
    Needle_length = float(125) 
    Needle_sweep = math.radians(214) #Number of degrees (converted to radians) that the needle is to deflect through
    Meter_max_scale = 260   # maximum value on the meter scale
    lo_reflect = float(20) # Meter reading that are less than this value are below the horizontal-Lo
    Angle_per_digit = Needle_sweep / Meter_max_scale # Angle_per_digit is in radians
    print '*******************NEW CYCLE*****************************'
    print 'The meter value is ' +str(meter_value)

    Start_displac =  Angle_per_digit * lo_reflect
    needle_ang =  -1*(Start_displac -(meter_value * Angle_per_digit))
    Needle_x = Needle_length * (math.cos(needle_ang))
    Needle_y = Needle_length * (math.sin(needle_ang))
    needle_degrees = math.degrees(needle_ang)
    anglea = needle_ang - math.pi/2
    angleb = needle_ang + math.pi/2
    base_x = 10*(math.cos(anglea))
    base_y = 10*(math.sin(anglea))
    print 'The needle angle is' + str(needle_degrees)
    print 'Angle A is ' + str(math.degrees(anglea)) 
    print 'Angle B is ' + str(math.degrees(angleb))    
    print 'The needle deflection angle is ' + str(math.degrees(needle_ang))  
    basea_y = int(Needle_centre_y- base_y)
    basea_x = int(Needle_centre_x - base_x)
    baseb_y = int(Needle_centre_y + base_y)
    baseb_x = int(Needle_centre_x + base_x)                 
    needle_y = int(Needle_centre_y - Needle_y)
    needle_x = int(Needle_centre_x - Needle_x)               
    Needle = [Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y] #Needle = [x1,y1,x2,y2,pointa_y,pointa_x,pointb_y,pointb_x]
    return Needle  

class MyPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent,pos = (0,0), size = (800,500))
        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def OnPaint(self, data_value):           
        data_value = Data()
        dc = wx.PaintDC(self)
        bmp = wx.Bitmap("HMIV0.2.bmp")
        dc.DrawBitmap(bmp, 0, 0)        

        if data_value > 300:
            dc.SetBrush(wx.RED_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)
            dc.SetBrush(wx.BLUE_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*300,2)
            dc.SetBrush(wx.GREEN_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*200,2)

        if data_value < 300 and data_value > 200 :
            dc.SetBrush(wx.BLUE_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)
            dc.SetBrush(wx.GREEN_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*200,2)

        if data_value < 200:
            dc.SetBrush(wx.GREEN_BRUSH)
            dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)          

        dc.SetBrush(wx.BLUE_BRUSH)
        HMI_needle = Pointer()
        print 'the contents of HMI needle are' + str(HMI_needle)
        print 'Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y'
        print type(HMI_needle)
        Points = [(HMI_needle[2],HMI_needle[3]),(HMI_needle[4],HMI_needle[5]),(HMI_needle[6],HMI_needle[7])]
        dc.DrawPolygon(Points)
        dc.DrawCircle(253,239,20)                   
        time.sleep(0.1)    
        self.Refresh()     

 class MyFrame(wx.Frame):
    def __init__(self, parent, title, size):
        wx.Frame.__init__(self, parent, wx.ID_ANY, title, wx.DefaultPosition, size,)
        bitmap = wx.Bitmap("Background.jpg", type=wx.BITMAP_TYPE_JPEG)
        self.bitmap =wx.StaticBitmap(self,bitmap =bitmap)
        self.Panel = MyPanel(self)


app = wx.PySimpleApp(redirect=False, filename = "C:\output.txt", clearSigInt=True)
frame = MyFrame(None,"WxPaint", size=(800,500))#size=(800,480))
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()

最佳答案

  • wx.Panel 上使用 wx.BG_STYLE_CUSTOM
  • OnPaint 处理程序中使用 wx.AutoBufferedPaintDC

在此处查看我的示例代码:

Best Canvas for WxPython

关于python - WxPython,在简单的 GUI 中使用缓冲 DC 和面板刷新(转速计数器和条形图),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16787535/

相关文章:

python - 单击按钮后如何更改组合框中的变量值?

python - 需要有关以空格开头的正则表达式的帮助

python - 如何使用 IDW 将 xarray 从高分辨率重新网格化为低分辨率

python - WxFormBuilder 没有 Python 选项

python - 如何设置Python wxWidgets应用程序窗口的类名?

python - pandas 中的条件成对计算

python - 按钮Name参数中的&是什么意思?

wxpython - wxWidgets wxPython 的 GUI 生成器

c++ - wxWidgets - Sizer 禁用自动布局

c++ - 未定义对 wxGLCanvas 构造函数的引用?