Acess a widget from another class? - python

I am trying to update a wx.ListCtrl from another class. This is driving me crazy, and I don't understand what exactly I'm doing wrong. The widget is created inside a wx.Frame like:
class DataTable(gridlib.GridTableBase):
def __init__(self, data):
gridlib.GridTableBase.__init__(self)
self.data = data
#Store the row and col length to see if table has changed in size
self._rows = self.GetNumberRows()
self._cols = self.GetNumberCols()
print(self._rows, self._cols)
self.odd=gridlib.GridCellAttr()
self.odd.SetBackgroundColour((217,217,217))
self.even=gridlib.GridCellAttr()
self.even.SetBackgroundColour((255,255,255))
def GetAttr(self, row, col, kind):
attr = [self.even, self.odd][row % 2]
attr.IncRef()
return attr
def GetNumberRows(self):
return len(self.data)
def GetNumberCols(self):
return len(self.data.columns) + 1
def IsEmptyCell(self, row, col):
return False
def GetValue(self, row, col):
if col == 0:
pass
# return None #self.data.index[row]
else:
return self.data.iloc[row, col-1]
def SetValue(self, row, col, value):
if col == 0:
pass
else:
self.data.iloc[row, col - 1] = value
def GetColLabelValue(self, col):
try:
if col == 0:
return ""
#return 'Index' if self.data.index.name is None else self.data.index.name
else:
return self.data.columns[col - 1] #[col-1]
except:
pass
class DataGrid(gridlib.Grid):
def __init__(self, parent, data): # data
gridlib.Grid.__init__(self, parent, - 1) #,colnames,-1 # data
self.table = DataTable(data)
self.SetTable(self.table, True)
self.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChanged)
def onCellChanged(self,event):
#Establish connection
self.connect_mysql()
#Update database
key_id = str("'") + self.GetCellValue(event.GetRow(),1) + str("'") #FOR TESTING. CHANGE TO 0 WHEN IMPORT IS FIXED
target_col = self.GetColLabelValue(event.GetCol())
key_col = self.GetColLabelValue(1) #FOR TESTING. CHANGE TO 0 WHEN IMPORT IS FIXED
nVal = str("'") + self.GetCellValue(event.GetRow(),event.GetCol()) + str("'")
sql_update = "UPDATE " + tbl + " SET " + target_col + " = " + nVal + " WHERE " + key_col + " = " + key_id + ""
try:
self.cursor.execute(sql_update)
stat = "UPDATE"
oVal = event.GetString()
action = "UPDATE"
msg = "Changed " + str("'") + oVal + str("'") + " to " + nVal + " for " + key_id + " in table: " + str("'") + tbl + str("'")
#self.updateStatus()
except:
stat = "ERROR"
msg = "ERROR: Failed to update SQL table. " + "'" + tbl + "'"
self.db_con.rollback()
#Update dataframe
#Log the change
#MainFrame.test_print(stat,msg)
#MainFrame.lc_change.Append(["1","2", "3" + "\n"])
#Close connection
self.close_connection()
class MainFrame(wx.Frame):
def __init__(self, parent, data): # (self, parent, data):
wx.Frame.__init__(self, parent, -1, "Varkey Foundation") #, size=(640,480))
#Create a panel
self.p = wx.Panel(self)
self.Maximize(True)
#Create blank dataframe
data = pd.DataFrame() #pd.DataFrame(np.random.randint(0,100,size=(200, 5)),columns=list('EFGHD')
#data.reset_index(drop=True, inplace=True)
self.data = DataTable(data)
self.nb = wx.Notebook(self.p)
self.p.SetBackgroundColour( wx.Colour( 0, 0, 0 ) ) # 38,38,38
self.nb.SetBackgroundColour(wx.Colour(58, 56, 56) )
#self.SetBackgroundColour( wx.Colour( 255, 255, 56 ) )
#create the page windows as children of the notebook
self.page1 = PageOne(self.nb)
self.page2 = PageTwo(self.nb)
self.page3 = PageThree(self.nb)
# add the pages to the notebook with the label to show on the tab
self.nb.AddPage(self.page1, "Data")
self.nb.AddPage(self.page2, "Analyze")
self.nb.AddPage(self.page3, "Change Log")
#Create the grid and continue layout
self.grid = DataGrid(self.page1, data)
#grid.SetReadOnly(5,5, True)
#CreateFonts
self.b_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.BOLD, True)
self.lbl_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.NORMAL, True)
self.cb_font = wx.Font(11,wx.SCRIPT,wx.ITALIC,wx.NORMAL, True)
self.h_font = wx.Font(18,wx.DECORATIVE,wx.ITALIC,wx.BOLD, True)
#Create Title bmp
ico = wx.Icon('varkey_bmp.bmp', wx.BITMAP_TYPE_ICO) #'varkey_frame.bmp'
self.SetIcon(ico)
#Page 1 sizers and widgets
self.title = wx.StaticText(self.page1,label="TITLE",style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE)
self.title.SetForegroundColour((255,255,255))
self.title.SetFont(self.h_font)
self.p1_sizer = wx.BoxSizer(wx.VERTICAL)
self.p1_sizer.Add(self.title,0,wx.EXPAND,5)
self.p1_sizer.Add(self.grid,3,wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM ,25)
#self.p1_sizer.Add(self.btn_new,-0,wx.ALIGN_CENTER,5)
self.page1.SetSizer(self.p1_sizer)
#Page 2 sizers and widgets
self.analyze_grid = gridlib.Grid(self.page2)
self.analyze_grid.CreateGrid(0, 10)
self.p2_sizer = wx.BoxSizer(wx.VERTICAL)
self.p2_sizer.Add(self.analyze_grid,1,wx.EXPAND)
self.page2.SetSizer(self.p2_sizer)
#Page 3 sizers and widgets
self.log_grid = gridlib.Grid(self.page3)
self.log_grid.CreateGrid(0, 9)
self.log_grid.EnableEditing(False)
self.p3_sizer = wx.BoxSizer(wx.VERTICAL)
self.p3_sizer.Add(self.log_grid,1,wx.EXPAND)
self.page3.SetSizer(self.p3_sizer)
#Create widgets for top sizer
#Insert Image
self.staticbitmap = wx.StaticBitmap(self.p)
self.staticbitmap.SetBitmap(wx.Bitmap('varkey_logo2.jpg'))
self
self.lbl_user = wx.StaticText(self.p,label="Username:")
self.lbl_password = wx.StaticText(self.p,label="Password:")
self.lbl_interaction = wx.StaticText(self.p,label="Interaction:")
self.lbl_table = wx.StaticText(self.p,label="Table:")
#SetForground colors
self.lbl_user.SetForegroundColour((255,255,255))
self.lbl_password.SetForegroundColour((255,255,255))
self.lbl_interaction.SetForegroundColour((255,255,255))
self.lbl_table.SetForegroundColour((255,255,255))
#Set Fonts
self.lbl_user.SetFont(self.lbl_font)
self.lbl_password.SetFont(self.lbl_font)
self.lbl_interaction.SetFont(self.lbl_font)
self.lbl_table.SetFont(self.lbl_font)
self.tc_user =wx.TextCtrl(self.p,value='cmccall95',size = (130,25))
self.tc_password =wx.TextCtrl(self.p,value='Achilles95', style=wx.TE_PASSWORD | wx.TE_PROCESS_ENTER,size = (130,25))
self.tc_password.Bind(wx.EVT_TEXT_ENTER,self.onLogin)
self.tc_user.SetFont(self.cb_font)
self.tc_password.SetFont(self.cb_font)
self.btn_login = wx.Button(self.p,label="Login", size=(105,30))
self.btn_login.SetBackgroundColour(wx.Colour(198, 89, 17))
self.btn_login.SetFont(self.b_font)
self.btn_login.Bind(wx.EVT_BUTTON, self.onLogin) #connect_mysql
self.btn_logout = wx.Button(self.p,label="Logout",size=(105,30))
self.btn_logout.SetBackgroundColour(wx.Colour(192,0,0))
self.btn_logout.SetFont(self.b_font)
#self.btn_logout.Bind(wx.EVT_BUTTON, self.onLogout)
self.combo_interaction = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
self.combo_interaction.Bind(wx.EVT_COMBOBOX, self.onComboInteraction)
self.combo_table = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
self.combo_table.Bind(wx.EVT_COMBOBOX, self.onHideCommands)
self.combo_interaction.SetFont(self.cb_font)
self.combo_table.SetFont(self.cb_font)
#self.combo_table.Bind(wx.EVT_COMBOBOX ,self.OnComboTable)
self.btn_load = wx.Button(self.p,label="Load Table", size=(105,30))
self.btn_load.SetBackgroundColour(wx.Colour(31, 216, 6))
self.btn_load.SetFont(self.b_font)
#self.btn_load.Bind(wx.EVT_BUTTON, self.onLoadData)
self.btn_load.Bind(wx.EVT_BUTTON, self.test_reload)
self.lc_change = wx.ListCtrl(self.p,-1,style = wx.TE_MULTILINE | wx.LC_REPORT | wx.LC_VRULES)
self.lc_change.InsertColumn(0,"User ID")
self.lc_change.InsertColumn(1,"Status")
self.lc_change.InsertColumn(2,"Description")
self.lc_change.InsertColumn(3,"Date/Time")
#Set column widths
self.lc_change.SetColumnWidth(0, 75)
self.lc_change.SetColumnWidth(1, 75)
self.lc_change.SetColumnWidth(2, 450)
self.lc_change.SetColumnWidth(3, 125)
#Add Row Button
#self.btn_new = wx.Button(self.page1,label="+", size = (35,25))
#self.btn_new.SetForegroundColour(wx.Colour(112,173,71))
#self.btn_new.SetFont(self.h_font)
#self.btn_new.Bind(wx.EVT_BUTTON, self.onInsertRecordBelow)
#Create Filler text
self.lbl_filler = wx.StaticText(self.p,label="",size = (125,20))
#Create FlexGridSizers(For top half)
self.left_fgs = wx.FlexGridSizer(3,4,25,15)
self.left_fgs.AddMany([(self.lbl_user,1,wx.ALIGN_LEFT | wx.LEFT,15),(self.tc_user,1,wx.EXPAND),(self.lbl_interaction,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_interaction,1,wx.EXPAND),
(self.lbl_password,1,wx.ALIGN_LEFT| wx.LEFT,15),(self.tc_password,1,wx.EXPAND),(self.lbl_table,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_table),
(self.btn_login,2,wx.EXPAND),(self.btn_logout,1,wx.EXPAND),(self.lbl_filler,1,wx.EXPAND),(self.btn_load,1)])
#Create Top Sizer
self.top_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.top_sizer.Add(self.left_fgs,proportion = 1, flag = wx.ALL|wx.EXPAND,border = 30)
self.top_sizer.Add(self.staticbitmap,2,wx.TOP | wx.RIGHT, border = 40) #30
self.top_sizer.Add(self.lc_change,2,wx.RIGHT|wx.EXPAND ,30)
#create Bottom Sizer
self.bottom_sizer = wx.BoxSizer(wx.VERTICAL)
self.bottom_sizer.Add(self.nb,proportion = 5, flag = wx.LEFT |wx.RIGHT | wx.EXPAND,border = 30)
self.mainsizer = wx.BoxSizer(wx.VERTICAL)
self.mainsizer.Add(self.top_sizer,proportion = 0, flag = wx.ALL|wx.EXPAND,border = 5)
self.mainsizer.Add(self.bottom_sizer,proportion = 1,flag = wx.ALL|wx.EXPAND,border = 5)
#self.mainsizer.Add(self.status_sizer,proportion =0,flag = wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, border = 15)
self.p.SetSizerAndFit(self.mainsizer)
self.hideWidgets()
self.onHideCommands(self)
#### Some functions...
if __name__ == '__main__':
import sys
app = wx.App()
frame = MainFrame(None, sys.stdout) # (None, sys.stdout)
frame.Show(True)
app.MainLoop()
I have another grid class where have some bound events.
class DataGrid(gridlib.Grid):
def __init__(self, parent, data):
gridlib.Grid.__init__(self, parent, - 1) #,colnames,-1
self.table = DataTable(data)
self.SetTable(self.table, True)
self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)
self.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChanged)
def onCellChanged(self,event):
try:
stat = "UPDATE"
msg = "Changed " + str("'") + self.oVal + str("'") + " to " + self.nVal + " for " + self.key_id + " in table: " + str("'") + tbl + str("'")
except:
stat = "ERROR"
msg = "ERROR: Failed to update SQL table. " + "'" + tbl + "'"
#self.updateStatus()
#MainFrame.test_print(stat,msg)
#self.MainFrame.lc_change.Append(["1","2", "3" + "\n"])
I have tried passing it directly to a function.
MainFrame.test_print(stat,msg)
Which works to pass the variables. The problem is when using "self", I get an error.
Then I've tried accessing the list control directly:
self.MainFrame.lc_change.Append(["1","2", "3" + "\n"])
And:
MainFrame.lc_change.Append(["1","2", "3" + "\n"])
These 2 give me "type object 'xxx' has no attribute 'xxx'
Can anyone tell me what I'm doing wrong?

