Slider Widget Bug

I believe I found a bug with the slider widget using a custom image sheet.  Of course, there’s always a good chance I’m just doing something wrong.  But this issue is 100% reproducible.  

When I go to the scene where my slider widget is, it looks like this:

If I exit the scene and go back in, it looks the same.  If I move the slider hard over to the left or right, it still looks fine as I think it should like this:

But if I exit the scene, and then return with the slider in that position, the graphics seem to get a little mangled.  In the image below, I moved the slider back to the right a bit so you could see what I mean:

Is it possible that I did something wrong in my image sheet?  Here’s a shot of it:

BTW, this happens in Simulator and on Android for sure.

Can you boil this down to just the scene and widget code you’re using and maybe provide the code and images here? That would let us reproduce your problem.

If you’re really convinced and no-one here can dispute it, submit a bug report with your boiled-down solution.

I use a globals.lua table to save settings, this will be required to show this issue:

[lua]

–globals.lua

local t = {}

–Volume settings

t.musicVolume = .5

t.FXVolume = .5 

return t

[/lua]

This is the stripped down code showing the slider widgets.  The behavior is 100% constant… but only if you move a slider hard over one way or the other, exit the settings.lua scene, and return with the sliders still hard over to one side.

[lua]

–gameSettings.lua


–Start off by requiring composer and creating a scene.


local composer = require ( “composer” )

local globals = require(‘globals’)

local widget = require( “widget” )

widget.setTheme( “widget_theme_android_holo_dark” )

local scene = composer.newScene()

native.setProperty( “androidSystemUiVisibility”, “immersive” )  – hide nave bar on newer Android Devices

– local forward references go here

_W = display.contentWidth

_H = display.contentHeight

   


– “scene:create()”


function scene:create( event )

    local sceneGroup = self.view

    --print( “Menu: Creating Stuff”)

        

–=============================================================

–================SLIDERS TO CONTROL SOUND FX==================

–=============================================================

local sliderGroup = display.newGroup()

sceneGroup:insert(sliderGroup)

–==========Music Volume==========–

local sliderNum = globals.musicVolume*100

local sliderText = nil 

local function sliderListener( event )    

sliderText.text = event.value…"%"

globals.musicVolume = event.value/100

audio.setVolume( globals.musicVolume, {channel=1 } )

–print( "Slider at " … event.value … "%  globals.musicVolume at "…globals.musicVolume )

end

local sliderWidth = 300 

local sliderHeight = 50

local sliderX = _W * .625

local sliderY = _H * .211

local sliderHeader = display.newImageRect( “images/boxHeader.png”, sliderWidth*.9, 45)

sliderHeader.x = sliderX

sliderHeader.y = sliderY-sliderHeight*.5

sliderGroup:insert(sliderHeader)

local musicText = display.newText( “Music Volume”, sliderHeader.x, sliderHeader.y-15, “saranaigamebold”, 18 )

musicText:setFillColor( 1 )

sliderGroup:insert(musicText)

local sliderBack = display.newImageRect( “images/sliderBack.png”, sliderWidth, sliderHeight)

sliderBack.x = sliderX

sliderBack.y = sliderY

sliderGroup:insert(sliderBack)

   

local numBox = display.newImageRect( “images/numBox.png”, sliderBack.width*.2, sliderBack.height*.75)

numBox.x = sliderBack.x+sliderBack.width*.655

numBox.y = sliderBack.y

sliderGroup:insert(numBox)

sliderText = display.newText( sliderNum…"%", numBox.x, numBox.y, “saranaigamebold”, 14 )

sliderText:setFillColor( 1 )

sliderText.anchor = .5

sliderGroup:insert(sliderText)

local sliderOptions = {

frames = {

{x=800, y=2, width=160, height=279}, --rightFrame (org 1 ) 1

{x=638, y=-15, width=160, height=279}, --fillFrame (org 3 ) 2

{x=476, y=-15, width=160, height=279}, --middleFrame (org 4 ) 3

{x=314, y=2, width=160, height=279},–leftFrame (org 5) 4

{x=2, y=2, width=310, height=310}, --handleFrame (org 2 ) 5

},

sheetContentWidth = 962,

sheetContentHeight = 314

}

