I want to show all data from my SQL Database in a TableWidget
if i enter print(row) and change the cursor in the for loop to mycursor.fetchall() it shows the values in the consoles. but tablewidget stays empty
Error in console: TypeError: 'NoneType' object is not iterable
Is there a way to use a Model based QTableView like in an offline Db
self.tbl_mitarbeiter.setColumnWidth(0,100)
self.tbl_mitarbeiter.setColumnWidth(1,100)
self.tbl_mitarbeiter.setColumnWidth(2,100)
self.tbl_mitarbeiter.setColumnWidth(3,100)
self.tbl_mitarbeiter.setColumnWidth(4,100)
self.tbl_mitarbeiter.setColumnWidth(5,100)
self.tbl_mitarbeiter.setColumnWidth(6,100)
tbl_mitarbeiter_header = ["Personalnummer","Name", "Abteilungsid", "Kontakt", "Eintrittsdatum", "Austrittsdarum", "Notizen"]
self.tbl_mitarbeiter.setHorizontalHeaderLabels(tbl_mitarbeiter_header)
self.load_data()
def load_data(self):
sql = 'SELECT * FROM mitarbeiter LIMIT 50'
# mycursor.execute(sql)
self.tbl_mitarbeiter.setRowCount(50)
tablerow = 0
for row in mycursor.execute(sql):
print(row)
self.tbl_mitarbeiter.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 1, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 4, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 5, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 6, QtWidgets.QTableWidgetItem(row[0]))
tablerow+=1
Model Based but also returns empty values
#TableModel
self.mod_mitarbeiter = QtSql.QSqlRelationalTableModel()
self.mod_mitarbeiter.setTable("mitarbeiter")
self.mod_mitarbeiter.setRelation(2,QtSql.QSqlRelation("abteilungen","Abteilungsid", "Abteilung"))
self.tbl_mitarbeiter.setItemDelegate(QtSql.QSqlRelationalDelegate())
self.db_refresh()
def db_refresh(self):
model = self.mod_mitarbeiter
abfrage = """UPDATE mitarbeiter"""
query.exec(abfrage)
model.select()
self.tbl_mitarbeiter.setModel(model)
Related
I have a table that's being populated from a database. you can edit the table then update the database with the new data. I have this:
def populate(self):
tablerow = 0
rowcount = 0
self.ui.widget_unass_fights.clearContents()
self.ui.widget_unass_fights.setRowCount(0)
for row in x:
rowcount += 1
self.ui.widget_unass_fights.setRowCount(rowcount)
self.ui.widget_unass_fights.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(str(row[0])))
self.ui.widget_unass_fights.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(str(row[2])))
self.ui.widget_unass_fights.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(str(row[3])))
self.ui.widget_unass_fights.setItem(tablerow, 4, QtWidgets.QTableWidgetItem(str(row[4])))
self.ui.widget_unass_fights.setItem(tablerow, 5, QtWidgets.QTableWidgetItem(str(row[5])))
self.ui.widget_unass_fights.setItem(tablerow, 8, QtWidgets.QTableWidgetItem(str(row[8])))
combobox1 = QComboBox()
combobox1.clear()
for j in self.plane_list_combo:
self.ui.widget_unass_fights.setItem(tablerow, 1, QtWidgets.QTableWidgetItem(""))
combobox1.addItem(j)
self.ui.widget_unass_fights.setCellWidget(tablerow, 1, combobox1)
self.ui.widget_unass_fights.cellWidget(tablerow, 1).setCurrentText(row[1])
combobox2 = QComboBox()
combobox2.clear()
combobox2.addItem("")
combobox3 = QComboBox()
combobox3.clear()
combobox3.addItem("")
for j in self.pilot_list_combo:
self.ui.widget_unass_fights.setItem(tablerow, 6, QtWidgets.QTableWidgetItem(""))
self.ui.widget_unass_fights.setItem(tablerow, 7, QtWidgets.QTableWidgetItem(""))
combobox2.addItem(j)
combobox3.addItem(j)
self.ui.widget_unass_fights.setCellWidget(tablerow, 6, combobox2)
self.ui.widget_unass_fights.setCellWidget(tablerow, 7, combobox3)
self.ui.widget_unass_fights.cellWidget(tablerow, 6).setCurrentText(row[6])
self.ui.widget_unass_fights.cellWidget(tablerow, 7).setCurrentText(row[7])
tablerow += 1
print(self.ui.widget_unass_fights.cellWidget(0, 1).currentText())
def update(self)
rowcount = self.ui.widget_unass_fights.rowCount()
print(self.ui.widget_unass_fights.cellWidget(0, 1).currentText())
for i in range(rowcount):
flight_id = self.ui.widget_unass_fights.item(i, 0).text()
flight_reg = self.ui.widget_unass_fights.cellWidget(i, 1).currentText()
desc = self.ui.widget_unass_fights.item(i, 2).text()
date = self.ui.widget_unass_fights.item(i, 3).text()
etd = self.ui.widget_unass_fights.item(i, 4).text()
flight_time = self.ui.widget_unass_fights.item(i, 5).text()
pilot = self.ui.widget_unass_fights.cellWidget(i, 6).currentText()
co_pilot = self.ui.widget_unass_fights.cellWidget(i, 7).currentText()
max_pax = self.ui.widget_unass_fights.item(i, 8).text()
columns 1, 6, and 7 are combo boxes
When I tried running the update function I got the error:
self.ui.widget_unass_fights.cellWidget(i, 1).currentText()
AttributeError: 'QWidget' object has no attribute 'currentText'
so I put in the 2 print commands to try to find out why. the print command in the populate function works, but the print command in the update function doesn't, they are copy and paste of each other, they should both work right? what am I doing wrong?
EDIT - after fiddling around I found that It will only let me call the last row of the table, none of the others.
I'm trying to retrieve the id of the last entry to a data base. id.fetchall() gives [(1,), (2,), (3,), (4,), (5,), (6,), (7,)] but len(id.fetchall() comes as 0 and when I try to do id.fetchall[-1] it says index is out of range. My code is as follows:
self.curs = self.conn.cursor()
id = self.curs.execute('''SELECT id FROM Addresses''')
entry = str(id.fetchall()[-1][0]) + str(firstname) + ' ' + str(lastname)
menu = self.addedrecord['menu']
menu.add_command(label = entry, command = lambda value = entry: self.selectedrecord.set(value))
self.statuslabel.grid_forget()
self.statuslabel.config(text = 'Record Loaded')
self.statuslabel.grid(row = 20, column = 1, columnspan = 2)
self.conn.commit()
self.conn.close()
I have a GUI where results from a dataframe are populated into a treeview within python based on filters previously input. The user can then click on treeview and update the values to the desired number. The number of rows within the view can vary from 1 - 20+. Once the user has updated the view as desired, I have a button below "Check Allocation".
It is at this point I want to "export" the treeview into a dataframe for me to run against another table. I cant seem to simply export this as a dataframe. Is there any work around this? I only need the first and last columns (of the 8) to check the newly updated file.
Here is what I have so far.
def PrintAllocation(self):
treeview = tkk.Treeview(root)
treeview.grid(column = 1, row = 8, columnspan = 4, padx = 1, pady = 1)
cols = list(matches.columns)
treeview["columns"] = cols
for i in cols:
treeview.column(i, width = 100, anchor = "w")
treeview.heading(i,text=i,anchor='w',)
for index, row in matches.iterrows():
treeview.insert("",0,text=index,values=list(row))
def set_cell_value(event): # Double click to enter the edit state
for item in treeview.selection():
#item = I001
item_text = treeview.item(item, "values")
#print(item_text[0:2]) # Output the value of the selected row
column= treeview.identify_column(event.x)# column
print(column)
row = treeview.identify_row(event.y) #row
cn = int(str(column).replace('#',''))
rn = int(str(row).replace('I',''))
if column == '#8':
entryedit = Text(root,width=50,height = 1)
entryedit.grid(column = 2, row = 9, padx = 1, pady = 1)
else:
entryedit = Text(root,width=10,height = 1)
entryedit.grid(column = 2, row = 9, padx = 1, pady = 1)
def saveedit():
treeview.set(item, column=column, value=entryedit.get(0.0, "end"))
entryedit.destroy()
okb.destroy()
okb = ttk.Button(root, text='OK', width=4, command=saveedit)
okb.grid(column = 3, row = 9,padx = 1, pady=1)
def CheckAllocation():
children = treeview.getchildren()
for child in children:
print(treeview.set(child))
treeview.bind('<Double-1>', set_cell_value) # Double-click the left button to enter the edit
button_check = Button(root,text="Check Allocation", command = CheckAllocation)
button_check.grid(column = 2, row = 10, padx = 10, pady=10)
'''
I don't really understand your code but when I need to get a treeview to pandas I do it as follows:
First I create an empty list for each column in the treeview.
column_a_list = []
column_b_list = []
column_c_list = []
column_d_list = []
Then running through the lines of the treeview in a "for" function, I append to each column list the value of the column in each line.
for child in self.treeview.get_children():
column_a_list.append(self.treeview.item(child)["values"][0])
column_b_list.append(self.treeview.item(child)["values"][1])
column_c_list.append(self.treeview.item(child)["values"][2])
column_d_list.append(self.treeview.item(child)["values"][3])
Then I create a dictionary from all the lists, using the header as the key and lists are the values as a list.
full_treeview_data_dict = {'HEADER A': column_a_list, 'HEADER B': column_b_list, 'HEADER C': column_c_list, 'HEADER D': column_d_list,}
Then I create a dataframe from the dictionary.
treeview_df = pd.DataFrame.from_dict(full_treeview_data_dict)
Here is the full sample code in one chunk:
column_a_list = []
column_b_list = []
column_c_list = []
column_d_list = []
for child in self.treeview.get_children():
column_a_list.append(self.treeview.item(child)["values"][0])
column_b_list.append(self.treeview.item(child)["values"][1])
column_c_list.append(self.treeview.item(child)["values"][2])
column_d_list.append(self.treeview.item(child)["values"][3])
full_treeview_data_dict = {'HEADER A': column_a_list, 'HEADER B': column_b_list, 'HEADER C': column_c_list, 'HEADER D': column_d_list,}
treeview_df = pd.DataFrame.from_dict(full_treeview_data_dict)
I hope it helps.
You can also do this:
row_list = []
columns = ('name', 'school', 'c3', 'c4')
for row in treeview.get_children():
row_list.append(treeview.item(row)["values"])
treeview_df = pd.DataFrame(row_list, columns = columns)
The current answer is good, I just wanted to add my two cents here:
self.treeview_columns = [] # list of names here
# initialize empty df
# if too big you can preallocate but probably not needed
treeview_df = pd.DataFrame(None, columns=self.treeview_columns)
for row in self.treeview.get_children():
# each row will come as a list under name "values"
values = pd.DataFrame([self.treeview.item(row)["values"]],
columns=self.treeview_columns)
# print(values)
treeview_df = treeview_df.append(values)
This way you grow your df row by row using append and you reduce the number of subsets that you need to do.
Problem Statement:
Disable specific columns and enable specific row on bases of current row index.
I am working on Qtablewidget i tried following code this working fine for disable.
i wanted to enable tablewidget row contents on bases of row index .
when i clicked pushbutton that row should be enable.I am new to the stackoverflow please guide me.I am tring to enable tablewidget cell,pushbutton,combobox i am not getting please guide me how to enble particular row on bases of index.
Code :
self.tableWidget = QtGui.QTableWidget(self.centralwidget)
self.tableWidget.setColumnCount(4)
myresult = [(u'sandeep', u'checkbox'), (u'shivaraj', u'checkbox')]
for row, result in enumerate(myresult):
self.tableWidget.insertRow(self.tableWidget.rowCount())
for column, value in enumerate(result):
item = QtGui.QTableWidgetItem(str(value))
if column == 1:
if (value == "textbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(1)
self.tableWidget.setCellWidget(row, column, self.cb)
self.cb.setEnabled(False)#this is for combobox disable
elif (value == "checkbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(2)
self.tableWidget.setCellWidget(row, column, self.cb)
self.cb.setEnabled(False)#this is for combobox disable
self.tableWidget.setItem(row, column, item)
item.setFlags(QtCore.Qt.ItemIsEnabled)#this is for text non editable
self.btn_sell = QtGui.QPushButton('Edit')
self.btn_sell1 = QtGui.QPushButton('Delete')
self.btn_sell1.setEnabled(False)#this for button disble
self.tableWidget.setCellWidget(row, 2, self.btn_sell)
self.tableWidget.setCellWidget(row, 3, self.btn_sell1)
self.btn_sell.clicked.connect(self.edit)
def edit(self):
index = self.tableWidget.currentRow()
print index
self.table = QtGui.QTableWidget()
self.table.setGeometry(QtCore.QRect(220, 100, 881, 100))
self.table.setColumnCount(4)
self.table.setRowCount(1)
self.table.setColumnWidth(0, 120)
self.table.setColumnWidth(1, 500)
self.table.setColumnWidth(2, 120)
self.table.setColumnWidth(3, 120)
indexes = self.tableWidget.currentRow()
widget = self.tableWidget.cellWidget(indexes, 2)
# print widget
if isinstance(widget, QtGui.QComboBox):
h = str(widget.currentText())
if (h == "multiple_input"):
j = "checkbox"
elif (h == "description"):
j = "textbox"
if (j == "textbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(1)
self.table.setCellWidget(0, 2, self.cb)
[enter image description here][1]elif (j == "checkbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(2)
self.table.setCellWidget(0, 2, self.cb)
n = [str(self.tableWidget.item(indexes, 0).text())]
for x in n:
f = ''.join(map(str, x))
self.table.setItem(0, 0, QtGui.QTableWidgetItem(f))
n1 = [str(self.tableWidget.item(indexes, 1).text())]
# print n1
for i in n1:
s = ''.join(i)
self.table.setItem(0, 1, QtGui.QTableWidgetItem(s))
self.li = QtGui.QPushButton("Update")
self.table.setCellWidget(0, 3, self.li)
self.li.clicked.connect(self.edit_data)
self.table.show()
click on below link has image.
Try the above code:
Select row and click on edit button it will take the current index row values into the separate table `where we can edit and update the values.This is the one way i have tried to update the value it works fine.
I have a system of editing data when the data is just text. I have added a combobox, and I want the data from that to be editable too. When the combobox is changed, and the edit button is clicked, I want the data to update in the database. How do I do that?
Here is the code for one of my outputted queries.
def click_btn_lessons(self):
self.screen_name = "lessons"
self.page_constants()
self.cur.execute("SELECT StudentID FROM StudentProfile")
students_students = self.cur.fetchall()
self.cur.execute("SELECT StudentID FROM Lessons")
students_lessons = self.cur.fetchall()
self.cur.execute("""SELECT s.studentID, s.FullName, l.LessonDate, r.RoadExerciseName, e.Rating
FROM StudentProfile s
LEFT JOIN Lessons l ON s.StudentID=l.StudentID
LEFT JOIN LessonExercises e ON l.LessonID=e.LessonID
LEFT JOIN RoadExerciseInfo r ON r.RoadExerciseID=e.RoadExerciseID
""")
self.all_data = self.cur.fetchall()
"""This section just removes black records"""
for student in students_students:
if student not in students_lessons:
for item in self.all_data:
if item[0] == student[0]:
self.all_data.remove(item)
self.table.setRowCount(len(self.all_data))
self.tableFields = ['check','Full name','Lesson date', 'Exercise', "Rating"]
self.table.setColumnCount(len(self.tableFields))
self.table.setHorizontalHeaderLabels(self.tableFields)
self.checkbox_list = []
for i, item in enumerate(self.all_data):
FullName = QtGui.QTableWidgetItem(str(item[1]))
LessonDate = QtGui.QTableWidgetItem(str(item[2]))
RoadExerciseName = QtGui.QTableWidgetItem(str(item[3]))
#This is the combobox and its items
Rating = QtGui.QComboBox()
for num in range(5):
Rating.addItem(str(num))
self.table.setItem(i, 1, FullName)
self.table.setItem(i, 2, LessonDate)
self.table.setItem(i, 3, RoadExerciseName)
#here is how the combobox isadded to the table
self.table.setCellWidget(i, 4, Rating)
#the checkbox items have to be ticked for them to be passed to the edit function
chkBoxItem = QtGui.QTableWidgetItem()
chkBoxItem.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
chkBoxItem.setCheckState(QtCore.Qt.Unchecked)
self.checkbox_list.append(chkBoxItem)
self.table.setItem(i, 0, self.checkbox_list[i])
FullName.setFlags(FullName.flags() & ~Qt.ItemIsEditable)
RoadExerciseName.setFlags(RoadExerciseName.flags() & ~Qt.ItemIsEditable)
self.name = None
self.changed_items = []
self.table.itemChanged.connect(self.log_change)
def log_change(self, item):
self.table.blockSignals(True)
item.setBackgroundColor(QtGui.QColor("red"))
self.table.blockSignals(False)
self.changed_items.append(item)
def click_btn_edit(self):
print("Updating")
for item in self.changed_items:
self.table.blockSignals(True)
item.setBackgroundColor(QtGui.QColor("white"))
self.table.blockSignals(False)
text, col, row = item.text(), item.column(), item.row()
new_data = self.all_data
for i, record in enumerate(self.all_data):
if i == row:
if self.checkbox_list[i].checkState() == QtCore.Qt.Checked:
#Below adds the new data to the database.
self.cur.execute("""UPDATE {0} SET {1} = ? WHERE {2} = ?""".format(self.table_edit_name,self.columnList[col],self.field_ID),(text,record[0],))
"""self.field_ID is the field name for the primary key, record[0]. This ensures data is entered in the correct record.
columnList is a list of columns in the record, in order.
self.table_edit_name is the name of the table involved."""