What you need to do is to be able to allow the DataGrid to have a reference to the wx.ListCtrl that MainFrame creates.
class MainFrame(wx.Frame):
def __init__(self, parent, data): # (self, parent, data):
wx.Frame.__init__(self, parent, -1, "Varkey Foundation") #, size=(640,480))
#Create a panel
self.p = wx.Panel(self)
#Create the ListCtrl here:
self.lc_change = wx.ListCtrl(self.p,-1,style = wx.TE_MULTILINE | wx.LC_REPORT | wx.LC_VRULES)
...
# Later when you create the DataGrid:
#Create the grid and continue layout
self.grid = DataGrid(self.page1, data, self.lc_change) # pass in the ListCtrl
...
class DataGrid(gridlib.Grid):
def __init__(self, parent, data, lc):
gridlib.Grid.__init__(self, parent, - 1) #,colnames,-1
self.lc = lc
...
def onCellChanged(self,event):
...
self.lc.Append(["1","2", "3" + "\n"]) # Now update the ListCtrl

Related

VTK textactor not showing

I'm using VTK to show textactor with info 'ID' added to the actors. When my mouse is over an actor, the MouseEvent will call an 'add_text' function. The function was called and printed the correct 'ID' but there's no textactor adding to the window, is there any problem with my program?
class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, parent=None):
self.AddObserver("MouseMoveEvent", self.MouseMove)
self.LastPickedActor = None
self.LastPickedProperty = vtk.vtkProperty()
self.new = vtkTextActor()
self.old = vtkTextActor()
self.on_actor = False
def add_text(self,renderer,ID):
self.new.SetInput(ID)
txtprop = self.new.GetTextProperty()
txtprop.SetFontSize(36)
self.new.SetDisplayPosition(0,0)
# renderer.RemoveActor(self.old)
self.old = self.new
if self.on_actor:
renderer.AddActor(self.new)
print("add_text called , ID : ",ID)
else:
pass
# renderer.RemoveActor(self.old)
# renderer.RemoveActor(self.new)
def MouseMove(self,obj,event):
Mousepos = self.GetInteractor().GetEventPosition()
picker = vtk.vtkPropPicker()
picker.Pick(Mousepos[0], Mousepos[1], 0, self.GetDefaultRenderer())
self.NewPickedActor = picker.GetActor()
if self.NewPickedActor:
if not self.on_actor:
self.on_actor = True
print("on actor")
info = self.NewPickedActor.GetProperty().GetInformation()
info = str(info)
pattern_1 = re.compile(r"ID.*\d+")
pattern_2 = re.compile(r"\d+")
string = pattern_1.findall(info)[0]
ID = pattern_2.findall(string)[0]
# print("ID : ",ID)
self.add_text(self.GetDefaultRenderer() , ID)
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
self.NewPickedActor.GetProperty().SetDiffuse(1.0)
self.NewPickedActor.GetProperty().SetSpecular(0.0)
self.LastPickedActor = self.NewPickedActor
else:
pass
else:
print("not on actor")
self.on_actor = False
Update , the problem is solved, source code :
class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, parent=None):
self.AddObserver("LeftButtonPressEvent", self.leftButtonPressEvent)
self.AddObserver("LeftButtonReleaseEvent", self.leftButtonReleaseEvent)
self.AddObserver("MouseMoveEvent", self.MouseMove)
self.LastPickedActor = None
self.LastPickedProperty = vtk.vtkProperty()
self.new = vtkTextActor()
self.old = vtkTextActor()
self.on_actor = False
self.picker = vtk.vtkPropPicker()
def add_text(self,renderer,ID):
self.new.SetInput(ID)
txtprop = self.new.GetTextProperty()
txtprop.SetFontSize(72)
self.new.SetDisplayPosition(0,0)
self.old = self.new
if self.on_actor:
renderer.AddActor(self.new)
# print("ID : ",ID)
def MouseMove(self,obj,event):
Mousepos = self.GetInteractor().GetEventPosition()
picker = vtk.vtkPropPicker()
picker.Pick(Mousepos[0], Mousepos[1], 0, self.GetDefaultRenderer())
self.NewPickedActor = picker.GetActor()
if self.NewPickedActor:
self.on_actor = True
# print("on actor")
info = self.NewPickedActor.GetProperty().GetInformation()
info = str(info)
pattern_1 = re.compile(r"ID.*\d+")
pattern_2 = re.compile(r"\d+")
string = pattern_1.findall(info)[0]
ID = pattern_2.findall(string)[0]
# print("ID : ",ID)
self.add_text(self.GetDefaultRenderer() , ID)
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
self.NewPickedActor.GetProperty().SetDiffuse(1.0)
self.NewPickedActor.GetProperty().SetSpecular(0.0)
self.LastPickedActor = self.NewPickedActor
self.OnLeftButtonDown()
self.OnLeftButtonUp()
else:
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.on_actor = False
self.GetDefaultRenderer().RemoveActor(self.new)
self.GetDefaultRenderer().RemoveActor(self.old)
self.OnLeftButtonDown()
self.OnLeftButtonUp()
def leftButtonPressEvent(self, obj, event):
self.RemoveObservers("MouseMoveEvent")
self.OnLeftButtonDown()
def leftButtonReleaseEvent(self, obj, event):
self.AddObserver("MouseMoveEvent",self.MouseMove)
self.OnLeftButtonUp()