local sliderSheet = graphics.newImageSheet( “images/sliderSheet.png”, sliderOptions )

local slider = widget.newSlider(

{

sheet = sliderSheet,

leftFrame = 4, --5

middleFrame = 3, --4

rightFrame = 1, --1

fillFrame = 2, --3

frameWidth = 10,

frameHeight = 25,

handleFrame = 5, --2

handleWidth = 64,

handleHeight = 64,

x = sliderX,

y = sliderY,

width = sliderWidth-15,

listener = sliderListener,

value = sliderNum

}

)

sliderGroup:insert(slider)

–==========FX Volume==========–

local sliderNum2 = globals.FXVolume*100

local sliderText2 = nil 

local function sliderListener2( event )    

sliderText2.text = event.value…"%"

globals.FXVolume = event.value/100

audio.setVolume( globals.FXVolume, {channel=2 } )

–print( "Slider at " … event.value … "%  globals.FXVolume at "…globals.FXVolume )

end

local sliderWidth2 = 300 

local sliderHeight2 = 50

local sliderX2 = _W * .625

local sliderY2 = _H * .5

local sliderHeader2 = display.newImageRect( “images/boxHeader.png”, sliderWidth2*.9, 45)

sliderHeader2.x = sliderX2

sliderHeader2.y = sliderY2-sliderHeight2*.5

sliderGroup:insert(sliderHeader2)

local musicText2 = display.newText( “FX Volume”, sliderHeader2.x, sliderHeader2.y-15, “saranaigamebold”, 18 )

musicText2:setFillColor( 1 )

sliderGroup:insert(musicText2)

local sliderBack2 = display.newImageRect( “images/sliderBack.png”, sliderWidth2, sliderHeight2)

sliderBack2.x = sliderX2

sliderBack2.y = sliderY2

sliderGroup:insert(sliderBack2)

   

local numBox2 = display.newImageRect( “images/numBox.png”, sliderBack2.width*.2, sliderBack2.height*.75)

numBox2.x = sliderBack2.x+sliderBack2.width*.655

numBox2.y = sliderBack2.y

sliderGroup:insert(numBox2)

sliderText2 = display.newText( sliderNum2…"%", numBox2.x, numBox2.y, “saranaigamebold”, 14 )

sliderText2:setFillColor( 1 )

sliderText2.anchor = .5

sliderGroup:insert(sliderText2)

local sliderOptions2 = {

frames = {

{x=800, y=2, width=160, height=279}, --rightFrame (org 1 ) 1

{x=638, y=-15, width=160, height=279}, --fillFrame (org 3 ) 2

{x=476, y=-15, width=160, height=279}, --middleFrame (org 4 ) 3

{x=314, y=2, width=160, height=279},–leftFrame (org 5) 4

{x=2, y=2, width=310, height=310}, --handleFrame (org 2 ) 5

},

sheetContentWidth = 962,

sheetContentHeight = 314

}

local sliderSheet2 = graphics.newImageSheet( “images/sliderSheet.png”, sliderOptions2 )

local slider2 = widget.newSlider(

{

sheet = sliderSheet2,

leftFrame = 4, --5

middleFrame = 3, --4

rightFrame = 1, --1

fillFrame = 2, --3

frameWidth = 10,

frameHeight = 25,

handleFrame = 5, --2

handleWidth = 64,

handleHeight = 64,

x = sliderX2,

y = sliderY2,

width = sliderWidth2-15,

listener = sliderListener2,

value = sliderNum2

}

)

sliderGroup:insert(slider2)

–=============================================================

–================END SLIDERS TO CONTROL SOUND FX==============

–=============================================================

   

    local function menuReturn( event )

        if ( “ended” == event.phase ) then

