【问题标题】:wxPython custom progressBar problemswxPython自定义progressBar问题
【发布时间】:2017-05-20 08:33:17
【问题描述】:

首先,我是 python 新手,所以请不要因为代码混乱而评判我 :)。我试图制作圆形进度条,但遇到了一些问题,找不到它导致的原因。问题是 setRange(0, 100) 或 setMmaximum(100) 如果我 setValue(100) 我被填满整个圆圈,则无法正常工作。第二个问题是我的进度条向后运行。请问有人可以解释我做错了什么吗?

这是我目前所拥有的:

main.py 文件

import wx
from src.arc import TestArc


class bandom(wx.Frame):

    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(800, 600))

        self.gauge = TestArc(self)
        self.gauge.SetFocus()
        #self.gauge.setMinimun(0)
        #self.gauge.setMaximun(100)
        self.gauge.setRange(0, 100)
        self.gauge.setValue(10)

       # timer for testing progressbar
  #     self.timer = wx.Timer(self)
  #     self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
  #     self.timer.Start(100)

  #     self.val = 0

 # def OnTimer(self, evt):
 #     self.val += 1
 #     self.gauge.setValue(self.val)
 #
 #     if self.val >= 100:
 #         self.val = 0
 #     #print(self.val)


class MyApp(wx.App):
    def OnInit(self):
       frame = bandom(None, -1, 'Window title here')
       frame.Show(True)
       self.SetTopWindow(frame)
       return True

    def main():
       app = MyApp(0)
       app.MainLoop()

if __name__ == '__main__':
    main()

和arc.py文件

class TestArc(wx.Panel):

def __init__(self, *args, **kwargs):
    super(TestArc, self).__init__(*args, **kwargs)

    self.lineWidth = 0
    self.min = 0
    self.max = 100
    self._value = 0
    self.setText = '---'
    # self.font = someFont()
    self.position = wx.Rect()  # self.position.Set(x, y, width, height)
    self.startPoint = math.radians(0)
    self.endPoint = math.radians(0)

    self.Bind(wx.EVT_PAINT, self.OnPaint)

def setRange(self, min, max):
    self.min = min
    self.max = max

    if self.max < self.min:
        self.max, self.min = self.min, self.max

    if self._value < self.min:
        self._value = self.min
    elif self._value > self.max:
        self._value = self.max

    self.Refresh()

def setMinimun(self, min):
    self.setRange(min, self.max)

def setMaximun(self, max):
    self.setRange(self.min, max)

def setValue(self, val):
    if self._value != val:
        if val < self.min:
            self._value = self.min
        elif val > self.max:
            self._value = self.max
        else:
            self._value = val
        self.Refresh()


    self.Refresh()

def setLineWidth(self, lineWidth):
    self.lineWidth = lineWidth

def setPosition(self, x, y, width, height):
    self.position = wx.Rect(x, y, width, height)

def OnPaint(self, event=None):
    dc = wx.PaintDC(self)
    gc = self.MakeGC(dc)
    self.Draw(gc)

def MakeGC(self, dc):
    try:
        if False:
            gcr = wx.GraphicsRenderer.GetCairoRenderer
            gc = gcr() and gcr().CreateContext(dc)
            if gc is None:
                wx.MessageBox("Unable to create Cairo Context.", "Oops")
                gc = wx.GraphicsContext.Create(dc)
        else:
            gc = wx.GraphicsContext.Create(dc)

    except NotImplementedError:
        dc.DrawText("This build of wxPython does not support the wx.GraphicsContext "
                    "family of classes.",
                    25, 25)
        return None
    return gc

def Draw(self, gc):

    #middle progressbar line
    radStart = math.radians(90)
    radEnd = math.radians(0)
    path = gc.CreatePath()
    path.AddArc(80, 80, 50, radStart, radEnd, True)
    pen = wx.Pen('#000000', 4)
    pen.SetCap(wx.CAP_BUTT)
    gc.SetPen(pen)
    gc.SetBrush(wx.Brush('#000000', wx.TRANSPARENT))
    gc.DrawPath(path)

    #progress bar
    start = math.radians(90)
    #r = math.radians(270)
    arcStep = -270 / (self.max - self.min) * self._value
    end = math.radians(arcStep)
    path = gc.CreatePath()
    path.AddArc(80, 80, 50, start, end)
    pen = wx.Pen('#CC7F32', 15)
    pen.SetCap(wx.CAP_BUTT)
    gc.SetPen(pen)
    gc.SetBrush(wx.Brush('#000000', wx.TRANSPARENT))
    gc.DrawPath(path)