what's the matter in this Python code?

I'm writing a unit converter using PyQt 4. Here, I'm facing a problem.
class UnitConverter(QtGui.QComboBox):
def __init__(self, parent=None):
super(UnitConverter, self).__init__(parent)
self.unitsdict = {
"mass": {"g": 1, "kg": 1000, "t": 1000000, "oz": 28.3495231, "lb": 453.59237},
"pressure": {"pa": 1, "kpa": 1000, "mpa": 1000000, "bar": 100000, "atm": 101325,
"tor": 133.3223684, "psi": 6894.757, "at": 98066.5}
}
def combo(self, measurement):
for key in self.unitsdict[measurement]:
self.addItem(self.tr(key), self.unitsdict[measurement][key])
def comboConnect(self, table, row, column):
self.names = locals()
#tablevar = "self.table_" + str(row) + "_" + str(column)
self.rowvar = "self.row_" + str(row) + "_" + str(column)
self.columnvar = "self.column_" + str(row) + "_" + str(column)
self.names[self.rowvar] = row
self.names[self.columnvar] = column
self.table = table
self.base = self.itemData(self.currentIndex())
self.currentIndexChanged.connect(self.change)
def change(self):
tobase = self.itemData(self.currentIndex())
try:
self.value = float(self.table.item(self.names[self.rowvar], self.names[self.columnvar]).text())
tovalue = '%f' % (self.value * self.base / tobase)
changeitem = QtGui.QTableWidgetItem(str(tovalue))
self.table.setItem(self.names[self.rowvar], self.names[self.columnvar], changeitem)
except:
pass
self.base = tobase
I want it can automatically calculate the result when I change the index of the combobox.
It works when there is only one QTableWidgetItem connect to it.
table = QTableWidget(10, 3)
combo = Unit converter()
combo.combo("pressure")
table.setCellWidget(5, 0, combo)
combo.comboConnect(table, 5, 1)
But when I connect another QTableWidgetItem, the first one unexpectedly doesn't work any more.
table = QTableWidget(10, 3)
combo = Unit converter()
combo.combo("pressure")
table.setCellWidget(5, 0, combo)
combo.comboConnect(table, 5, 1)
combo.comboConnect(table, 5, 2)
So, I want to know what the problem is. Or, how can I do to make the table(5, 1) work again?
the main problem is that you are overwriting many variables so you only see the last saved data, for example self.rowvar and self.columnvar save the last row and column, instead of updating you must add it to a list or something similar.
class UnitConverter(QtGui.QComboBox):
def __init__(self, table, parent=None):
super(UnitConverter, self).__init__(parent)
self.unitsdict = {
"mass": {"g": 1, "kg": 1000, "t": 1000000, "oz": 28.3495231, "lb": 453.59237},
"pressure": {"pa": 1, "kpa": 1000, "mpa": 1000000, "bar": 100000, "atm": 101325,
"tor": 133.3223684, "psi": 6894.757, "at": 98066.5}
}
self.table = table
self.base = -1
self.items = []
self.currentIndexChanged.connect(self.change)
def combo(self, measurement):
for key in self.unitsdict[measurement]:
self.addItem(self.tr(key), self.unitsdict[measurement][key])
self.base = self.itemData(self.currentIndex())
def comboConnect(self, row, column):
self.items.append((row, column))
def change(self, ix,):
tobase = self.itemData(ix)
factor = self.base / tobase
self.base = tobase
for r, c in self.items:
it = self.table.item(r, c)
try:
value = float(it.text())
tovalue = '%f' % (value * factor)
it.setText(tovalue)
except:
pass
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
table = QtGui.QTableWidget(10, 3)
combo = UnitConverter(table)
combo.combo("pressure")
table.setCellWidget(5, 0, combo)
combo.comboConnect(5, 1)
combo.comboConnect(5, 2)
table.show()
sys.exit(app.exec_())