composer.gotoScene( “menu”, “slideRight”, 500 )

        end 

    end

    

    ------------------------------------------------------------------------

    --New Return to Menu Button

    ------------------------------------------------------------------------

    local menuButton = widget.newButton

    {       

        label = “Back”,

        labelColor = { default={ 1, 1, 1 }, over={ 0, 0, 0, 1 } },

        onEvent = menuReturn,

width = _W*.18,

        height = _H*.15,

        x = _W*.89,

        y = _H*.89,

        defaultFile = “images/yellowButton.png”,

        overFile = “images/yellowButtonOver.png”,

        font = “saranaigamebold”,

        fontSize = 14

    }    

    sceneGroup:insert(menuButton)    

    ------------------------------------------------------------------------

    --End New Return to Menu Button

    ------------------------------------------------------------------------

       

end  --end Scene Create Function


– “scene:show()”


function scene:show( event )

    local sceneGroup = self.view

    local phase = event.phase

    --print( “Menu: Showing stuff” )

    if ( phase == “will” ) then

        – Called when the scene is still off screen (but is about to come on screen).

    elseif ( phase == “did” ) then

– Called when the scene is now on screen.

        – Insert code here to make the scene come alive.

        – Example: start timers, begin animation, play audio, etc.

composer.removeHidden()

    end

end


– “scene:hide()”


function scene:hide( event )

    local sceneGroup = self.view

    local phase = event.phase

    --print( “Menu: Hiding stuff” )

    if ( phase == “will” ) then

        – Called when the scene is on screen (but is about to go off screen).

        – Insert code here to “pause” the scene.

        – Example: stop timers, stop animation, stop audio, etc.

    elseif ( phase == “did” ) then

        – Called immediately after scene goes off screen.

    end

end


– “scene:destroy()”


function scene:destroy( event )

    local sceneGroup = self.view

    --print( “Menu: Destroying stuff” )

    – Called prior to the removal of scene’s view (“sceneGroup”).

    – Insert code here to clean up the scene.

    – Example: remove display objects, save state, etc.

end


– Listener setup

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )


return scene

[/lua]

All the images required by settings.lua are attached in a .zip file.

Hi @kthompson200,

I seem to recall seeing this before, awhile back, but I need to explore what’s happening. I’ll keep you posted…

Brent

Can you boil this down to just the scene and widget code you’re using and maybe provide the code and images here? That would let us reproduce your problem.

If you’re really convinced and no-one here can dispute it, submit a bug report with your boiled-down solution.

I use a globals.lua table to save settings, this will be required to show this issue:

[lua]

–globals.lua

local t = {}

–Volume settings

t.musicVolume = .5

t.FXVolume = .5 

return t

[/lua]

This is the stripped down code showing the slider widgets.  The behavior is 100% constant… but only if you move a slider hard over one way or the other, exit the settings.lua scene, and return with the sliders still hard over to one side.

[lua]

–gameSettings.lua


–Start off by requiring composer and creating a scene.


local composer = require ( “composer” )

local globals = require(‘globals’)

local widget = require( “widget” )

widget.setTheme( “widget_theme_android_holo_dark” )

local scene = composer.newScene()

native.setProperty( “androidSystemUiVisibility”, “immersive” )  – hide nave bar on newer Android Devices

– local forward references go here

_W = display.contentWidth

_H = display.contentHeight

   


– “scene:create()”


function scene:create( event )

    local sceneGroup = self.view

    --print( “Menu: Creating Stuff”)

        

–=============================================================

–================SLIDERS TO CONTROL SOUND FX==================

–=============================================================

local sliderGroup = display.newGroup()

sceneGroup:insert(sliderGroup)

–==========Music Volume==========–

local sliderNum = globals.musicVolume*100

local sliderText = nil 

local function sliderListener( event )    

sliderText.text = event.value…"%"

globals.musicVolume = event.value/100

audio.setVolume( globals.musicVolume, {channel=1 } )

