Widget buttons - possible to separate parameters other than position?

I’ve created several widget buttons and switches etc in scene:create but I want to update for example the defaultFile and overFile with a different image dynamically. I tried:

 my\_btn = widget.newButton({ id = "mine", x = 200, y = 300, onPress = Game.dosomething, width = 60, height = 30, }) my\_btn.defaultFile = "images/game/on.png" my\_btn.overFile = "images/game/off.png"

But this didn’t work. But this seems to work ok but not sure why only position works unless I’m doing something wrong:

 my\_btn.x = 300 my\_btn.y = 400

@hasen

You’re conflating the table that is passed in to configure the button creation and the button.  They are separate entities. 

Question: Are you trying to create multiple buttons from the same signature or trying to update the textures used in an existing button.

You can do the prior easily,

local myButtons = {} local params = { id = "mine", x = 200, y = 300, onPress = Game.dosomething, width = 60, height = 30, defaultFile = "images/game/on\_v1.png", overFile = "images/game/off\_v1.png", } buttons[1] = widget.newButton( params ) params.y = 350 params.defaultFile = "images/game/on\_v2.png" params.overFile = "images/game/off\_v2.png" buttons[2] = widget.newButton( params ) params.y = 420 params.defaultFile = "images/game/on\_v3.png" params.overFile = "images/game/off\_v3.png" params.width = 80 params.height = 40 buttons[3] = widget.newButton( params )

The latter, I don’t think you can do without hacking the button structure.

Tip in my example I modified the table, but if all the buttons are the same, just re-use it.

I’m trying to for example create the button in scene:create and then update it’s image in scene:show. I wanted to do this with the x and y position and I was advised in another thread to separate the parameters and have the x and y parameters of the button in the scene:show. So I wanted to also do this with the defaultFile and overFile to dynamically change the image in scene:show but it doesn’t seem to work in the same way.

Looks like you’re saying I can’t do this. What would be the best way to approach this without duplicating the code in scene:create and scene:show then?

  1. I don’t understand why you want to change the images.  Do you actually mean you want to update the state of the button?  

(If you mean update the state, then simply use the state setting mechanism provided by the button you are making.)

2.  However, since you are making a push button, that makes no sense.  I think you need to be making a toggle button.

https://docs.coronalabs.com/api/library/widget/newSwitch.html

Do you know the three button types and their similarities and differences? 

  • push button (made with widget.newButton() )
  • toggle button (made with widget.newSwitch() )
  • radio button  (made with widget.newSwitch() )

If you need to make buttons that can have arbitrary images at any time, better to make your own button library.

Sorry, but I have to leave for a while.  I have been spending too much time in the forums lately and need to re-focus.  I will check back later or tomorrow.

Hopefully you resolve this or someone else can chime in with additional suggestions.

If you change the theme of the game then everything changes lol. Hence the images will change. The state already changes no problem when pressed or not pressed but the whole thing needs to swap depending on the the theme.

I would simply redraw the scene using the new theme.  That would be safer and easier.

Or… write you’re own buttons.  Reading into the widget.* objects will be messy and prone to future failure.

Or #2 … download the widget code, modify it to allow this and then use that local library instead.

Still, this can be achieved with your own button library/code much more easily.

So basically the overall answer is no you can’t separate parameters other than position. Ok thanks for clarification. :slight_smile:

No not at all. I’m saying you’re conflating the building of the button and the table used to initialize it with the button it produces.

The parameters used to build the button (that table you pass in to the newButton() function) are not accessible later.  The table is in fact gone after the create.

In your code, you’re accessing properties of the button object which are not the same as the temporary fields in that table.

To clarify, try this:

local params = { x = 200, y = 300, width = 60, height = 30, } local my\_btn = widget.newButton( params ) print( "before params.x == " .. tostring( params.x ) ) print( "before my\_btn.x == " .. tostring( my\_btn.x ) ) my\_btn.x = 300 print( "after params.x == " .. tostring( params.x ) ) print( "after my\_btn.x == " .. tostring( my\_btn.x ) )

Notice that the my_btn.x values change, but params.x do not.  i.e. The button and the table are not the same entity.

I was also saying, while you could dig into the structure of the button and locate the handles to the textures so you could modify their fill, it would be a bad idea.
 

If you could find the references to the textures, you’d change their fill with code like this:

https://docs.coronalabs.com/api/type/BitmapPaint/index.html#example

NOT by simply assigning new texture names to them.

Simply drop and recreate UI on theme change.  Something like this