pyqtgraph plot widget is not update

I have two working stream.
1 - receiving data from com port and sends signal.
def __packet_parser(self, *args):
while self.__thred_is_runing:
data = self.__connection.read_all()
if data != b'':
self.change_data.emit(self.__readline())
self.__callback(self.__readline())
2 - draw graph.
def set_value_by_plot_name(self, value, name='default'):
self.__plots[name].setData(np.append(self.__plots[name].getData()[1][1:], value))
def __test(self, value):
tmp = value.decode('windows-1252')
data = tmp.split('\t')
if len(data) == 10:
self.__gr.set_value_by_plot_name(int(data[1]))
def main(self):
self.__window = Window()
self.__gr = Graphics()
w = self.__gr.get_widget()
self.__window.add_widget(w)
connect = COMPortConnection('COM7', 38400)
connect.change_data.connect(self.__test)
connect.open()
self.__window.show()
few seconds everything works fine, and then ceases to be updated.
What problem?
Data is updated, picture is not.
I had a similar problem, i solved it by passing by an intermediate method i'm not sure why:
class GraphWindowController:
# init ...
def start_graph(self):
# ... process
self.view.run_graph(self.graph_nodes)
stream_signals_and_slots = []
my_steam_signal.connect(self.add_value_to_graph)
def add_value_to_graph(self, values):
self.view.update(values)
class GraphWindow(QtGui.QFrame, Ui_GraphWindow):
def __init__(self, parent=None):
"""Initializer."""
super(GraphWindow, self).__init__(parent)
self.setupUi(self)
self.connect_signals()
self.plot_widget = None
self.y_data = []
self.x_data = []
self.curve = []
self.display_range = None
self.velocity = None
self.values_to_display = None
self.count_value_to_display = 0
self.legend = None
self.build_gui()
# Doing stuff ...
def build_gui(self):
self.plot_widget = pg.PlotWidget()
layout = QtGui.QGridLayout()
self.PlotLayout.setLayout(layout)
layout.addWidget(self.plot_widget, 0,1)
def configure_graph(self, display_range, velocity):
self.display_range = display_range
self.velocity = velocity
self.plot_widget.setLabels(left='axis 1')
self.legend = pg.LegendItem((100, 60), offset=(70, 30))
self.legend.setParentItem(self.plot_widget.graphicsItem())
self.plot_widget.showGrid(True, True, 251)
self.plot_widget.showButtons()
self.plot_widget.setRange(rect=None, xRange=[0, self.display_range], yRange=[
1300, -300], padding=0.09, update=True, disableAutoRange=True)
def run_graph(self, values_to_display):
self.values_to_display = values_to_display
self.curve_number = len(self.values_to_display)
for i in range(self.curve_number):
self.y_data.append([])
colors_to_use = self.enumerate_colors(
self.curve_number)
# Blablabla doing stuff ...
def update(self, my_values):
value = my_values
for i in range(self.curve_number):
if len(self.y_data[i]) >= int((self.display_range * 1000) / self.velocity):
del self.y_data[i][0]
else:
my_var = len(self.x_data) * (self.velocity / 1000.0)
self.x_data.append(my_var)
self.y_data[i].append(int(value[i]))
my_data_to_display = list(
zip(self.x_data, self.y_data[i]))
my_array = np.array(my_data_to_display)
self.curve[i].setData(my_array)