–print( "Slider at " … event.value … "%  globals.musicVolume at "…globals.musicVolume )

end

local sliderWidth = 300 

local sliderHeight = 50

local sliderX = _W * .625

local sliderY = _H * .211

local sliderHeader = display.newImageRect( “images/boxHeader.png”, sliderWidth*.9, 45)

sliderHeader.x = sliderX

sliderHeader.y = sliderY-sliderHeight*.5

sliderGroup:insert(sliderHeader)

local musicText = display.newText( “Music Volume”, sliderHeader.x, sliderHeader.y-15, “saranaigamebold”, 18 )

musicText:setFillColor( 1 )

sliderGroup:insert(musicText)

local sliderBack = display.newImageRect( “images/sliderBack.png”, sliderWidth, sliderHeight)

sliderBack.x = sliderX

sliderBack.y = sliderY

sliderGroup:insert(sliderBack)

   

local numBox = display.newImageRect( “images/numBox.png”, sliderBack.width*.2, sliderBack.height*.75)

numBox.x = sliderBack.x+sliderBack.width*.655

numBox.y = sliderBack.y

sliderGroup:insert(numBox)

sliderText = display.newText( sliderNum…"%", numBox.x, numBox.y, “saranaigamebold”, 14 )

sliderText:setFillColor( 1 )

sliderText.anchor = .5

sliderGroup:insert(sliderText)

local sliderOptions = {

frames = {

{x=800, y=2, width=160, height=279}, --rightFrame (org 1 ) 1

{x=638, y=-15, width=160, height=279}, --fillFrame (org 3 ) 2

{x=476, y=-15, width=160, height=279}, --middleFrame (org 4 ) 3

{x=314, y=2, width=160, height=279},–leftFrame (org 5) 4

{x=2, y=2, width=310, height=310}, --handleFrame (org 2 ) 5

},

sheetContentWidth = 962,

sheetContentHeight = 314

}

local sliderSheet = graphics.newImageSheet( “images/sliderSheet.png”, sliderOptions )

local slider = widget.newSlider(

{

sheet = sliderSheet,

leftFrame = 4, --5

middleFrame = 3, --4

rightFrame = 1, --1

fillFrame = 2, --3

frameWidth = 10,

frameHeight = 25,

handleFrame = 5, --2

handleWidth = 64,

handleHeight = 64,

x = sliderX,

y = sliderY,

width = sliderWidth-15,

listener = sliderListener,

value = sliderNum

}

)

sliderGroup:insert(slider)

–==========FX Volume==========–

local sliderNum2 = globals.FXVolume*100

local sliderText2 = nil 

local function sliderListener2( event )    

sliderText2.text = event.value…"%"

globals.FXVolume = event.value/100

audio.setVolume( globals.FXVolume, {channel=2 } )

–print( "Slider at " … event.value … "%  globals.FXVolume at "…globals.FXVolume )

end

local sliderWidth2 = 300 

local sliderHeight2 = 50

local sliderX2 = _W * .625

local sliderY2 = _H * .5

local sliderHeader2 = display.newImageRect( “images/boxHeader.png”, sliderWidth2*.9, 45)

sliderHeader2.x = sliderX2

sliderHeader2.y = sliderY2-sliderHeight2*.5

sliderGroup:insert(sliderHeader2)

local musicText2 = display.newText( “FX Volume”, sliderHeader2.x, sliderHeader2.y-15, “saranaigamebold”, 18 )

musicText2:setFillColor( 1 )

sliderGroup:insert(musicText2)

local sliderBack2 = display.newImageRect( “images/sliderBack.png”, sliderWidth2, sliderHeight2)

sliderBack2.x = sliderX2

sliderBack2.y = sliderY2

sliderGroup:insert(sliderBack2)

   

local numBox2 = display.newImageRect( “images/numBox.png”, sliderBack2.width*.2, sliderBack2.height*.75)

numBox2.x = sliderBack2.x+sliderBack2.width*.655