【问题讨论】:

    标签: python python-2.7 wxpython wxwidgets


    【解决方案1】:

    这有点可怕,因为您将所有内容都偏移了 90º,因此您必须考虑到这一点。
    这里什么都没有:

    import wx
    import math
    class TestArc(wx.Panel):
    
        def __init__(self, *args, **kwargs):
            super(TestArc, self).__init__(*args, **kwargs)
    
            self.lineWidth = 0
            self.min = -90
            self.max = 360
            self._value = 0
            self.setText = '---'
            # self.font = someFont()
            self.position = wx.Rect()  # self.position.Set(x, y, width, height)
            self.startPoint = math.radians(0)
            self.endPoint = math.radians(0)
            self.Bind(wx.EVT_PAINT, self.OnPaint)
    
        def setRange(self, min, max):
            self.min = min
            self.max = max
            if self._value < self.min:
                self._value = self.min
            elif self._value > self.max:
                self._value = self.max
            self.Refresh()
    
        def setMinimun(self, min):
            self.setRange(min, self.max)
    
        def setMaximun(self, max):
            self.setRange(self.min, max)
    
        def setValue(self, val):
            if self._value != val:
                if val < self.min:
                    self._value = self.min
                elif val > self.max:
                    self._value = self.max
                else:
                    self._value = val
            self.Refresh()
    
        def setLineWidth(self, lineWidth):
            self.lineWidth = lineWidth
    
        def setPosition(self, x, y, width, height):
            self.position = wx.Rect(x, y, width, height)
    
        def OnPaint(self, event=None):
            dc = wx.PaintDC(self)
            gc = self.MakeGC(dc)
            self.Draw(gc)
    
        def MakeGC(self, dc):
            try:
                if False:
                    gcr = wx.GraphicsRenderer.GetCairoRenderer
                    gc = gcr() and gcr().CreateContext(dc)
                    if gc is None:
                        wx.MessageBox("Unable to create Cairo Context.", "Oops")
                        gc = wx.GraphicsContext.Create(dc)
                else:
                    gc = wx.GraphicsContext.Create(dc)
            except NotImplementedError:
                dc.DrawText("This build of wxPython does not support the wx.GraphicsContext "
                            "family of classes.",
                            25, 25)
                return None
            return gc
    
        def Draw(self, gc):
            #middle progressbar line
            radStart = math.radians(90)
            radEnd = math.radians(0)
            path = gc.CreatePath()
            path.AddArc(80, 80, 50, radStart, radEnd, True)
            pen = wx.Pen('#000000', 4)
            pen.SetCap(wx.CAP_BUTT)
            gc.SetPen(pen)
            gc.SetBrush(wx.Brush('#000000', wx.TRANSPARENT))
            gc.DrawPath(path)
    
            #progress bar
            start = math.radians(90)
            #r = math.radians(270)
            arcStep = 270 / (self.max - self.min) * self._value
            end = math.radians(arcStep)
            path = gc.CreatePath()
            path.AddArc(80, 80, 50, start, end)
            pen = wx.Pen('#CC7F32', 15)
            pen.SetCap(wx.CAP_BUTT)
            gc.SetPen(pen)
            gc.SetBrush(wx.Brush('#000000', wx.TRANSPARENT))
            gc.DrawPath(path)
    
    class bandom(wx.Frame):
    
        def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title, size=(800, 600))
    
            self.gauge = TestArc(self)
            self.gauge.SetFocus()
            self.gauge.setMinimun(90)
            self.gauge.setMaximun(360)
            self.gauge.setValue(90)
    
           # timer for testing progressbar
            self.val = 90
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
            self.timer.Start(100)
    
        def OnTimer(self, evt):
           self.val += 2.7
           self.gauge.setValue(self.val)
           if self.val >= 360:
               self.val = 90
    
    if __name__ == '__main__':
        app = wx.App()
        frame = bandom(None, -1, 'Window title here')
        frame.Show(True)
        app.MainLoop()
    

    为方便起见,我将它们全部放入一个文件中。
    编辑: 将最大值更改为 360 并使用 270 计算弧中的步长的原因是您选择使用 3/4 圆作为仪表,并且您正在计算使用弧度增加仪表的量。您可以使用度数或弧度,但无论哪种方式,它都将在 0 到 270 之间计算度数,或者在 0 到 3π/2 之间计算弧度。最初您说您需要一个介于 0 和 100 之间的刻度,最简单的安排方法是将仪表计数器增加/减少 2.7 而不是 1,即 270 点行程/100(您需要的刻度)。在 0 点而不是 90 点开始仪表会更容易,但我认为您这样做是为了锻炼或出于审美原因。
    您关于需要 240 增量的最后评论,与原始问题和其他 cmets 冲突,但可以通过将仪表计数器增加 1.125 (270/240) 而不是 1 或 2.7 来实现

    编辑 2:
    在我的机器上运行此代码我没有“闪烁”。这可能取决于您的机器速度,如果您更改传递给wx.Timer 的值(目前为 100 毫秒或每秒 10 次),它可能会有所改善。请记住,此代码本质上是通过使用计时器来假装显示任务的进度,实际上您将不是基于计时器而是基于实际过程的进度将值传递给仪表。

    【讨论】:

    • 谢谢,但还是会倒退,知道我该如何解决这个问题吗?
    • 我不知道你指的是什么。使用指南针/时钟,我的代码从南 (6) 的底部开始,顺时针穿过西 (9),然后北 (12) 并在东 (3) 结束。这听起来并不“倒退”
    • 对不起,我弄错了!非常感谢
    • 方向由arcStep 的符号控制我已将其设置为正 270 您将其设置为负。如果你把它改回来,你将不得不调整开始和结束的位置,我想!
    • 谢谢!现在我需要找到一种方法来确定 0 到 100 之间的范围:)
    猜你喜欢
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-18
    • 2012-10-31
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多