sábado, 25 de abril de 2015

wxPython double slider widget to enter a range.

I had this problem to enter a range of times in a wxPython application. After some research I could not found a widget that does what I need. The closest I could get was a Slider with SL_SELRANGE
style. Unfortunatelly this option is only available in Windows.

So I decide to create a small widget with two sliders to select the maximum and minimum time. If the minimum goes over the maximum the maximum is updated and viceversa. The selected values are updated as labels.





This is the code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class RangeSlider (wx.Panel):
    MAX_VALUE = 1000

    def __init__ (self, parent, minTime, maxTime):
        super(RangeSlider, self).__init__(parent, wx.ID_ANY)

        self.minTime = minTime
        self.maxTime = maxTime

        sizer = wx.FlexGridSizer (rows=2, cols = 3, vgap = 5, hgap = 5)
        self.sldMax = wx.Slider(self, value=RangeSlider.MAX_VALUE, minValue=0,
                maxValue=self.MAX_VALUE,
                style=wx.SL_HORIZONTAL )
        self.sldMin = wx.Slider (self, value=0, minValue=0,
                maxValue=self.MAX_VALUE,
                style =wx.SL_HORIZONTAL )

        self.sldMax.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        self.sldMin.Bind (wx.EVT_SCROLL, self.OnSliderScroll2)

        self.txtMax = wx.StaticText(self, label= self.formatTime (self.maxTime))
        self.txtMin = wx.StaticText(self, label=self.formatTime (self.minTime))

        lab1 = wx.StaticText (self, label="Min " + self.formatTime (self.minTime))
        lab2 = wx.StaticText (self, label="Max " + self.formatTime (self.maxTime))

        sizer.Add (lab1, 0, wx.LEFT, 10)
        sizer.Add (self.sldMax, 1, wx.EXPAND)
        sizer.Add (lab2, 0, wx.RIGHT, 10)
        sizer.Add (self.txtMin, 1, wx.ALIGN_CENTER)
        sizer.Add (self.sldMin, 1, wx.EXPAND)
        sizer.Add (self.txtMax, 1, wx.ALIGN_CENTER)
        sizer.AddGrowableCol (1, 1)

        self.SetSizer (sizer)

    def formatTime (self, t):
        return "%02d:%02d:%02d" % (t / 3600, (t%3600)/60, t%60)

    def formatValue (self, v):
        t = v * (self.maxTime - self.minTime) / 1000
        return self.formatTime (t)


    def OnSliderScroll(self, e):

        val = self.sldMax.GetValue()

        valMin = self.sldMin.GetValue ()
        if valMin > val:
            self.sldMin.SetValue (val)
            self.txtMin.SetLabel (self.formatValue(val))

        self.txtMax.SetLabel(self.formatValue(val))

    def OnSliderScroll2 (self, e):
        val = self.sldMin.GetValue()

        valMax = self.sldMax.GetValue ()
        if valMax < val:
            self.sldMax.SetValue (val)
            self.txtMax.SetLabel (self.formatValue(val))

        self.txtMin.SetLabel(self.formatValue(val))


class Example(wx.Frame):

    def __init__(self, parent, minTime, maxTime):
        """ The time is seconds """
        super(Example, self).__init__(parent, wx.ID_ANY)


        self.InitUI(minTime, maxTime)


    def InitUI(self, minTime, maxTime):

        rangeSlider = RangeSlider (self,minTime, maxTime)

        self.SetTitle('RangeSlider')
        self.Centre()
        self.Show(True)

def main():

    ex = wx.App()
    Example(None, 0, 7200)
    ex.MainLoop()

if __name__ == '__main__':
    main()



No hay comentarios:

Publicar un comentario