local UIGroup = display.newGroup() function createUI()&nbsp; --clean group first &nbsp; for i = UIGroup.numChildren, 1, -1 do &nbsp; &nbsp; display.remove(UIGroup[i]) &nbsp; &nbsp; UIGroup[i] = nil &nbsp; end --create buttons now &nbsp; local my\_btn = widget.newButton({ &nbsp; &nbsp; id = "mine", &nbsp; &nbsp; x = 200, &nbsp; &nbsp; y = 300, &nbsp; &nbsp; onPress = Game.dosomething, &nbsp; &nbsp; width = 60, &nbsp; &nbsp; height = 30, &nbsp; &nbsp; defaultFile = "images/\<theme\>/on.png", &nbsp; &nbsp; overFile = "images/\<theme\>/off.png", &nbsp; }) UIGroup:insert(my\_btn) end

Then call createUI() whenever you want a theme change.

Yes that’s a useful workaround. I create the params in scene:create and then the rest in scene:show. I just wasn’t sure why only position can be separated but I guess that’s just the way it is.

Ok yeah that’s a good workaround too.

I keep explaining and you keep circling back to the same belief that the object will have all the fields shown in the table used to create it.  

That isn’t how it works.  I think there is some kind of communication barrier here.

Let me give you an simplified example of how this is probably being done 

-- A 'thing' builder (i.e. newButton() builds things) -- Takes a table 'tbl' of parameters. -- Returns a image rectangle with parameters applied. -- local function makeThing( tbl ) local thing = display.newImageRect( tbl.img, tbl.w, tbl.h ) thing.x = tbl.x thing.y = tbl.y if( tbl.fill ) then thing:setFillColor( unpack( tbl.fill ) ) end return thing end local params = { x = 100, y = 50, w = 200, h = 40, img = "images/smiley.png", fill = { 1, 0, 0 } } local myThing = makeThing( params )

At the end of all this, assuming I made no typos, we have:

  • makeAThing() - A builder function that takes a parameterized table and returns an image rect.  This is the equivalent of the widget function you’re calling.
  • params - A temporary table I made filled with settings to build a ‘thing’.
  • myThing - A image rect, returned by makeAThing() and built based on the settings in params.

You can set whatever properties myThing (an image rect) has and you can call whatever functions it provides.  You can’t expect doing this to have any effect:

myThing.img = "images/bob.png"

This is essentially what you’re expecting to be able to do with widgets and it simply doesn’t work that way.  The docs clearly state what properties and functions each of the widget objects has.  You can only use those.

Not sure why you think that, I understood it several posts back. In my last post I said I guess that’s just the way it is. My title for all intents and purposes was “will an object have all the fields shown in the table used to create it?” and the answer is clearly no. I get it, thanks for your help.  :slight_smile:

Yes I see that is only the case with the position parameters. It’s ok because I have managed to achieve what I need to now anyway thanks to the suggestions in this thread.

@hasen,

OK.  I guess I’m not understanding your responses and that’s fine. 

My confusion came from the fact that to me, it seemed that your posted interpretations of answers didn’t match what was said.  Again, to me and how I understood both the answers and your responses.

So, I worried you were filtering the answers through what you wanted the answer to be and how you think it should work and not what it was.  This happens sometimes and I wanted to be sure you were seeing the difference.  

Having said all that… if you are satisfied. Good enough.

@hasen

You’re conflating the table that is passed in to configure the button creation and the button.  They are separate entities. 

Question: Are you trying to create multiple buttons from the same signature or trying to update the textures used in an existing button.

You can do the prior easily,

local myButtons = {} local params = { id = "mine", x = 200, y = 300, onPress = Game.dosomething, width = 60, height = 30, defaultFile = "images/game/on\_v1.png", overFile = "images/game/off\_v1.png", } buttons[1] = widget.newButton( params ) params.y = 350 params.defaultFile = "images/game/on\_v2.png" params.overFile = "images/game/off\_v2.png" buttons[2] = widget.newButton( params ) params.y = 420 params.defaultFile = "images/game/on\_v3.png" params.overFile = "images/game/off\_v3.png" params.width = 80 params.height = 40 buttons[3] = widget.newButton( params )

The latter, I don’t think you can do without hacking the button structure.

Tip in my example I modified the table, but if all the buttons are the same, just re-use it.

I’m trying to for example create the button in scene:create and then update it’s image in scene:show. I wanted to do this with the x and y position and I was advised in another thread to separate the parameters and have the x and y parameters of the button in the scene:show. So I wanted to also do this with the defaultFile and overFile to dynamically change the image in scene:show but it doesn’t seem to work in the same way.

Looks like you’re saying I can’t do this. What would be the best way to approach this without duplicating the code in scene:create and scene:show then?

  1. I don’t understand why you want to change the images.  Do you actually mean you want to update the state of the button?  

(If you mean update the state, then simply use the state setting mechanism provided by the button you are making.)

2.  However, since you are making a push button, that makes no sense.  I think you need to be making a toggle button.

https://docs.coronalabs.com/api/library/widget/newSwitch.html

Do you know the three button types and their similarities and differences? 

  • push button (made with widget.newButton() )
  • toggle button (made with widget.newSwitch() )
  • radio button  (made with widget.newSwitch() )

If you need to make buttons that can have arbitrary images at any time, better to make your own button library.