numBox2.y = sliderBack2.y

sliderGroup:insert(numBox2)

sliderText2 = display.newText( sliderNum2…"%", numBox2.x, numBox2.y, “saranaigamebold”, 14 )

sliderText2:setFillColor( 1 )

sliderText2.anchor = .5

sliderGroup:insert(sliderText2)

local sliderOptions2 = {

frames = {

{x=800, y=2, width=160, height=279}, --rightFrame (org 1 ) 1

{x=638, y=-15, width=160, height=279}, --fillFrame (org 3 ) 2

{x=476, y=-15, width=160, height=279}, --middleFrame (org 4 ) 3

{x=314, y=2, width=160, height=279},–leftFrame (org 5) 4

{x=2, y=2, width=310, height=310}, --handleFrame (org 2 ) 5

},

sheetContentWidth = 962,

sheetContentHeight = 314

}

local sliderSheet2 = graphics.newImageSheet( “images/sliderSheet.png”, sliderOptions2 )

local slider2 = widget.newSlider(

{

sheet = sliderSheet2,

leftFrame = 4, --5

middleFrame = 3, --4

rightFrame = 1, --1

fillFrame = 2, --3

frameWidth = 10,

frameHeight = 25,

handleFrame = 5, --2

handleWidth = 64,

handleHeight = 64,

x = sliderX2,

y = sliderY2,

width = sliderWidth2-15,

listener = sliderListener2,

value = sliderNum2

}

)

sliderGroup:insert(slider2)

–=============================================================

–================END SLIDERS TO CONTROL SOUND FX==============

–=============================================================

   

    local function menuReturn( event )

        if ( “ended” == event.phase ) then

composer.gotoScene( “menu”, “slideRight”, 500 )

        end 

    end

    

    ------------------------------------------------------------------------

    --New Return to Menu Button

    ------------------------------------------------------------------------

    local menuButton = widget.newButton

    {       

        label = “Back”,

        labelColor = { default={ 1, 1, 1 }, over={ 0, 0, 0, 1 } },

        onEvent = menuReturn,

width = _W*.18,

        height = _H*.15,

        x = _W*.89,

        y = _H*.89,

        defaultFile = “images/yellowButton.png”,

        overFile = “images/yellowButtonOver.png”,

        font = “saranaigamebold”,

        fontSize = 14

    }    

    sceneGroup:insert(menuButton)    

    ------------------------------------------------------------------------

    --End New Return to Menu Button

    ------------------------------------------------------------------------

       

end  --end Scene Create Function


– “scene:show()”


function scene:show( event )

    local sceneGroup = self.view

    local phase = event.phase

    --print( “Menu: Showing stuff” )

    if ( phase == “will” ) then

        – Called when the scene is still off screen (but is about to come on screen).

    elseif ( phase == “did” ) then

– Called when the scene is now on screen.

        – Insert code here to make the scene come alive.

        – Example: start timers, begin animation, play audio, etc.

composer.removeHidden()

    end

end


– “scene:hide()”


function scene:hide( event )

    local sceneGroup = self.view

    local phase = event.phase

    --print( “Menu: Hiding stuff” )

    if ( phase == “will” ) then

        – Called when the scene is on screen (but is about to go off screen).

        – Insert code here to “pause” the scene.

        – Example: stop timers, stop animation, stop audio, etc.

    elseif ( phase == “did” ) then

        – Called immediately after scene goes off screen.

    end

end


– “scene:destroy()”


function scene:destroy( event )

    local sceneGroup = self.view

    --print( “Menu: Destroying stuff” )

    – Called prior to the removal of scene’s view (“sceneGroup”).

    – Insert code here to clean up the scene.

    – Example: remove display objects, save state, etc.

end


– Listener setup

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )


return scene

[/lua]

All the images required by settings.lua are attached in a .zip file.

Hi @kthompson200,

I seem to recall seeing this before, awhile back, but I need to explore what’s happening. I’ll keep you posted…

Brent