I am having an error when trying to access a file with a tab bar constructed within it. Does anyone know what I am doing wrong. Corona SDK tells me my error is in the section of code where I actually create the tab bar, not the buttons. Thanks
Below is my code for the MainPage.lua scene in which the tab bar is created.
local tabBar = nil
function scene: create (event)
local group = scene.view
local tabButtons =
{
{
width = 20,
height = 32,
defaultFile = "assets/home.png",
overFile = "assets/PressHome.png",
label = "Home",
font = tabLabelFont,
size = tabLabelFontSize,
onPress = function() composer.gotoScene( "Home" ); end,
},
{
width = 20,
height = 32,
defaultFile = "assets/Explore.png",
overFile = "assets/Explore.png",
label = "Explore",
font = tabLabelFont,
size = tabLabelFontSize,
onPress = function() composer.gotoScene( "Explore" ); end,
},
{
width = 20,
height = 32,
defaultFile = "assets/Post.png",
overFile = "assets/Post.png",
label = "Post",
font = tabLabelFont,
size = tabLabelFontSize,
onPress = function() composer.gotoScene( "Post" ); end,
},
{
width = 20,
height = 32,
defaultFile = "assets/Notification.png",
overFile = "assets/Notification.png",
label = "Notification",
font = tabLabelFont,
size = tabLabelFontSize,
onPress = function() composer.gotoScene( "Notification" ); end,
},
{
width = 20,
height = 32,
defaultFile = "assets/Profile.png",
overFile = "assets/Profile.png",
label = "Profile",
font = tabLabelFont,
size = tabLabelFontSize,
onPress = function() composer.gotoScene( "Profile" ); end,
}
}
-- Create a tab-bar and place it at the bottom of the screen
tabBar = widget.newTabBar
{
top = display.contentHeight - 50,
width = display.contentWidth,
backgroundFile = "assets/tabbar.png",
tabSelectedLeftFile = "assets/tabBar_tabSelectedLeft.png",
tabSelectedMiddleFile = "assets/tabBar_tabSelectedMiddle.png",
tabSelectedRightFile = "assets/tabBar_tabSelectedRight.png",
tabSelectedFrameWidth = 20,
tabSelectedFrameHeight = 52,
buttons = tabButtons
}
group: insert(tabBar)
composer.gotoScene("Home")
end
scene:addEventListener( "create", scene )
return scene
here is the method from the log in page that is supposed to access the tab bar page.
local function EnterPage( event )
composer.gotoScene("MainPage")
end
this is what the error is saying
stack traceback:
?: in function '?'
?: in function <?:703>
(tail call): ?
?: in function <?:122>
(tail call): ?
MainPage.lua:127: in main chunk
[C]: in function 'require'
?: in function <?:797>
(tail call): ?
LogIn.lua:78: in function <LogIn.lua:70>
?: in function <?:218>
line 127 of Main Page is the line that states "tabBar = widget.newTabBar"
The errors in the log in page just go to the gotoScene(MainPage) method
"File: ? Attempt to index a nil value" is very helpful: it says that you are doing an operation of the form a.b like a.b = something or a.b() where a is nil. Given the line it happens on, this is surely because you forgot
widget = require 'widget'
near the top of your file.
If that line is already there (in MainPage.lua), then check that widget hasn't been overwritten:
print('widget is', widget)
tabBar = widget.newTabBar
...
If it is not nil then you have made an error in the information you posted (wrong line number, etc) or maybe you tried many things and info got mixed up. You could try, just to be sure,
widget = require 'widget'
tabBar = widget.newTabBar
If that works, then you know you are overwriting widget somewhere in your MainPage.lua, in code not shown. You should also try
test = widget.newButton
{
left = 100, top = 200,
label = "Default",
onEvent = function() print('hi') end
}
If that works, but the newTabBar still doesn't work, try replacing your options with those of the example on corona newTabBar site.
Related
I am constructing widgets dynamically from from the output of iw dev interface scan I then add them to a scroll box held in a wibox. The problem I find is that the mouse::enter and mouse::leave signals I connect the widgets to do not catch the mouse signals when inside the wibox.container.scroll. All the rest of the code works as intended and the signals are caught as intended if I omit the wibox.container.scroll wrapper.
The widget template to be added to the scroll container:
function wifitbox.new(ssid, screen, interface)
tbox = wibox.widget{
{
{
wibox.widget.textbox(ssid[2] .. " " .. ssid[3]),
{
wibox.widget.textbox(ssid[4]),
halign = "right",
widget = wibox.container.place
},
layout = wibox.layout.ratio.horizontal
},
margins = beautiful.xresources.apply_dpi(10, screen),
widget = wibox.container.margin
},
id = "tbox",
bg = beautiful.wifi_tbox_bg or "#928374",
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end,
widget = wibox.container.background
}
awful.spawn.easy_async('bash -c "sudo iw dev ' .. interface .. ' station dump | awk \'FNR == 1 {print($2)}\'"', function(stdout)
if(gears.string.split(stdout, "\n")[1] == ssid[1]) then
tbox.bg = "#b16286"
end
end)
tbox:connect_signal("mouse::enter", function()
tbox.bg_cache = tbox.bg
tbox.bg = "#689d6a"
end)
tbox:connect_signal("mouse::leave", function()
tbox.bg = tbox.bg_cache
end)
return tbox
end
The two :signal_connect() statements are the ones in questions.
The widgets are added to the scroll container a follows:
awful.spawn.with_line_callback(cmd, {
stdout = function(line)
local ssid = gears.string.split(line, "\t")
wifitbox_table:get_children_by_id("tbox_list")[1]:add(wifitbox(ssid, screen, interface))
end,
output_done = function()
self:set_widget(wifitbox_table)
end
})
The widget the containing the scroll container is as follows:
local wifitbox_table = wibox.widget{
scrollbtn,
{
id = "scroll_box",
speed = 100,
extra_space = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.container.scroll.vertical,
step_function = wibox.container.scroll.step_functions.linear_increase,
{
id= "tbox_list",
spacing = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.layout.fixed.vertical()
}
},
spacing = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.layout.fixed.vertical,
}
As I mentioned before if i remove the "scroll_box" widget around the "tbox_list" widget the signals connect without issue. But then obviously I don't get scrolling.
And finally all of it put together:
local awful = require('awful')
local wibox = require('wibox')
local gears = require('gears')
local beautiful = require('beautiful')
local wifimodal = { mt = {} }
local wifitbox = { mt = {} }
local setmetatable = setmetatable
function wifitbox.new(ssid, screen, interface)
tbox = wibox.widget{
{
{
wibox.widget.textbox(ssid[2] .. " " .. ssid[3]),
{
wibox.widget.textbox(ssid[4]),
halign = "right",
widget = wibox.container.place
},
layout = wibox.layout.ratio.horizontal
},
margins = beautiful.xresources.apply_dpi(10, screen),
widget = wibox.container.margin
},
id = "tbox",
bg = beautiful.wifi_tbox_bg or "#928374",
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end,
widget = wibox.container.background,
}
awful.spawn.easy_async('bash -c "sudo iw dev ' .. interface .. ' station dump | awk \'FNR == 1 {print($2)}\'"', function(stdout)
if(gears.string.split(stdout, "\n")[1] == ssid[1]) then
tbox.bg = "#b16286"
end
end)
tbox:connect_signal("mouse::enter", function()
tbox.bg_cache = tbox.bg
tbox.bg = "#689d6a"
end)
tbox:connect_signal("mouse::leave", function()
tbox.bg = tbox.bg_cache
end)
return tbox
end
function wifitbox.mt.__call(_, ...)
return wifitbox.new(...)
end
setmetatable(wifitbox, wifitbox.mt)
function wifimodal.new(screen, interface, curSSID)
self = wibox {
screen = screen,
width = screen.geometry.width / 5,
type = 'modal',
height = screen.workarea.height/2,
x = screen.geometry.width - screen.geometry.width/5,
y = beautiful.xresources.apply_dpi(beautiful.wibar_height or 25, screen),
ontop = true,
visible = true,
bg = beautiful.bg_normal,
fg = "black",
opacity = 0.8,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end
}
self:connect_signal('mouse::leave', function()
self.visible = false
self = nil
end)
local scrollbtn = wibox.widget{
{
{
widget = wibox.widget.imagebox,
resize = true,
image = gears.filesystem.get_configuration_dir() .. "widgets/wifi/arrow_up.png",
forced_height = beautiful.xresources.apply_dpi(25, screen),
},
widget = wibox.container.place,
valign = "center",
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end,
widget = wibox.container.background,
bg = beautiful.wifi_scroll_btn_bg or "#d79921",
}
scrollbtn:connect_signal("mouse::enter", function()
scrollbtn:emit_signal_recursive("scroll::continue")
scrollbtn.bg = beautiful.wifi_scroll_btn_bg_hover or "#458588"
end)
scrollbtn:connect_signal("mouse::leave", function()
scrollbtn:emit_signal_recursive("scroll::pause")
scrollbtn.bg = beautiful.wifi_scroll_btn_bg or "#d79921"
end)
local scan_awk = gears.filesystem.get_configuration_dir() .. "widgets/wifi/scan.awk"
local cmd = 'bash -c "sudo iw ' .. interface .. ' scan | awk -f ' .. scan_awk .. '"'
local wifitbox_table = wibox.widget{
scrollbtn,
{
id = "scroll_box",
speed = 100,
extra_space = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.container.scroll.vertical,
step_function = wibox.container.scroll.step_functions.linear_increase,
{
id= "tbox_list",
spacing = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.layout.fixed.vertical()
}
},
spacing = beautiful.xresources.apply_dpi(5, screen),
layout = wibox.layout.fixed.vertical,
}
local scrollbox = wifitbox_table:get_children_by_id("scroll_box")[1]
scrollbox:pause()
wifitbox_table:connect_signal("scroll::continue", function()
scrollbox:continue()
end)
wifitbox_table:connect_signal("scroll::pause", function()
scrollbox:pause()
end)
awful.spawn.with_line_callback(cmd, {
stdout = function(line)
local ssid = gears.string.split(line, "\t")
wifitbox_table:get_children_by_id("tbox_list")[1]:add(wifitbox(ssid, screen, interface))
end,
output_done = function()
self:set_widget(wifitbox_table)
end
})
return self
end
function wifimodal.mt.__call(_, ...)
return wifimodal.new(...)
end
return setmetatable(wifimodal, wifimodal.mt)
Here is a screen shot for some context:
Also, if you don't have the answer but notice something else you can critic feel free. Thank you
The problem I find is that the mouse::enter and mouse::leave signals I connect the widgets to do not catch the mouse signals when inside the wibox.container.scroll
The third sentence on https://awesomewm.org/doc/api/classes/wibox.container.scroll.html is:
Please note that mouse events do not propagate to widgets inside of the scroll container.
So, this is "working as intended".
Also: https://github.com/awesomeWM/awesome/issues/3076
I get the following error message from Corona SDK : attempt to call field "ImageSheet" (a nil value) stack traceback. Can somebody point out the mistake?
local ISPar = {
width = 2541,
height = 264,
numFrames = 7
}
local ImageSheet = graphics.ImageSheet("Apus.png, ISPar")
local ApusSequenceData = {
{name = "fly", frames {1,2,3,4,5,6,7}, time = 800, loopCount = 0}
}
local Apus = display.newSrpite(ImageSheet, ApusSequenceData)
Apus.x = display.contentWidth/2
Apus.y = display.contentHeight/2
Apus:play()
You got the function name wrong, it was supposed to be graphics.newImageSheet. Also you misplaced the quotation marks when calling it. And afterwards you misspelt newSprite
This code should work:
local ISPar = {
width = 2541,
height = 264,
numFrames = 7
}
local ImageSheet = graphics.newImageSheet("Apus.png", ISPar)
local ApusSequenceData = {{name = "fly", frames = {1,2,3,4,5,6,7}, time = 800, loopCount = 0}}
local Apus = display.newSprite(ImageSheet, ApusSequenceData)
Apus.x = display.contentWidth/2
Apus.y = display.contentHeight/2
Apus:play()
I am attempting to create a list of items using the TableView widget in Corona. I followed their online examples and created the TableView. It appears on the screen and is scrollable, but no event is fired when I click a row, even though I set a listener for OnRowTouch.
local options_for_list_view = {
id = "list_view",
top = 0,
left = 0,
width = display.contentWidth,
height = display.contentHeight,
hideBackground = true,
hideScrollBar = true,
listener = on_table_touch,
onRowRender = onRowRender,
onRowTouch = on_row_touch, -- registering listener
}
list_view = widget.newTableView(options_for_list_view)
for key, value in pairs(trophy_list) do
local params =
{
name = key
}
list_view:insertRow
{
isCategory = false,
rowHeight = total_height * 0.1,
rowColor = rowColor,
lineColor = { 0, 0, 0 },
params = params
}
end
Here is the listener:
local function on_row_touch( event )
print("error")
end
Does anyone know what the issue could be?
You should define Your on_row_touch( event ) function BEFORE adding it to the options_for_list_view Table.
Objects in Lua are created in the same order as listed in sources. So, in Your case, You're just putting a nil into the onRowTouch event's listener place. And just after that creating a local function which was supposed to be an event listener :)
Some proper static analysis tool should help getting rid of this kind of errors...
Good luck ;)
Simplified version:
print(foo())
function foo()
return "some_value..."
end
Output:
lua: ./call_test.lua:1: attempt to call global 'foo' (a nil value)
In this app I'm creating with Corona SDK, when you win the text "You win" sould appear, but doesn't. I could post all the code, but I don't think the rest would be hepful, so here is only the essencial:
_H = display.contentHeight;
_W = display.contentWidth;
mRand = math.random;
o = 0;
time_remain = 20;
time_up = false;
total_orbs = 45;
total_secs = 20;
ready = false;
local backGround = display.newImage("media/bg.png");
backGround.xScale = 2;
backGround.yScale = 2;
loseMSG = display.newText("You Lose!", _W/2, _H/2, nil, 50)
loseMSG.isVisible = false
winMSG = display.newText("You Win!", _W/2, _H/2, nil, 50)
winMSG.isVisible = false
local countdowntxt = display.newText(time_remain, 0, 0, native.systemFont, 60);
countdowntxt.xScale = .5; countdowntxt.yScale = .5;
countdowntxt:setReferencePoint(display.BottomRightReferencePoint);
countdowntxt.x = _W-20; display.y = _H-20;
countdowntxt:setTextColor(0, 0, 0)
function winLose(condition)
if (condition == "Win") then
bgAlpha = display.newImage("media/bgAlpha.png");
bgAlpha.xScale = 2;
bgAlpha.yScale = 2;
winMSG.isVisible = true -- Here the win text should become visible, but doesn't
elseif (condition == "Fail") then
bgAlpha = display.newImage("media/bgAlpha.png");
bgAlpha.xScale = 2;
bgAlpha.yScale = 2;
loseMSG.isVisible = true
end
end
Any Ideas why?
You need to take a divide and conquer approach.
Does this work?
winMSG = display.newText("You Win!", _W/2, _H/2, nil, 50)
winMSG.isVisible = true <-- note this is set to true
It does?
Does winLose every get called? Put a print statement in it or a break point or whatever you use on your platform to debug.
It does?
What does the variable condition contain? Inspect it/print it out and verify that it is indeed "Win", same case, no spaces, etc. or you can put a print statement in the appropriate branch of that function to make sure it's being hit.
Is that OK?
Does it show up if you remove the bgAlpha code?
So on and so forth.
I don't know Corona, but Googling the docs for newText it's possible you have the parameters wrong (you're not passing a font).
I could post all the code
The less you post the better, because that means you've already gone through the steps shown above to try to isolate the problem. Nine times out of ten, doing that will reveal the problem all by itself.
Why have you given nil for font value?
Atleast pass the default system font
loseMSG = display.newText("You Lose!", _W/2, _H/2, native.systemFont, 50)
winMSG = display.newText("You Win!", _W/2, _H/2, native.systemFont, 50)
how do you make a default table and then use it when making other tables?
example
--default table
Button = {
x = 0,
y = 0,
w = 10,
h = 10,
Texture = "buttonimg.png",
onClick = function() end
}
newbutton = Button {
onClick = function()
print("button 1 pressed")
end
}
newbutton2 = Button {
x = 12,
onClick = function()
print("button 2 pressed")
end
}
newbuttons will get y, w, h and texture set to default value but anything set in the brackets get overwritten
You can achieve what you want by merging Doug's answer with your original scenario, like this:
Button = {
x = 0,
y = 0,
w = 10,
h = 10,
Texture = "buttonimg.png",
onClick = function() end
}
setmetatable(Button,
{ __call = function(self, init)
return setmetatable(init or {}, { __index = Button })
end })
newbutton = Button {
onClick = function()
print("button 1 pressed")
end
}
newbutton2 = Button {
x = 12,
onClick = function()
print("button 2 pressed")
end
}
(I actually tested this, it works.)
Edit: You can make this a bit prettier and reusable like this:
function prototype(class)
return setmetatable(class,
{ __call = function(self, init)
return setmetatable(init or {},
{ __index = class })
end })
end
Button = prototype {
x = 0,
y = 0,
w = 10,
h = 10,
Texture = "buttonimg.png",
onClick = function() end
}
...
If you set the new table's metatable's __index to point to Button it will use the default values from the Button table.
--default table
Button = {
x = 0,
y = 0,
w = 10,
h = 10,
Texture = "buttonimg.png",
onClick = function() end
}
function newButton () return setmetatable({},{__index=Button}) end
Now when you make buttons with newButton() they use the default values from the Button table.
This technique can be used for class or prototype object oriented programming. There are many examples here.