SQLite Python; writing a value that populates a grid from a slider to the database

I want to populate a SQLite database with a value from a slider widget. I can update a cell using the keyboard but I can't get it to work when the cell is populated from the slider. I am using a button to trigger the population and the write to the database but when I click it, I get a 'sqlite3.OperationError: near "0": syntax error. Here is my code:
import wx
import wx.grid as gridlib
import sqlite3
class Grid(gridlib.Grid):
def __init__(self, parent, db):
gridlib.Grid.__init__(self, parent)
self.CreateGrid(10,5)
for row in range(10):
rowNum = row + 1
self.SetRowLabelValue(row, "cue %s" %rowNum)
self.db = db
self.cur = self.db.con.cursor()
meta = self.cur.execute("SELECT * from CUES")
labels = []
for i in meta.description:
labels.append(i[0])
labels = labels[1:]
for i in range(len(labels)):
self.SetColLabelValue(i, labels[i])
all = self.cur.execute("SELECT * from CUES ORDER by DTindex")
for row in all:
row_num = row[0]
cells = row[1:]
for i in range(len(cells)):
if cells[i] != None and cells[i] != "null":
self.SetCellValue(row_num, i, str(cells[i]))
self.Bind(gridlib.EVT_GRID_CELL_CHANGED, self.CellContentsChanged)
def CellContentsChanged(self, event):
x = event.GetCol()
y = event.GetRow()
val = self.GetCellValue(y,x)
if val == "":
val = "null"
ColLabel = self.GetColLabelValue(x)
InsertCell = "UPDATE CUES SET %s = ? WHERE DTindex = %d"%(ColLabel,y)
self.cur.execute(InsertCell, [(val),])
self.db.con.commit()
self.SetCellValue(y, x, val)
class TestFrame(wx.Frame):
def __init__(self, parent, db):
wx.Frame.__init__(self, parent, -1, "Grid plus db", size = (800,600))
panel = wx.Panel(self, -1)
self.db = db
self.cur = self.db.con.cursor()
sizer = wx.GridBagSizer(vgap=10, hgap=10)
self.slide1 = wx.Slider(panel, -1, 0, 0, 255, size=(50,400),
style=wx.SL_VERTICAL|wx.SL_AUTOTICKS|wx.SL_LABELS|wx.SL_INVERSE)
self.slide1.SetTickFreq(10)
self.Bind(wx.EVT_SCROLL_CHANGED, self.onReport, self.slide1)
self.slide2 = wx.Slider(panel, -1, 0, 0, 255, size=(50,400),
style=wx.SL_VERTICAL|wx.SL_AUTOTICKS|wx.SL_LABELS|wx.SL_INVERSE)
self.slide2.SetTickFreq(10)
self.grid = Grid(panel,db)
self.display = wx.TextCtrl(panel, -1, size=(200,100), style=wx.TE_MULTILINE)
self.aBtn = wx.Button(panel, -1, "Grid")
self.Bind(wx.EVT_BUTTON, self.onPopulate, self.aBtn)
self.bBtn = wx.Button(panel, -1, "Database")
sizer.Add(self.slide1, pos=(0,0))
sizer.Add(self.slide2, pos=(0,1))
sizer.Add(self.grid, pos = (0,2))
sizer.Add(self.aBtn, pos=(1,0))
sizer.Add(self.display, pos=(1,1), span=(2,2))
sizer.Add(self.bBtn, pos=(2,0))
panel.SetSizer(sizer)
panel.Fit()
def onReport(self,event):
val = self.slide1.GetValue()
self.display.WriteText("Slide 1 value = %s\n"%val)
def onPopulate(self, event):
"""Work in Progress"""
val = str(self.slide1.GetValue()) + '\n'
#put a dlg here to get row col - place in SetCellValue(x,y,....
self.grid.SetCellValue(0,0, val) #gets it to the grid...Need to write it to the database
InsertCell = "UPDATE CUES SET %s = ? WHERE DTindex = %d"%(0,0)
self.cur.execute(InsertCell, [(val),])
self.db.con.commit()
class GetDatabase():
def __init__(self, f):
try:
file = open(f)
file.close()
except IOError:
self.exists = 0
else:
self.exists = 1
self.con = sqlite3.connect(f)
if __name__ == "__main__":
import sys
db = GetDatabase("data.db")
app = wx.App()
frame = TestFrame(None, db)
frame.Show(True)
app.MainLoop()
The database was created in DB Browser for SQLite:
CREATE TABLE CUES (
DTindex INTEGER,
A string,
B string,
C string,
D string,
E string,
PRIMARY KEY(DTindex)
);
I think that it's a simple error in this line:
InsertCell = "UPDATE CUES SET %s = ? WHERE DTindex = %d"%(0,0)
0 whilst a valid value for DTindex is a not a valid value for a column name, which would be A,B,C,D or E.
Without knowing exactly what you are attempting to achieve, the following will function.
InsertCell = "UPDATE CUES SET %s = ? WHERE DTindex = %d"%('A',0)
But only if you have a record with a DTindex of 0 (zero), where it replaces the value of the column A with the value from your slider

