Ruby with Java swing is saying that count is nil - ruby

Hello so i am new to javax.swing and i wanted to ask you guys why am i getting this error(i am going to put the exact error after my code). I have tried everything i can find. Thank you guys and im sorry if this is an easy fix i really suck at ruby right now
testGui.rb
# javaSwingHello.rb
require 'java' # Line 2
JFrame = javax.swing.JFrame
JLabel = javax.swing.JLabel
JPanel = javax.swing.JPanel
JButton = javax.swing.JButton
BorderFactory = javax.swing.BorderFactory
BorderLayout = java.awt.BorderLayout
GridLayout = java.awt.GridLayout
count = 1
frame = JFrame.new
panel = JPanel.new
button = JButton.new "Click me"
button.addActionListener self
label = JLabel.new "Number of clicks: 0"
panel.setBorder BorderFactory.createEmptyBorder(70, 70, 20, 70)
panel.setLayout GridLayout.new(0, 1)
panel.add button
panel.add label
frame.add panel, BorderLayout::CENTER
frame.setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE)
frame.setTitle "TEST GUI"
frame.pack
frame.setVisible true
def actionPerformed(event)
count += 1
texttoset = "Number of clicks " + count
label.setText(texttoset)
end
Error( I am getting this when i press the button )
Exception in thread "AWT-EventQueue-0" org.jruby.exceptions.NoMethodError: (NoMethodError) undefined method `+' for nil:NilClass
at testGui.actionPerformed(testGui.rb:26)

more of a Ruby question - local variables won't be copied into a new scope:
def actionPerformed(event)
count += 1
texttoset = "Number of clicks " + count
label.setText(texttoset)
end
count is a local variable for the method (initially nil) thus the failure.
if you're just testing things out you can work-around this using a global:
$count = 1
def actionPerformed(event)
$count += 1
texttoset = "Number of clicks " + count
label.setText(texttoset)
end
that being said do not use globals and rather setup a proper object that will encapsulate the state and 'implement' the actionPerformed inteface.

You did not say, how you are going to use actionPerformed, but one possibility would be make the method a lambda:
count = 1
$ActionPerformed = -> (event) do
count += 1
texttoset = "Number of clicks " + count
label.setText(texttoset)
end
You would have to invoke it as
$ActionPerformed.call(myEvent)

Related

tk.Entry validate command doesn't restore previous value when False returned

I have carefully reviewed answers to Interactively validating Entry widget content in tkinter, but my script fails to restore previous value if the validate command returns False. I captured %P and %s and print them out...They both show the same value.
import tkinter as tk
class Controller :
def __init__(self) :
i=10
j=20
# list comprehension
self.entry_widgets = [[None for col in range(j)] for row in range(i)]
#print(self.entry_widgets)
self.values = [["string"+str(row) + str(col) for col in range(10)] for row in range(20)]
#print(self.values)
class EnterBox(tk.Entry):
def __init__(self,*args,**kwargs):
#print (args)
self._modified = False
self._save = 0
self._raise = 1
self._lower = 2
frame, i,j, *newargs = args
self._content = tk.StringVar()
# tk.Entry.__init__(self,frame,*newargs,
# validate = 'focusout',
# validatecommand = vcmd,
# **kwargs)
tk.Entry.__init__(self,frame,*newargs,**kwargs)
vcmd = (self.register(self._revert), '%P', '%s')
ct.entry_widgets[i][j] = self
self.config(textvariable=self._content)
self.config(validate = "focusout")
self.config(validatecommand = vcmd )
x=(ct.values[i][j])
self.insert(0,x)
#self._content.set(x)
self.bind("<Return>",lambda event, x=self._save : self._action(event,x) )
self.bind("<Button-2>",lambda event, x=self._save : self._action(event,x) )
self.bind("<FocusIn>", lambda event, x=self._raise : self._action(event,x))
self.bind("<FocusOut>", lambda event, x=self._lower : self._action(event,x))
self.bind('<Button-3>', lambda event, x=self._lower : self._action(event,x))
self.grid(column=i+1,row=j+2)
def _revert(self,P,s):
print ("Hi There")
print(P)
print(s)
return False
def _action(self,event,action):
print(str(action)+' ' + str(event))
if action == self._save :
ct.values[i][j] = self._content.get()
self.config(bg='lightskyblue2')
self._modified = True
elif action == self._raise :
self.config(bg = 'light pink')
elif action == self._lower :
self.config(bg = 'gray80')
self._modified = False
else :
print('action value is bad action =>' + str(action))
if "__main__" == __name__ :
root = tk.Tk()
frame = tk.Frame()
i=j=0
ct = Controller()
root.grid()
frame.grid()
check = EnterBox(frame,i,j,width = 24)
check2 = EnterBox(frame,i+1,j,width = 24)
root.mainloop()
I have tried removing all other bindings, to no avail.
Interestingly, but a separate issue, If I use StringVar. set instead of self.insert, (see commented out line) the validate command runs once, and never again despite several focus changes. Using Python 3.8
The validation isn't designed to restore anything if the validation happens on focusout. The validation can only prevent characters from being added at the time they are added. You will have to add code to restore the previous value.

wxPython ListBox event not firing

I have a wx.Dialog that contains a button and 2 ListBoxes, the button findAppBtn searches through a list of directories and then displays the result in actListBox. Selecting the directory of your choice from actListBox should then fire the event EVT_LISTBOX which calls actListBoxList. This function does an ls on the directory and should list the files it finds in the lower list box binListBox using Append. Upon selecting an item from the lower ListBox, the window closes.
The problem is that the self.Bind(EVT_LISTBOX, self.actListBoxList) does not seem to be firing when an item is selected.
(also please excuse the bad coding, I am trying to get it working before minifying)
self.findAppBtn = wx.Button(panel, -1, "Find app")
self.findAppBtn.SetDefault()
self.Bind(wx.EVT_BUTTON, self.startConf, self.findAppBtn)
hBox2.Add(self.findAppBtn, 0, flag=wx.LEFT, border=5)
vBox.Add(hBox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=3)
self.actListBox = wx.ListBox(panel, choices=[])
self.Bind(wx.EVT_LISTBOX, self.actListBoxList)
vBox.Add(self.actListBox, 2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=3)
self.binListBox = wx.ListBox(panel, choices=[])
self.Bind(wx.EVT_LISTBOX, self.binListBoxList)
vBox.Add(self.binListBox, 2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=3)
self.closeBtn = wx.Button(panel, wx.ID_OK)
hBox4.Add(self.closeBtn, 0, flag=wx.LEFT, border=5)
vBox.Add(hBox4, 0, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=5)
panel.SetSizer(vBox)
def startConf(self,e):
val = self.cmdTxt.GetValue().replace(" ","\ ")
path = "/private/"
aCmd = "find " + path + " -iname '*"+val+"*.app'"
try:
s = pxssh.pxssh()
s.login(sshIP, "root", sshPort, sshPass)
s.sendline(aCmd)
s.prompt()
AP = s.before
for m in AP.split('\n'):
if path in m:
self.actListBox.Append(m.replace(path,"").strip())
s.logout()
return path
except pxssh.ExceptionPxssh as e:
self.parent.progressBox.AppendText(str(e))
def actListBoxList(self,e):
#get string from top box selection e.g xxxx-xxxx-xxxx-/myapp.app
selName = self.actListBox.GetStringSelection()
path = "/private/"
#list all the files in the dir from top box selection
aCmd = "ls " + path + selName
try:
s = pxssh.pxssh()
s.login(sshIP, "root", sshPort, sshPass)
s.sendline(aCmd)
s.prompt()
ls = s.before
for file in ls.split('\n'):
if not file.endswith("/"):
reg = r"\..*"
matchObj = re.search(reg, file)
if not matchObj:
self.binListBox.Append(file)
s.logout()
except pxssh.ExceptionPxssh as e:
self.parent.progressBox.AppendText(str(e))
def binListBoxList(self,e):
binaryName = self.binListBox.GetStringSelection()
self.Close()
EDIT: self.actListBox.Bind(wx.EVT_LISTBOX, self.actListBoxList) fixed the issue.
calling self.Bind(... binds the event to the parent window which is why you're not seeing the event being called. Bind to the listbox instead:
self.actListBox.Bind(wx.EVT_LISTBOX, self.actListBoxList)

wxpython grid: multiple cell edit (ala Excel)

I'm looking for a way for a user to edit data in bulk in a wxPython grid, a little like in Excel when you select a range, type data and press shift-Enter. This is a simplified version of my grid:
class MyGrid(gridlib.Grid):
def __init__(self, panel):
gridlib.Grid.__init__(self, panel)
self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.onEditCell)
self.Bind(gridlib.EVT_GRID_RANGE_SELECT, self.onSelection)
def onSelection(self, event):
if self.GetSelectionBlockTopLeft() == []:
self.selected_row_number = 0
self.selected_col_number = 0
else:
self.selected_row_number = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1
self.selected_col_number = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1
print self.selected_row_number, self.selected_col_number
def onEditCell(self,event):
print self.selected_row_number, self.selected_col_number
The issue seems to be that the onEditCell event overwrites the previous selection. So I can select e.g. a four by four block in the grid, and onSelection will print 4 4. But when I start typing and press Enter, onEditCell will print 0,0 as if only the cell I'm editing was selected. How can I keep a "memory" of how many cells are selected? Thank you,
Answering my own question: I can get it to work with an ugly hack that doesn't seem like the right way to do things:
def onSelection(self, event):
self.previous_selected_row_number = self.selected_row_number
self.previous_selected_col_number = self.selected_col_number
if self.GetSelectionBlockTopLeft() == []:
self.selected_row_number = 0
self.selected_col_number = 0
else:
self.selected_row_number = self.GetSelectionBlockBottomRight()[0][0] - self.GetSelectionBlockTopLeft()[0][0] + 1
self.selected_col_number = self.GetSelectionBlockBottomRight()[0][1] - self.GetSelectionBlockTopLeft()[0][1] + 1
print self.selected_row_number, self.selected_col_number
print self.previous_selected_row_number, self.previous_selected_col_number
def onEditCell(self,event):
print self.previous_selected_row_number, self.previous_selected_col_number
If anyone can think of a better way...

While debugging the function breakpoint is not hit

I am using powerbuilder 11.2 and I have a pbl that creates a main screen. The user enters an order number in the textbox and hit enter and it fills in data in the bottom of the screen. I am trying to get debugging to hit a breakpoint in my function but it seems to ignore the breakpoint. Is there a way to break into the function? I have a variable I need to evaluate and I can't seem to get into the function while running. Here is the code:
Decimal{2} ld_total_hrs,ld_load_hrs,ld_unload_hrs
long ll_stops_rowcount, ll_row, ll_type, ll_ord_number, ll_rd_rowcount
datetime ldt_1st_stop, ldt_last_stop, ldt_start_time, ldt_end_time, ldt_deliver_time
string ls_dest_id, ls_type, ls_pay_id, ls_ref_number, ls_pay_leg_config
boolean lb_first_drop = TRUE
ld_load_hrs = 0
ld_unload_hrs = 0
SetNull(ldt_deliver_time)
ll_stops_rowcount = dw_trip.RowCount()
If ll_stops_rowcount < 1 then Return 0
For ll_row = 1 to ll_stops_rowcount
If ll_row = 1 then
ldt_1st_stop = dw_trip.GetItemDateTime ( 1, "stops_stp_arrivaldate" )
End if
If dw_trip.GetItemString(ll_row,"stops_stp_type") = "PUP" then
ldt_start_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_arrivaldate")
ldt_end_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_departuredate")
ld_load_hrs = ld_load_hrs + (f_datetimediff(ldt_start_time,ldt_end_time)/60)/60
End if
If dw_trip.GetItemString(ll_row,"stops_stp_type") = "DRP" then
ldt_start_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_arrivaldate")
ldt_end_time = dw_trip.GetItemDateTime(ll_row,"stops_stp_departuredate")
ld_unload_hrs = ld_unload_hrs + (f_datetimediff(ldt_start_time,ldt_end_time)/60)/60
// get the first drops info for the report if paylegaslane is true else get last drop
ls_pay_leg_config = is_PayLegConfig
If is_CompanyOverride=true then
ls_pay_leg_config = "ByLeg"
End if
//TGRIFFIT - PayLegConfig = 'ByLeg' in TMW is equivalent to 'PayLegAsLane = 'Y' in FSS
if Upper(ls_pay_leg_config) = 'BYLEG' then
If lb_first_drop Then
ldt_deliver_time = ldt_end_time
ls_dest_id = dw_trip.GetItemString(ll_row,"stops_cmp_id")
ls_ref_number = dw_trip.GetItemString(ll_row,"stops_stp_refnum")
lb_first_drop = FALSE
End if
else
ldt_deliver_time = ldt_end_time
ls_dest_id = dw_trip.GetItemString(ll_row,"stops_cmp_id")
ls_ref_number = dw_trip.GetItemString(ll_row,"stops_stp_refnum")
end if
End if
Next
ldt_last_stop = dw_trip.GetItemDateTime ( ll_stops_rowcount, "stops_stp_departuredate" )
ld_total_hrs = (f_datetimediff(ldt_1st_stop,ldt_last_stop)/60)/60
ll_ord_number = long(dw_triptab.GetItemString(1,"ord_number"))
//If g_messlevel% < 1 Then
if gnv_app.ii_MessLevel < 1 Then
ids_revdist.Reset()
End if
//Load the datastore that stores all the revenue distribution values
ll_rd_rowcount = ids_revdist.RowCount()
ids_revdist.InsertRow(0)
ll_rd_rowcount ++
ids_revdist.SetItem(ll_rd_rowcount,"mov_number",i_movenum%)
ids_revdist.SetItem(ll_rd_rowcount,"lgh_number",dw_trip.GetItemNumber(1,"stops_lgh_number"))
ids_revdist.SetItem(ll_rd_rowcount,"total_hours",ld_total_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"load_hours",ld_load_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"unload_hours",ld_unload_hrs)
ids_revdist.SetItem(ll_rd_rowcount,"deliver_date",ldt_deliver_time)
ids_revdist.SetItem(ll_rd_rowcount,"dest_code",ls_dest_id)
ids_revdist.SetItem(ll_rd_rowcount,"ref_number",ls_ref_number)
Return ids_revdist.RowCount()
I need to evaluate this line specifically and I set a breakpoint at this line:
ls_pay_leg_config = "ByLeg"
as well as the following lines. It does not break. I am rusty at PowerBuilder and can figure this out.
Put the breakpoint at the start of the loop.

VBScript For Loop not executing if statement?

Not exactly sure how to search for this issue I have with VBScript, so please forgive if this is a duplicate.
I have a function that prints pagination on a page that takes 2 parameters, totalpgs and active. My issue is that the active page only applies the style on the link when the variable pg is NOT set. I'm pretty sure this is a logic issue but I've been staring at this for 7 days now.
Here is the function:
'======= Print Pagination links
function print_pagination (totalpgs,active)
p = "<div class=""row"">"
p = p & "<div class=""pagination pagination-right"">"
p = p & "<ul>"
for x = 1 to totalpgs
if x = active then
li = "<li class=""active"">" '<- Set class for current page
else
li = "<li>" '<- else regular link
end if
p = p & li & "<a href='?pg="& x &"'>"& x &"</a></li>"
next
p = p & "</ul></div></div>"
print_pagination = p
end function
Here is the code on the page:
pg = request.querystring("pg")
if pg = "" then
pg = 1
end if
<%=print_pagination(totalpages,pg) %>
Here is the desired result:
I want the current <li> to contain a class called active.
This is what's happening:
The active class never gets applied to the <li> tag. When the url contains the get variable of pg, no active class is assigned. When it does not, then it's applied to the first link.
Change your line that does the comparison to this:
if cstr(x) = cstr(active) then

Resources