How can I print my data from my database (sqlite) into a notepad /word document from my table in my GUI (using the same formatting). Here is my code for the table which is represented on my gui.
class Table(QtGui.QDialog):
def __init__(self):
super(Table, self).__init__()
with sqlite3.connect('database.db') as db:
cursor=db.cursor()
cursor.execute('select* from Receipt Order BY ReceiptID ASC')
title = [cn[0] for cn in cursor.description]
rows = [cn[0] for cn in cursor.description]
cur=cursor.fetchall()
layout = QtGui.QGridLayout()
self.table = QtGui.QTableWidget()
self.setGeometry(500,500,500,400)
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
self.label2=QtGui.QLabel(self)
self.label2.setPixmap(QtGui.QPixmap('receipt_pic.jpg'))
self.label2.setGeometry(0,0,500,400)
self.table.setColumnCount(2)
self.table.setHorizontalHeaderLabels(title)
for i,row in enumerate(cur):
self.table.insertRow(self.table.rowCount())
for j,val in enumerate(row):
self.table.setItem(i, j, QtGui.QTableWidgetItem(str(val)))
layout.addWidget(self.table, 0, 0)
self.setLayout(layout)
self.setWindowTitle('Receipt Table')
I want to be able to click a button which copies this information (which would appear as a table with filled columns and rows) into a seperate notepad file / or any text document (where I can send the table to the printer to be printed).
It would probably be easier to just print the table directly, rather than use an intermediary file.
To do this, you can use a QTextDocument to create a printable representation of the table, and then use the built-in print dialogs to do the rest.
So, first add some buttons:
...
layout.addWidget(self.table, 0, 0, 1, 2)
self.buttonPrint = QtGui.QPushButton('Print', self)
self.buttonPrint.clicked.connect(self.handlePrint)
self.buttonPreview = QtGui.QPushButton('Preview', self)
self.buttonPreview.clicked.connect(self.handlePreview)
layout.addWidget(self.buttonPrint, 1, 0)
layout.addWidget(self.buttonPreview, 1, 1)
self.setLayout(layout)
...
then some handlers for the print and print-preview dialogs:
def handlePrint(self):
dialog = QtGui.QPrintDialog()
if dialog.exec_() == QtGui.QDialog.Accepted:
self.handlePaintRequest(dialog.printer())
def handlePreview(self):
dialog = QtGui.QPrintPreviewDialog()
dialog.paintRequested.connect(self.handlePaintRequest)
dialog.exec_()
and finally some methods for creating the document and printing it:
def handlePaintRequest(self, printer):
document = self.makeTableDocument()
document.print_(printer)
def makeTableDocument(self):
document = QtGui.QTextDocument()
cursor = QtGui.QTextCursor(document)
rows = self.table.rowCount()
columns = self.table.columnCount()
table = cursor.insertTable(rows + 1, columns)
format = table.format()
format.setHeaderRowCount(1)
table.setFormat(format)
format = cursor.blockCharFormat()
format.setFontWeight(QtGui.QFont.Bold)
for column in range(columns):
cursor.setCharFormat(format)
cursor.insertText(
self.table.horizontalHeaderItem(column).text())
cursor.movePosition(QtGui.QTextCursor.NextCell)
for row in range(rows):
for column in range(columns):
cursor.insertText(
self.table.item(row, column).text())
cursor.movePosition(QtGui.QTextCursor.NextCell)
return document
If you prefer to save to a file, you can use QTextDocument.toHtml to dump the table as html.
The printed results are quite basic, but if you want something more fancy, you can always build the document using html/css.
I use this function
def LoadDatabase(self):
self.banco = sqlite3.connect ( 'Vendas.db' )
self.cursor = banco.cursor ( )
query = "SELECT * FROM Produtos"
result = self.banco.execute ( query )
self.listaprodutos.setRowCount ( 0 )
for row_number, row_data in enumerate ( result ):
self.listaprodutos.insertRow ( row_number )
for colum_number, data in enumerate ( row_data ):
self.listaprodutos.setItem ( row_number, colum_number, QtWidgets.QTableWidgetItem ( str ( data ) ) )
Related
I have a program that is "divided" in 6 classes, the first class is the Main Window where I can choose where I'd like to go (I have 4 choices, a page to visualize all the data, one to modify and the other 2 to visualize data with filters), each of theese pages is a QDialog that contains a QTableWidget, this table is connected to a SQL Server database and shows data from a specific table (to be honest it shows data from 2 tables).
My problem is:
In the 2 class ("modificaviaggi") I connected some signals to some action, first of all I connected the itemChanged signal to a method that stores the items written by the user and saves them in the SQL DB, the signal signal I used is the clicked signal, I connected this signal to a method that verifies if the cell clicked it's the 8 or 9, in case it's 8 or 9 it shows another QDialog (class "articoli") where the user can insert some data regarding weight of every product, this weight data are stored in a second table in the SQL Server DB, I use this table to get the weight for every product when I show my table.
So I get all the data from the table SQL "Viaggi" and then I verify if there are some values in the SQL table "Pesi" for each row of the table "Viaggi" using the row ID.
Now the complicated part is that when the user click the columns 8 or 9 it shows another Qdialog, I show this Qdialog everytime the user clicks the columns 8 or 9, then the user can write data on the table and those data will be stored in the table "Pesi", thanks to the variable "lastID" declared on the "modificaviggi" class I know for which row the user clicked the columns 8 or 9, thanks to that I store the values in the SQL table and for each value I have their row ID, now that the situation is more clear the real question is: How can "Re-load" the QTableWidget "tabella_registrazioni" inside the class "modificaviaggi" everytime the user clicks the QPushButton "get_back_button"? Because in the class "articoli" the user modifies/adds values for each row in the QTableWidget "tabella_registrazioni" but I can't reload the data inside here's my code :
c = conn.cursor()
d = conndue.cursor()
class Ui(QtWidgets.QMainWindow):
def __init__(self):
super(Ui, self).__init__() # chiamare le inherited classi con metodo __init__
uic.loadUi('pagina_scelta.ui', self) # caricare file.ui
self.show() # mostrarlo
bottonefinestramodifica = self.findChild(QtWidgets.QPushButton, 'bottone_modifica')
bottonefinestramodifica.clicked.connect(self.finestramodifica)
def finestramodifica(self):
self.finestramodifica = modificaviaggi()
self.finestramodifica.show()
class MyDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
return
class modificaviaggi(QtWidgets.QDialog):
lastid = [0]
recall = [2]
def finestraarticoli(self):
self.finestraarticoli = articoli()
self.finestraarticoli.show()
def chiusura(self):
self.accept()
def __init__(self):
super(modificaviaggi, self).__init__()
uic.loadUi('modifica_reg.ui', self)
bottonetorna = self.bottone_torna
bottonetorna.clicked.connect(self.chiusura)
self.reloading()
self.datitabella()
def reloading(self):
if 1 == 1:
if self.recall[0] == 1:
self.datitabella()
self.recall[0] == 2
def datitabella(self):
delegate = MyDelegate(self)
tablerow = 0
conteggio = c.execute('SELECT COUNT(ID) FROM Viaggi').fetchone()[0]
print(conteggio)
customers = [" "]
self.tabella_registrazioni.blockSignals(True)
self.customers_combo(customers)
self.tabella_registrazioni.setRowCount(conteggio)
for row in c.execute("SELECT * FROM Viaggi "):
rigavalore = 0
self.tabella_registrazioni.setRowCount(conteggio)
for r in range(0, 19):
self.tabella_registrazioni.setItem(tablerow, rigavalore, QtWidgets.QTableWidgetItem(str(row[rigavalore])))
rigavalore+= 1
tablerow+= 1
self.combocreation(customers)
self.combocreation(customers)
self.tabella_registrazioni.blockSignals(False)
self.tabella_registrazioni.itemChanged.connect(self.changeIcon)
self.tabella_registrazioni.setItemDelegateForColumn(0, delegate)
self.tabella_registrazioni.clicked.connect(self.pressed)
self.combo_customers.activated.connect(self.customer_combo_selection)
righe = self.tabella_registrazioni.rowCount()
tablerow1= 0
for i in range(0, righe):
idrow = self.tabella_registrazioni.item(i, 0).text()
netweight = c.execute("SELECT SUM(Peso_netto) FROM Pesi WHERE ID_registrazione = ?", idrow)
if netweight != None or not netweight.isspace():
netweight = float(str(netweight.fetchone()[0]))
else:
print("Nessun peso")
grossweight = c.execute("SELECT SUM(Peso_lordo) FROM Pesi WHERE ID_registrazione = ?", idrow)
if grossweight != None or not grossweight.isspace():
grossweight = float(str(grossweight.fetchone()[0]))
self.tabella_registrazioni.setItem(tablerow1, 8, QtWidgets.QTableWidgetItem(str(netweight)))
self.tabella_registrazioni.setItem(tablerow1, 9, QtWidgets.QTableWidgetItem(str(grossweight)))
tablerow1+= 1
def combocreation(self, customers):
self.combo_customers = QComboBox()
self.combo_customers.setEditable(True)
def customers_combo(self, customers):
for cu in d.execute("SELECT ANDESCRI FROM VALL_CONTI WHERE ANTIPCON = 'C' "):
customers.append(cu[0].strip())
def changeIcon(self, item):
row = item.row()
col = item.column()
zero = self.tabella_registrazioni.item(row, 0).text()
uno = self.tabella_registrazioni.item(row, 1).text()
custcode = self.tabella_registrazioni.item(row, 3).text()
custname = self.tabella_registrazioni.item(row, 4).text()
c.execute('UPDATE Viaggi SET Codice_cliente = ?, Ragione_sociale = ? WHERE ID = ?',
(custcode, custname, zero))
c.commit()
def pressed(self, item):
row = item.row()
col = item.column()
customers = [" "]
self.lastid[0] = self.tabella_registrazioni.item(row, 0).text()
if col == 8 or col == 9:
self.finestraarticoli()
self.customers_combo(customers)
self.combocreation(customers)
textcell = self.tabella_registrazioni.item(row, col).text()
self.combo_customers.setCurrentText(textcell)
self.combo_customers.activated.connect(self.customer_combo_selection)
if col == 3:
self.tabella_registrazioni.setCellWidget(row, 3, self.combo_customers)
def customer_combo_selection(self):
customer_name = self.combo_customers.currentText()
row = self.rrow
self.tabella_registrazioni.setItem(self.rrow, self.ccolumn, QtWidgets.QTableWidgetItem(str(customer_name)))
id = self.tabella_registrazioni.item(row, 0).text()
c.execute("UPDATE Viaggi SET Ragione_Sociale=? WHERE ID = ?", (customer_name, id))
c.commit()
class articoli(QtWidgets.QDialog):
def changevariable(self):
modificaviaggi.recall[0] = 1
self.accept()
def __init__(self):
super(articoli, self).__init__()
uic.loadUi('Inserimento_articoli.ui', self)
self.get_back_button.clicked.connect(self.changevariable)
self.tabellapesi()
def tabellapesi(self):
self.IDpressed = modificaviaggi.lastid
tablerow = 0
self.tabella_articoli.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
self.conteggio = int(str(c.execute("SELECT COUNT(ID_registrazione) FROM Pesi WHERE ID_registrazione = ? ", self.IDpressed[0]).fetchone()[0]))
for row in c.execute("SELECT * FROM Pesi WHERE ID_registrazione = ? ORDER BY ID ", self.IDpressed[0]):
rigavalore = 0
self.tabella_articoli.setRowCount(self.conteggio)
for r in range(0, 6):
self.tabella_articoli.setItem(tablerow, rigavalore, QtWidgets.QTableWidgetItem(str(row[rigavalore])))
rigavalore+= 1
tablerow+= 1
def insert(self):
rows = self.tabella_articoli.rowCount()
tablerow = 0
for row in range (0, rows):
articlecode = self.tabella_articoli.item(tablerow, 1).text()
articledesc = self.tabella_articoli.item(tablerow, 2).text()
netweight = float(self.tabella_articoli.item(tablerow, 3).text())
grossweight = float(self.tabella_articoli.item(tablerow, 4).text())
price = float(self.tabella_articoli.item(tablerow, 5).text())
if self.tabella_articoli.item(tablerow, 0) == None:
IDweight = ""
else:
IDweight = int(self.tabella_articoli.item(tablerow, 0).text())
queryinsert = "INSERT INTO Pesi ( Codice_articolo, Descrizione_articolo, Peso_netto, Peso_lordo, ID_registrazione, Prezzo) VALUES (?,?,?,?,?,?)"
values = [articlecode, articledesc, netweight, grossweight, self.IDpressed[0], price]
queryupdate = "UPDATE Pesi SET Peso_lordo = ?, Prezzo = ?, Peso_netto = ? , Codice_articolo = ?, Descrizione_articolo = ? WHERE ID = ? "
valuesupdate = [grossweight, price, netweight, articlecode, articledesc, IDweight]
exist = str(c.execute("IF EXISTS (SELECT * FROM CARICO_VIAGGI..Pesi WHERE ID = ?) BEGIN SELECT 1 END ELSE BEGIN SELECT 2 END", (IDweight)).fetchone()[0])
if exist == "1":
c.execute(queryupdate, valuesupdate)
c.commit()
print(type(IDweight))
elif exist == "2":
c.execute(queryinsert, values)
c.commit()
else:
print("Impossibile salvare gli articoli, riprovare")
tablerow+= 1
self.tabella_articoli.clearContents()
tablerow = 0
self.conteggiox = int(str(c.execute("SELECT COUNT(ID_registrazione) FROM Pesi WHERE ID_registrazione = ? ", self.IDpressed[0]).fetchone()[0]))
for row in c.execute("SELECT * FROM Pesi WHERE ID_registrazione = ? ORDER BY ID", self.IDpressed[0]):
rigavalore = 0
self.tabella_articoli.setRowCount(self.conteggiox)
for r in range(0, 6):
self.tabella_articoli.setItem(tablerow, rigavalore, QtWidgets.QTableWidgetItem(str(row[rigavalore])))
rigavalore+= 1
tablerow+= 1
app = QtWidgets.QApplication(sys.argv)
window = Ui()
app.exec_()
One solution could be to set up signals that would update the table as the user makes changes so there would be no need to refresh at all.
For example:
Set up a signal in your dialog class that will be emitted whenever the user changes the data. Then in the original dialog with the table you want to update, connect to that signal after initializing the dialog.
here is a minimal example:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
def populate_table(table):
for i in range(10):
table.insertRow(table.rowCount())
for j in range(2):
item = QTableWidgetItem(type=0)
item.setText(f"({i}, {j})")
table.setItem(i,j,item)
class Dialog2(QDialog):
tableInfoChanged = pyqtSignal([int, int, str])
def __init__(self,parent=None):
super().__init__(parent=parent)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.table = QTableWidget()
self.table.setColumnCount(2)
self.layout.addWidget(self.table)
populate_table(self.table)
self.table.cellChanged.connect(self.emitChangedInfo)
def emitChangedInfo(self, row, col):
text = self.table.item(row, col).text()
self.tableInfoChanged.emit(row, col, text)
class Dialog1(QDialog):
def __init__(self,parent=None):
super().__init__(parent=parent)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.table = QTableWidget()
self.table.setColumnCount(2)
self.button = QPushButton("Push to open dialog2")
self.layout.addWidget(self.table)
self.layout.addWidget(self.button)
populate_table(self.table)
self.button.clicked.connect(self.openDialog2)
def updateTable(self, row, col, text):
self.table.item(row,col).setText(text)
def openDialog2(self):
self.dialog2 = Dialog2()
self.dialog2.tableInfoChanged.connect(self.updateTable)
self.dialog2.exec()
app = QApplication(sys.argv)
window = Dialog1()
window.show()
sys.exit(app.exec_())
I have tested this code and should function as is.
Thanks all for your suggestions. Adding self. before calling my functions fixed that issue. I'm now running into a different issue where the stored procedure I am using isn't getting properly read into the pandas dataframe. I don't get any errors, the tkinter window pops up like it should, but when the PDF gets generated, there is no data in the rows, just the column names and other formatting I've written in.
I added print(df) to the code to check if it was an issue with the data getting read from the dataframe to the PDF, but print(df) just returns Empty DataFrame.
from tkinter import *
import pyodbc
import pandas as pd
from reportlab.lib import colors
from reportlab.platypus import *
from reportlab.lib import styles
from reportlab.lib.units import inch
# Create connection
server = 'XXXXXXX'
database = 'XXXXXXX'
username = 'XXXXXXXX'
password = 'XXXXXXXXX'
try:
cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+password+'')
except:
raise NameError('unable to connect')
#save stored procedure to a global variable
storedProc = 'EXEC [presentation].[pdf_project] '
elements = []
class NewPDF:
def __init__(self):
window = tk.Tk()
window.title("Form Example")
window = tk.Frame(window)
window.grid(column=0,row=0, sticky=(tk.N,tk.W,tk.E,tk.S))
window.columnconfigure(0, weight = 1)
window.rowconfigure(0, weight = 1)
window.pack(pady = 100, padx = 100)
self.tkvar = tk.StringVar(window)
choices = {'2021','2020','2019','2018'}
self.tkvar.set('2021')
popupMenu = tk.OptionMenu(window, self.tkvar, *choices)
tk.Label(window, text = "Pick Year").grid(row = 1, column = 1)
popupMenu.grid(row = 1, column = 2)
tk.Label(window, text = "Customer").grid(row = 2, column = 1)
self.e1 = tk.Entry(window)
self.e1.grid(row = 2, column = 2)
self.param_year = self.tkvar.get()
self.param_cust = str(self.e1.get())
B = tk.Button(window, text = "Make PDF", command=self.make_df_and_pdf()).grid(row = 3, column = 1)
self.tkvar.trace('w', self.change_dropdown())
window.mainloop()
def change_dropdown(self, *args):
print(args)
def make_df_and_pdf(self):
#param_year = self.tkvar.get()
#param_cust = str(self.e1.get())
params = "'" + self.param_cust + "'," + self.param_year + ""
querystring = storedProc + params
df = pd.read_sql_query(querystring, cnxn)
lista = [df.columns[:,].values.astype(str).tolist()] + df.values.tolist()
#cust_list = (df['CUSTOMER'].unique())
#cust_list = cust_list.tolist()
#print(df)
styles = getSampleStyleSheet()
ts = [('ALIGN', (1,1), (-1,1), 'LEFT'),
('BOX', (0,0), (3,0), 2, colors.red),
('FONT', (0,0), (-1,0), 'Times-Bold'),
('GRID', (0,1), (-1,-1), 0.5, colors.grey)]
n_table = Table(lista, colWidths = (1.5*inch, 1.5*inch, 1.5*inch, 1.5*inch, 1.5*inch), repeatRows = 1)
table_style = TableStyle(ts)
n_table.setStyle(table_style)
PATH_OUT = "Desktop"
doc = SimpleDocTemplate(PATH_OUT + 'UserInputPDF_Test.pdf')
elements.append(Paragraph("CustomerTAT", styles['Title']))
elements.append(n_table)
doc.build(elements)
NewPDF()
EDIT: The stored procedure operates as it should within SQL. Here is the code for my stored procedure:
USE [XXXXX]
GO
/****** Object: StoredProcedure [presentation].[pdf_project] Script Date: 6/22/2021 4:31:20 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: XXXXXX
-- Create date:
-- Description:
-- =============================================
ALTER PROCEDURE [presentation].[pdf_project]
-- Add the parameters for the stored procedure here
#CustomerName varchar(50) = '',
#Year int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT CUSTOMER, [TAT Whole Days], [SHIP DATE], YEAR([SHIP DATE]) AS YEAR,
CASE
WHEN MONTH([SHIP DATE]) IN (1,2,3) THEN 'Q1'
WHEN MONTH([SHIP DATE]) IN (4,5,6) THEN 'Q2'
WHEN MONTH([SHIP DATE]) IN (7,8,9) THEN 'Q3'
ELSE 'Q4'
END AS QUARTER
FROM presentation.CustomerTAT
WHERE (YEAR([SHIP DATE]) = #Year or YEAR([SHIP DATE]) = #Year)
AND CUSTOMER = #CustomerName
END
Below is my table :
In the above table, i have placed the Radiobutton at each row.
In the table, column 'field' has same values in the rows i.e startdate is present in two rows and validity is also repeating in rows.
What i want is to only select only one row consisting validity from the repeating values using radio button. if user selects another value,it must deselect previously selected value.
Below is my code:
class Window(QtGui.QWidget):
def __init__(self, data):
QtGui.QWidget.__init__(self)
self.data=data
rows=len(data)
data1=list()
for d in data:
#print d
#print "ddddddddddddddd",type(d)
d=d.replace('null','""')
d=eval(d)
#print type(d)
data1.append(d)
self.data1=data1
key_list=['file','field','content','refined_content','page_number']
data2=list()
for line in data1:
#print line
d = OrderedDict((k, line[k]) for k in key_list)
data2.append(d)
#print data2
data1=data2
#print data1
keys = ['file','field','content','refined_content','page_number']
keys=list(keys)
columns=len(keys)+1
keys.append("checkbox")
self.table = QtGui.QTableWidget(rows, columns, self)
self.table.setHorizontalHeaderLabels(keys)
self.keys=keys
#print "total columns",columns
#print "total rows",rows
#columns=str(columns)
for column in range(columns-1):
for row in range(rows):
qwidget = QtGui.QWidget()
checkbox = QtGui.QRadioButton()
checkbox.setChecked(False)
qhboxlayout = QtGui.QHBoxLayout(qwidget)
qhboxlayout.addWidget(checkbox)
qhboxlayout.setAlignment(Qt.AlignCenter)
qhboxlayout.setContentsMargins(0, 0, 0, 0)
dic=data1[row]
#print dic
index=int(column)
#print "index",index
value = dic.values()[index]
#print "current row",row
#print "current column",column
self.table.setItem(row, column, QtGui.QTableWidgetItem(str(value)))
#self.table.setItem(row, columns+1, QtGui.QTableWidgetItem(str(row)))
self.table.setCellWidget(row,columns-1 , qwidget)
layout = QtGui.QVBoxLayout(self)
self.button = QtGui.QPushButton()
self.button.setObjectName("loadButton")
self.button.setFixedWidth(100)
self.button.setFixedHeight(30)
self.button.setStyleSheet('color: white;background-color:rgb(0, 76, 153);border-style: outset;border-width: 2px;border-color: rgb(0, 76, 153);border-radius: 10px;alignment:left;')
self.button.setText("Submit")
layout.addWidget(self.table)
layout.addWidget(self.button)
self.button.clicked.connect(self.ButtonClicked)
def ButtonClicked(self,c):
c=self.table.columnCount()
#print "c",c
#print "keys",self.keys
checked_list = []
for i in range(self.table.rowCount()):
#checked_list = []
dic={}
if self.table.cellWidget(i, c-1).findChild(type(QtGui.QRadioButton())).isChecked():
for j in range(c-1):
st=str(self.table.item(i, j).text())
#print j,st
dic[self.keys[j]]=st
#checked_list.append(st)
#print "ddiic",dic
checked_list.append(dic)
print checked_list
im trying to populate QTableWidget with some data from excel file, i want to add row to my QTable only if ID is on the listID, and i get no data in QTable cells
https://drive.google.com/file/d/0B_PFK3V2Ij4tSko4emplYmNuN1E/view?usp=sharing here an excel file, it don't contain any formatin or formula, just empty rows and columns, because file is generated automaticaly
here is my code
wb = openpyxl.load_workbook(os.path.join(os.getcwd(), file), read_only=True)
ws = wb.active
headers = []
for item in ws[4]:
headers.append(item.value)
headers.pop(0)
listID = []
for index in range(self.listWidgetID.count()):
listID.append(self.listWidgetID.item(index).text())
data = ws.iter_rows(row_offset=5, column_offset=1)
row_increment = 0
self.tableWidgetDATA.setRowCount(1)
self.tableWidgetDATA.setColumnCount(len(headers))
self.tableWidgetDATA.setHorizontalHeaderLabels(headers)
for x, rows in enumerate(data):
if str(rows[0].value) in listID:
for y, cell in enumerate(rows):
item = QTableWidgetItem(str(cell.value))
self.tableWidgetDATA.setItem(x, y, item)
row_increment = row_increment + 1
self.tableWidgetDATA.setRowCount(row_increment)
To add elements to the QTableWidget, the position must be setRowCount(), in your case you update after adding, so it will not be saved, Another error is that you do not verify if the data is valid.
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.tableWidgetDATA = QTableWidget(self)
self.listWidgetID = QListWidget(self)
self.setLayout(QVBoxLayout())
self.layout().addWidget(self.listWidgetID)
self.layout().addWidget(self.tableWidgetDATA)
self.listWidgetID.addItems(["113894", "113906", "113895"])
file = "Livro2.xlsx"
wb = openpyxl.load_workbook(os.path.join(os.getcwd(), file), read_only=True)
ws = wb.active
headers = [item.value for item in ws[4] if item.value is not None]
listID = [self.listWidgetID.item(i).text() for i in range(self.listWidgetID.count())]
data = ws.iter_rows(row_offset=5, column_offset=1)
self.tableWidgetDATA.setColumnCount(len(headers))
self.tableWidgetDATA.setHorizontalHeaderLabels(headers)
for x, rows in enumerate(data):
if rows[0].value is not None:
if str(rows[0].value) in listID:
self.tableWidgetDATA.setRowCount(self.tableWidgetDATA.rowCount()+1)
for y, cell in enumerate(rows):
val = cell.value
if val is not None:
item = QTableWidgetItem(str(val))
self.tableWidgetDATA.setItem(self.tableWidgetDATA.rowCount()-1, y, item)
Output:
I have a problem when I do click on the listbox, In my program, I did click on the listbox will appear a video and explain about the video. I made a sample in the database are "name_link" which will appear in the listbox. expl1, expl2, expl3. Of each name_link have different information. However, that happens every time I click on one of these name_link, video that appears only Video3 and system never show the explain about video. When I click name_link video1 video2 emerging or always Video3. I am so stuck in this section.
this section during click :
tb4 = wx.StaticText(self, -1, label='explain', pos=(20, 145))
wx.TextCtrl(self, -1, pos=(80, 145), size=(220, 120))
self.opt = wx.ListBox(pan1, -1, pos=(10, 210), size=(480, 250), style= wx.TE_MULTILINE | wx.BORDER_SUNKEN)
def playFile(self, event):
self.player.Play()
def OnEnter(self, event):
self.opt.SetLabel(self.PatMatch())
def PatMatch(self):
con = sqlite3.connect('test.db')
with con:
cur = con.cursor()
for row in cur.execute("Select * From Video"):
klmt = self.inpt.GetValue()
if row[1] in klmt.lower():
self.opt.Append(row[2])
self.player.Load(row[4])
return self.Bind(wx.EVT_LISTBOX_DCLICK, self.playFile, self.op)
The data base like this :
id word name_link explain link
--- ------ ----------- --------- --------
1 python Video1 test C:\Users\Ihsan\Downloads\Video1.MP4
2 python Video2 test1 C:\Users\Ihsan\Downloads\Video2.MP4
3 python Video3 test2 C:\Users\Ihsan\Downloads\Video3.MP4
There are several issues:
You want bind wx.EVT_LISTBOX_DCLICK only once. When the event is fired, you want to read out which item (GetSelection) was selected when double-clicking. Use GetSelections for multiple selections.
Bad indentation: In the inner loop (self.player…) and with the return self.Bind… which should be in the innermost loop. As it is written now it will bind once to the last element. As written in point 1 this is not the way how it is done anyhow.
In Bind, self.op should be self.opt
See the wxPython demo on the download page to see how to use ListBox sensibly.
EDIT: Code sample added
import wx
import sqlite3
class play_model(object):
def __init__(self):
# all the sqlite init stuff goes here, it is mocked for the sake of the example
self.conn = sqlite3.connect(':memory:')
c = self.conn.cursor()
c.execute('CREATE TABLE video (word text, name_link text, explain text, link text)')
newrecs = (('python', 'Video1', 'test1', r'C:\video1.MP4'),
('python', 'Video2', 'test2', r'C:\video2.MP4'),
('notpython', 'Video3', 'test3', r'C:\video3.MP4'),
('python', 'Video4', 'test4', r'C:\video4.MP4'),
('python', 'Video5', 'test5', r'C:\video5.MP4'),
)
for tup in newrecs:
c.execute('INSERT INTO video VALUES (?, ?, ?, ?)', tup)
self.map_explain = {}
def get_videos(self, klmt):
# you want to get videos matching a parameter?
sqlstr = 'SELECT * FROM video WHERE video.word = (?)'
c = self.conn.cursor()
c.execute(sqlstr, (klmt.lower(),))
res = c.fetchall()
return res
class playframe(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
pnl = wx.Panel(self, -1)
self.explain = wx.StaticText(pnl, -1, 'Click in list to show explanation')
self.klmt = wx.TextCtrl(pnl, -1, '')
self.srch = wx.Button(pnl, -1, u'Search…')
self.vids = wx.ListBox(pnl, -1, style=wx.LB_MULTIPLE)
szmain = wx.BoxSizer(wx.VERTICAL)
szmain.Add(wx.StaticText(pnl, -1, 'Search for video category:'), 0, wx.EXPAND|wx.ALL, 4)
szmain.Add(self.klmt, 0, wx.EXPAND|wx.ALL, 4)
szmain.Add(self.srch, 0, wx.EXPAND|wx.ALL, 4)
szmain.Add(self.vids, 1, wx.EXPAND|wx.ALL, 4)
szmain.Add(wx.StaticText(pnl, -1, 'Explanation for video'), 0, wx.EXPAND|wx.ALL, 4)
szmain.Add(self.explain, 0, wx.EXPAND|wx.ALL, 4)
pnl.SetSizer(szmain)
szmain.Fit(self)
class controller(object):
def __init__(self, app):
self.model = play_model()
self.search_results = []
# print self.model.get_videos('python')
self.frm = playframe(None, -1, 'test_playframe')
self.frm.Show()
self.frm.srch.Bind(wx.EVT_BUTTON, self.on_srch)
self.frm.vids.Bind(wx.EVT_LISTBOX, self.onvid_dblclick)
def onvid_dblclick(self, evt):
sels = evt.GetEventObject().GetSelections()
for idx in sels:
self.frm.explain.SetLabel(self.search_results[idx][2])
print 'play video:', idx, self.search_results[idx]
def on_srch(self, evt):
klmt = self.frm.klmt.GetValue()
# print klmt
res = self.model.get_videos(klmt)
if res:
self.search_results = res
self.frm.vids.Clear()
self.frm.vids.AppendItems([row[1] for row in self.search_results])
else:
parent = self.frm
wx.MessageDialog(parent,
'Not found in word category: {0}'.format(klmt),
'Category not found').ShowModal()
if __name__ == '__main__':
app = wx.App(redirect=False)
controller(app)
app.MainLoop()
I was try create some code like this.
def playVideo(self, evt, temp):
self.player.Load(evt.GetClientObject())
self.Play(True)
self.pjs.Clear()
self.pjs.AppendText(evt.GetClientObject())
Its work for the video, the video can play. but for the information from column database explain, its not show. i want the information from column explain print in tb4. #nepix32