python ObjectListView updating display with blank lines, even though the list has valid data

I have a list that updates ObjectListView, it previously worked, but in troubleshooting a different issue, I somehow broke it but now can't figure out why its not working.
When the program parses a directory it is supposed to updated the list view with info about .mp3 files found. It is updating the display, but only with blank lines. However, if you force an output to the command line it shows that the content of the list is correct.
To even confuse me further, I have a second list that acts as a type of 'log'. It works correctly, and they both use the same technique to update their respective lists. I have checked the code to find where (what I am guessing) my typo is, but for the life of me I can't figure out why this is now not working.
The list that is not updating correctly is TrackOlv. To see the error in action simply browse to a source dir that contains .mp3 files and then select a destination dir. You will see the display update with blank lines instead of line of data.
#Boa:Frame:Frame1
import wx
import os
import glob
import shutil
import datetime
from mutagen.mp3 import MP3
from mutagen.easyid3 import EasyID3
import mutagen.id3
import unicodedata
from ObjectListView import ObjectListView, ColumnDefn
########################################################################
class Track(object):
def __init__(self, title, artist, album, source, dest):
"""
Model of the Track Object
Contains the followign attributes:
'Title', 'Artist', 'Album', 'Source', 'Dest'
"""
self.atrTitle = title
self.atrArtist = artist
self.atrAlbum = album
self.atrSource = source
self.atrDest = dest
class Action(object):
def __init__(self, timestamp, action, result):
self.timestamp = timestamp
self.action = action
self.result = result
########################################################################
# Non GUI
########################################################################
def selectFolder(sMessage):
print "Select Folder"
dlg = wx.DirDialog(None, message = sMessage)
if dlg.ShowModal() == wx.ID_OK:
# User has selected something, get the path, set the window's title to the path
filename = dlg.GetPath()
else:
filename = "None Selected"
dlg.Destroy()
return filename
def getList(SourceDir):
print "getList"
listOfFiles = None
print "-list set to none"
listOfFiles = glob.glob(SourceDir + '/*.mp3')
return listOfFiles
def getListRecursive(SourceDir):
print "getListRecursive"
listOfFiles = None
listOfFiles = []
print "-list set to none"
for root, dirs, files in os.walk(SourceDir):
for file in files:
if file.endswith(".mp3"):
listOfFiles.append(os.path.join(root,file))
#print listOfFiles
return listOfFiles
def strip_accents(s):
print "strip_accents"
return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
def replace_all(text):
print "replace_all " + text
dictionary = {'\\':"", '?':"", '/':"", '...':"", ':':"", '&':"and"}
print "-- repl_orig: " + text
print "-- repl_decode: " + text.decode('utf-8')
text = strip_accents(text.decode('utf-8'))
for i, j in dictionary.iteritems():
text = text.replace(i,j)
return text
def getTitle(fileName):
print "getTitle"
audio = MP3(fileName)
try:
sTitle = str(audio["TIT2"])
except KeyError:
sTitle = os.path.basename(fileName)
frame.lvActions.Append([datetime.datetime.now(),fileName,"Title tag does not exist, set to filename"])
# TODO: Offer to set title to filename
## If fileName != filename then
## prompt user for action
## Offer Y/n/a
sTitle = replace_all(sTitle)
return sTitle
def getArtist(fileName):
print "get artist"
audio = MP3(fileName)
try:
sArtist = str(audio["TPE1"])
except KeyError:
sArtist = "unkown"
frame.lvActions.Append([datetime.datetime.now(),fileName,"Artist tag does not exist, set to unkown"])
#Replace all special chars that cause dir path errors
sArtist = replace_all(sArtist)
#if name = 'The Beatles' change to 'Beatles, The'
if sArtist.lower().find('the') == 0:
sArtist = sArtist.replace('the ',"")
sArtist = sArtist.replace('The ',"")
sArtist = sArtist + ", The"
return sArtist
def getAblum(fileName):
print "get album"
audio = MP3(fileName)
try:
sAlbum = str(audio["TALB"])
except KeyError:
sAlbum = "unkown"
frame.lvActions.Append([datetime.datetime.now(),fileName,"Album tag does not exist, set to unkown"])
#Replace all special chars that cause dir path error
sAlbum = replace_all(sAlbum)
return sAlbum
########################################################################
# GUI
########################################################################
class MainPanel(wx.Panel):
#----------------------------------------------------------------------
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
#Create Track Object List
self.TrackOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
self.TrackOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK
self.setTracks()
#Create Actions Objet List
self.ActionsOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
self.setActions()
# create browse to source button
sourceBtn = wx.Button(self, wx.ID_ANY, "Browse Source")
sourceBtn.Bind(wx.EVT_BUTTON, self.onBrowseSource)
# create source txt box
self.txSource = wx.TextCtrl(self, wx.ID_ANY, name=u'txSource', value=u'')
# create browse dest button
destBtn = wx.Button(self, wx.ID_ANY, "Browse Destination")
destBtn.Bind(wx.EVT_BUTTON, self.onBrowseDest)
# create dest txt box
self.txDest = wx.TextCtrl(self, wx.ID_ANY, name=u'txDest', value=u'')
# create Move Files button
moveBtn = wx.Button(self, wx.ID_ANY, "Move Files")
moveBtn.Bind(wx.EVT_BUTTON, self.onMoveFiles)
# print list button - debug only
printBtn = wx.Button(self, wx.ID_ANY, "Print List")
printBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn)
# create check box to include all sub files
self.cbSubfolders = wx.CheckBox(self, wx.ID_ANY,
label=u'Include Subfolders', name=u'cbSubfolders', style=0)
self.cbSubfolders.SetValue(True)
self.cbSubfolders.Bind(wx.EVT_CHECKBOX, self.OnCbSubfoldersCheckbox)
# create check box to repace file names
self.cbReplaceFilename = wx.CheckBox(self, wx.ID_ANY,
label=u'Replace Filename with Title Tag',
name=u'cbReplaceFilename', style=0)
self.cbReplaceFilename.SetValue(False)
self.cbReplaceFilename.Bind(wx.EVT_CHECKBOX, self.OnCbReplaceFilenameCheckbox)
# Create some sizers
mainSizer = wx.BoxSizer(wx.VERTICAL)
feedbackSizer = wx.BoxSizer(wx.VERTICAL)
sourceSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
feedbackSizer.Add(self.TrackOlv, 1, wx.ALL|wx.EXPAND, 2)
feedbackSizer.Add(self.ActionsOlv, 1, wx.ALL|wx.EXPAND, 2)
sourceSizer.Add(sourceBtn, 0, wx.ALL, 2)
sourceSizer.Add(self.txSource, 1, wx.ALL|wx.EXPAND, 2)
sourceSizer.Add(destBtn, 0, wx.ALL, 2)
sourceSizer.Add(self.txDest, 1, wx.ALL|wx.EXPAND, 2)
btnSizer.Add(printBtn)
btnSizer.Add(moveBtn, 0, wx.ALL, 2)
btnSizer.Add(self.cbSubfolders, 0, wx.ALL, 2)
btnSizer.Add(self.cbReplaceFilename, 0, wx.ALL, 2)
mainSizer.Add(feedbackSizer, 1 , wx.ALL|wx.EXPAND, 2)
mainSizer.Add(sourceSizer, 0, wx.ALL|wx.EXPAND, 2)
#mainSizer.Add(destSizer, 0, wx.ALL|wx.EXPAND, 2)
#mainSizer.Add(destSizer, 0, wx.All|wx.Expand, 2)
mainSizer.Add(btnSizer, 0, wx.ALL, 2)
self.SetSizer(mainSizer)
mainSizer.Fit(self)
#----------------------------------------------------------------------
# Set the GUI column headers and width
#----------------------------------------------------------------------
def setTracks(self, data=None):
self.TrackOlv.SetColumns([
ColumnDefn("Title", "left", 100, "title"),
ColumnDefn("Artist", "left", 100, "artist"),
ColumnDefn("Album", "left", 100, "album"),
ColumnDefn("Source", "left", 300, "source"),
ColumnDefn("Destination", "left", 300, "dest"),
])
def setActions(self, data=None):
self.ActionsOlv.SetColumns([
ColumnDefn("Time", "left", 100, "timestamp"),
ColumnDefn("Action", "left", 450, "action"),
ColumnDefn("Result", "left", 450, "result")
])
#----------------------------------------------------------------------
# GUI EVENTS
#-----------------------------------------------------------------------
#Select Source of files
def onBrowseSource(self, event):
print "OnBrowseSource"
source = selectFolder("Select the Source Directory")
print "--source :" + source
self.txSource.SetValue(source)
self.anEvent = Action(datetime.datetime.now(),source,"Set as Source dir")
self.ActionsOlv.AddObject(self.anEvent)
self.populateList()
#Select Source of files
def onBrowseDest(self, event):
print "OnBrowseDest"
dest = selectFolder("Select the Destination Directory")
print dest
self.txDest.SetValue(dest)
self.anEvent = Action(datetime.datetime.now(),dest,"Set as Destination dir")
self.ActionsOlv.AddObject(self.anEvent)
self.populateList()
def OnCbSubfoldersCheckbox(self, event):
print "cbSubfolder"
self.populateList()
def OnCbReplaceFilenameCheckbox(self, event):
print "cbReplaceFilename"
self.populateList()
def onMoveFiles(self, event):
print "onMoveFiles"
self.moveFiles()
def onPrintBtn(self, event):
print "onPrintBtn"
#Why does this work
#rowObj = self.dataOlv.GetSelectedObject()
#print rowObj.author
#print rowObj.title
#debug - how many item in the list... why does it only print 1?
itemcount = self.TrackOlv.GetItemCount()
print "-- itemcount: " + str(itemcount)
getData = self.TrackOlv.GetItemData(1)
print "-- getData: " + str(getData)
trackList = self.TrackOlv.GetObjects()
for tracks in trackList:
print tracks.atrTitle, tracks.atrArtist, tracks.atrAlbum, tracks.atrSource, tracks.atrDest
#-------------
#Computations
#-------------
def defineDestFilename(self, sFullDestPath):
print "define dest"
iCopyX = 0
bExists = False
sOrigName = sFullDestPath
#If the file does not exist return original path/filename
if os.path.isfile(sFullDestPath) == False:
print "-" + sFullDestPath + " is valid"
return sFullDestPath
#Add .copyX.mp3 to the end of the file and retest until a new filename is found
while bExists == False:
sFullDestPath = sOrigName
iCopyX += 1
sFullDestPath = sFullDestPath + ".copy" + str(iCopyX) + ".mp3"
if os.path.isfile(sFullDestPath) == False:
print "-" + sFullDestPath + " is valid"
self.lvActions.Append([datetime.datetime.now(),"Desitnation filename changed since file exists",sFullDestPath])
bExists = True
#return path/filename.copyX.mp3
return sFullDestPath
def populateList(self):
print "populateList"
sSource = self.txSource.Value
sDest = self.txDest.Value
#Initalize list to reset all values on any option change
itemcount = self.TrackOlv.GetItemCount()
print "-- itemcount: " + str(itemcount)
if itemcount > 0:
self.TrackOlv.DeleteAllItems()
print "--list cleaned"
#Create list of files
if self.cbSubfolders.Value == True:
listOfFiles = getListRecursive(sSource)
else:
listOfFiles = getList(sSource)
print listOfFiles
#prompt if no files detected
if listOfFiles == []:
self.anEvent = Action(datetime.datetime.now(),"Parse Source for .MP3 files","No .MP3 files in source directory")
self.ActionsOlv.AddObject(self.anEvent)
#Populate list after both Source and Dest are chosen
if len(sDest) > 1 and len(sDest) > 1:
print "-iterate listOfFiles"
for file in listOfFiles:
#gest Source and Filename
(sSource,sFilename) = os.path.split(file)
print "-- source: " + sSource
print "-- filename: " + sFilename
#sFilename = os.path.basename(file)
sTitle = getTitle(file)
print "-- title: " + sTitle
#Get artist
try:
sArtist = getArtist(file)
except UnicodeDecodeError:
print "unicode"
sArtist = "unkown"
print "-- artist: " + sArtist
#Get Album
sAlbum = getAblum(file)
print "-- album: " + sAlbum
# Make dest path = sDest + Artist + Album
sDestDir = os.path.join (sDest, sArtist)
sDestDir = os.path.join (sDestDir, sAlbum)
#If file exists change destination to *.copyX.mp3
if self.cbReplaceFilename.Value == True:
sDestDir = self.defineDestFilename(os.path.join(sDestDir,sTitle))
else:
sDestDir = self.defineDestFilename(os.path.join(sDestDir,sFilename))
print "-- dest: " + sDestDir
# Populate listview with track info
self.aTrack = Track(sTitle,sArtist,sAlbum,sSource,sDestDir)
self.TrackOlv.AddObject(Track(sTitle,sArtist,sAlbum,sSource,sDestDir))
self.Update()
print "** ITEM ADDED **"
else:
print "-list not iterated"
def moveFiles (self):
print "move files"
#for track in self.TrackOlv:
# print "-iterate SourceDest"
# #create dir
# (sDest,filename) = os.path.split(self.TrackOlv)
# print "-check dest"
#
# if not os.path.exists(sDest):
# print "-Created dest"
# os.makedirs(sDest)
# self.lvActions.Append([datetime.datetime.now(),sDest,"Created"])
# self.Update()
# self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1)
#
# #Move File
# print "-move file"
# shutil.move(SourceDest[0],SourceDest[1])
# self.lvActions.Append([datetime.datetime.now(),filename,"Moved"])
# self.Update()
# self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1)
#
#self.lvActions.Append([datetime.datetime.now(),"Move Complete","Success"])
#self.Update()
#self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1)
########################################################################
class MainFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, parent=None, id=wx.ID_ANY,
title="MP3 Manager", size=(1024,768)) #W by H
panel = MainPanel(self)
########################################################################
class GenApp(wx.App):
#----------------------------------------------------------------------
def __init__(self, redirect=False, filename=None):
wx.App.__init__(self, redirect, filename)
#----------------------------------------------------------------------
def OnInit(self):
# create frame here
frame = MainFrame()
frame.Show()
return True
#----------------------------------------------------------------------
def main():
"""
Run the demo
"""
app = GenApp()
app.MainLoop()
if __name__ == "__main__":
main()
The problem is that the 4th argument in the ColumnDefn in your setTracks method don't match the Track object's attribute names. If they don't match exactly, then it won't map correctly and nothing will be shown in the widget.
So, change "title" to "atrTitle", etc in the setTracks method or do the reverse in the Track object.
This is one of the few got'chas I've had with ObjectListView.

Categories

Resources