Форум сайта python.su
Как добавлять записи в QTableView я разобрался)))А вот при удалении возник такой вопрос:
Допустим теперь я выделяю какую-то запись в таблице и затем мне требуется ее удалить,подскажите как определять индекс записи которая будет удалятся?
Когда я делаю запрос я указываю id как именованный аргумент и затем я указываю что вместо него нужно подставлять.
Как я понял нужно чтобы вычислялся индекс удаляемой строки,но вот как это сделать я не знаю((
Вот код:
def del_zapis(self):
self.query=QtSql.QSqlQuery()
self.query.prepare(“DELETE FROM zapchasty WHERE id=:id”)
#не знаю че указать после “:id”!!!
self.query.bindValue(“:id”,)
self.query.exec_()
self.model.setQuery(“SELECT * FROM zapchasty”)
self.table.setModel(self.model)
Буду очень благодарен за помощь!
Офлайн
В общем случае выглядеть это будет примерно так:
self.query.exec_(“Запрос, который найдет мне нужную запись”)
record = self.query.record() # возвращает QSqlRecord (первую найденную по запросу запись)
id = record.value(“id”) # вот он id, (record.value() - возвращает значение поля по его имени)
Ну а дальше уже приступать к удалению.
Только использовать PyQt для работы с бд - гиблое дело. Там все как-то через з… сделано. Лучше что-нибудь другое взять.
Офлайн
dartNNNДа ты был прав)))
В общем случае выглядеть это будет примерно так:
self.query.exec_(“Запрос, который найдет мне нужную запись”)
record = self.query.record() # возвращает QSqlRecord (первую найденную по запросу запись)
id = record.value(“id”) # вот он id, (record.value() - возвращает значение поля по его имени)
Ну а дальше уже приступать к удалению.
Только использовать PyQt для работы с бд - гиблое дело. Там все как-то через з… сделано. Лучше что-нибудь другое взять.
Офлайн
apologize828Тут просто имеется такой финт: SELECT по спецификации возвращает указатель на первую запись результата, и чтоб просмотреть весь результат необходима эта конструкция. Кстати в ней баг: while (query.next()) - сразу переводит указатель на следущую запись, и получается, что первая запись результата проходит мимо (мне лично приходилось перед этой конструкцией ее обрабатывать. Такой гемор и изврат).
while (query.next()) {
QString name = query.value(0).toString();
int salary = query.value(1).toInt();
qDebug() << name << salary;
}
Типа я что ли только таким перебором смогу обращаться к записям, что ли так?
А я разве не могу обращаться к записям сразу после например запроса “SELECT * FROM zapchasty” и не писать фигню которая делается выше?
Или я чето не догоняю((
Офлайн
dartNNNСпасибо большое за разъяснение.apologize828Тут просто имеется такой финт: SELECT по спецификации возвращает указатель на первую запись результата, и чтоб просмотреть весь результат необходима эта конструкция. Кстати в ней баг: while (query.next()) - сразу переводит указатель на следущую запись, и получается, что первая запись результата проходит мимо (мне лично приходилось перед этой конструкцией ее обрабатывать. Такой гемор и изврат).
while (query.next()) {
QString name = query.value(0).toString();
int salary = query.value(1).toInt();
qDebug() << name << salary;
}
Типа я что ли только таким перебором смогу обращаться к записям, что ли так?
А я разве не могу обращаться к записям сразу после например запроса “SELECT * FROM zapchasty” и не писать фигню которая делается выше?
Или я чето не догоняю((
По поводу кода:Я вот тоже также и думал но не смог переделать(((
query.bindValue(“:id”, tableWidget->item(tableWidget->currentIndex().row(), 0)->text())
Вот эта строчка берет номер текущей (выделенной) строки в TableWidget (tableWidget->currentIndex().row()) (кстати, вам бы его использовать, а не TableView) и берет значение 0-го столбца этой строки item(…, 0) (где и находится id) Это значение и подставляется. Т.е. в вашем случае просто поменять
self.table=QtGui.QTableView(self) на self.table=QtGui.QTableWidget(self)
и вместо
self.query.bindValue(“id”,) написать self.query.bindValue(“:id”, self.table.item(self.table.currentIndex().row(), 0).text())
И будет оно удалять выделенную строку из таблицы.
self.table=QtGui.QTableView(self) на self.table=QtGui.QTableWidget(self)то вот здесь
self.table.setModel(self.model)пишет что типа это приватный метод:
If you want a table that uses your own data model you should use QTableView rather than this class.Тогда получается надо мутить как в примере который я отметил в P.S
void MainWindow::RefreshTable()Тока тогда Здесь я не понял мысль вот этого:
{
int n = tableWidget->rowCount();
for( int i = 0; i < n; i++ ) tableWidget->removeRow( 0 );
QSqlQuery query;
query.exec(“SELECT * FROM tabMain;”);
while (query.next())
{
tableWidget->insertRow(0);
tableWidget->setItem(0, 0, new QTableWidgetItem(query.value(0).toString()));
tableWidget->setItem(0, 1, new QTableWidgetItem(query.value(1).toDateTime().toString()));
tableWidget->setItem(0, 2, new QTableWidgetItem(query.value(2).toString()));
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));
tableWidget->setRowHeight(0, 20);
}
}
int n = tableWidget->rowCount();и вот этого
for( int i = 0; i < n; i++ ) tableWidget->removeRow( 0 );
tableWidget->insertRow(0);Переписал вот это :
self.table=QtGui.QTableWidget(self)и тогда теперь надо переписать это иначе даже добавление не пашет((
self.table.resize(417,200)
self.table.setColumnCount(4)
self.item_0=QtGui.QTableWidgetItem()
self.item_0.setText(“№”)
self.item_1=QtGui.QTableWidgetItem()
self.item_1.setText(“Наименование”)
self.item_2=QtGui.QTableWidgetItem()
self.item_2.setText(“Количество”)
self.item_3=QtGui.QTableWidgetItem()
self.item_3.setText(“Цена”)
self.table.setHorizontalHeaderItem(0,self.item_0)
self.table.setHorizontalHeaderItem(1,self.item_1)
self.table.setHorizontalHeaderItem(2,self.item_2)
self.table.setHorizontalHeaderItem(3,self.item_3)
self.table.setColumnHidden(0,True)
void MainWindow::RefreshTable()Но я как уже писал выше не догоняю тут смысл некоторых строк((((
{
int n = tableWidget->rowCount();
for( int i = 0; i < n; i++ ) tableWidget->removeRow( 0 );
QSqlQuery query;
query.exec(“SELECT * FROM tabMain;”);
while (query.next())
{
tableWidget->insertRow(0);
tableWidget->setItem(0, 0, new QTableWidgetItem(query.value(0).toString()));
tableWidget->setItem(0, 1, new QTableWidgetItem(query.value(1).toDateTime().toString()));
tableWidget->setItem(0, 2, new QTableWidgetItem(query.value(2).toString()));
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));
tableWidget->setRowHeight(0, 20);
}
}
def refresh(self):Тогда добавляет тока одну строку и пишет ошибку
self.table.removeRow(0)
self.query=QtSql.QSqlQuery()
self.query.exec(“SELECT * FROM zapchasty”)
self.item0=QtGui.QTableWidgetItem()
self.item1=QtGui.QTableWidgetItem()
self.item2=QtGui.QTableWidgetItem()
self.item3=QtGui.QTableWidgetItem()
while self.query.next():
self.table.insertRow(0)
self.table.setItem(0,0,self.item0(self.query.value(0)))
self.table.setItem(0,1,self.item1(self.query.value(1)))
self.table.setItem(0,2,self.item2(self.query.value(2)))
self.table.setItem(0,3,self.item3(self.query.value(3)))
self.table.setItem(0,0,self.item0(self.query.value(0).toInt()))то теперь вот эта фигня)))
P.S. Или я вообще не правильно понял и тут можно работать с setModel()
Отредактировано (Март 11, 2010 21:01:40)
Офлайн
apologize828Вместо этого лучше сразу писать
self.item_0=QtGui.QTableWidgetItem()
self.item_0.setText(“№”)
self.item_1=QtGui.QTableWidgetItem()
self.item_1.setText(“Наименование”)
self.item_2=QtGui.QTableWidgetItem()
self.item_2.setText(“Количество”)
self.item_3=QtGui.QTableWidgetItem()
self.item_3.setText(“Цена”)
self.table.setHorizontalHeaderItem(0,self.item_0)
self.table.setHorizontalHeaderItem(1,self.item_1)
self.table.setHorizontalHeaderItem(2,self.item_2)
self.table.setHorizontalHeaderItem(3,self.item_3)
self.table.setHorizontalHeaderItem(0,QtGui.QTableWidgetItem('№'))
apologize828Тут имеется ввиду, что TableWidget работает без модели (метод setModel недоступен), поэтому он “вручную” очищается (имеется ввиду удаляется строка на позиции 0, т.е. первая строка удаляется n раз) И заново заполняется
int n = tableWidget->rowCount();
for( int i = 0; i < n; i++ ) tableWidget->removeRow( 0 );
while (query.next())
{
tableWidget->insertRow(0);
tableWidget->setItem(0, 0, new QTableWidgetItem(query.value(0).toString()));
tableWidget->setItem(0, 1, new QTableWidgetItem(query.value(1).toDateTime().toString()));
tableWidget->setItem(0, 2, new QTableWidgetItem(query.value(2).toString()));
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));
tableWidget->setRowHeight(0, 20);
}
def refresh(self):
self.table.removeRow(0)
self.query=QtSql.QSqlQuery()
self.query.exec("SELECT * FROM zapchasty")
self.item0=QtGui.QTableWidgetItem()
self.item1=QtGui.QTableWidgetItem()
self.item2=QtGui.QTableWidgetItem()
self.item3=QtGui.QTableWidgetItem()
while self.query.next():
self.table.insertRow(0)
self.table.setItem(0,0,self.item0(self.query.value(0)))
self.table.setItem(0,1,self.item1(self.query.value(1)))
self.table.setItem(0,2,self.item2(self.query.value(2)))
self.table.setItem(0,3,self.item3(self.query.value(3)))
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));
self.table.setItem(0, 3, QtGui.QTableWidgetItem(self.query.value(3).toString()));
Офлайн
self.table.setHorizontalHeaderItem(0,QtGui.QTableWidgetItem('№'))Понял))
Не забывайте про читабельность :)
int n = tableWidget->rowCount();Спасибо теперь все понял.
for( int i = 0; i < n; i++ ) tableWidget->removeRow( 0 );
Тут имеется ввиду, что TableWidget работает без модели (метод setModel недоступен), поэтому он “вручную” очищается (имеется ввиду удаляется строка на позиции 0, т.е. первая строка удаляется n раз) И заново заполняется
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));Здесь toString() не канала(((
Означает, что в позицию 0,3 устанавливаем новый экземпляр QTableWidgetItem, созданного с параметром query.value(3).toString()
ЗЫ. Не стоит все переменные вешать на self (self.table, self.query…) Это не очень хорошо. В этом случае вы храните дополнительные ссылки на объекты (query) до тех пор пока у вас существует self, то есть само окно. Хотя для query в этом нет необходимости, и если вы его опишите как просто query (без self), то он будет храниться только пока выполняется функция (будет как локальная переменная, которая уничтожается по выходу из функции). Это технический моммент, а еще важно, что query имеет смысл только в рамках даннной функции (в других функциях уже другие, не связанные запросы) что несомненно сказывается на читабельности (и писать меньше придется :)).Учту на будущее)
self.table=QtGui.QTableWidget(self)
self.table.resize(417,200)
self.table.setColumnCount(4)
self.table.setHorizontalHeaderItem(0,QtGui.QTableWidgetItem(“№”))
self.table.setHorizontalHeaderItem(1,QtGui.QTableWidgetItem(“Наименование”))
self.table.setHorizontalHeaderItem(2,QtGui.QTableWidgetItem(“Количество”))
self.table.setHorizontalHeaderItem(3,QtGui.QTableWidgetItem(“Цена”))
self.table.setColumnHidden(0,True)
def refresh(self):Вот это пришлось написать так потому что надо что бы ячейки нельзя было редактировать:
n=self.table.rowCount()
i=0
while i<n:
if i<n:
self.table.removeRow(0)
i+=1
continue
else:
break
query=QtSql.QSqlQuery()
query.exec(“SELECT * FROM zapchasty”)
while query.next():
item0=QtGui.QTableWidgetItem(query.value(0))
item0.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item1=QtGui.QTableWidgetItem(query.value(1))
item1.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item2=QtGui.QTableWidgetItem(query.value(2))
item2.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item3=QtGui.QTableWidgetItem(query.value(3))
item3.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
self.table.insertRow(0)
self.table.setItem(0,0,item0)
self.table.setItem(0,1,item1)
self.table.setItem(0,2,item2)
self.table.setItem(0,3,item3)
item0=QtGui.QTableWidgetItem(query.value(0))
item0.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item1=QtGui.QTableWidgetItem(query.value(1))
item1.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item2=QtGui.QTableWidgetItem(query.value(2))
item2.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item3=QtGui.QTableWidgetItem(query.value(3))
item3.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
def add_zapis(self):
a=self.my_form2.edit_naimenovanie.text()
b=self.my_form2.edit_kolichestvo.text()
c=self.my_form2.edit_price.text()
query=QtSql.QSqlQuery()
query.prepare(“INSERT INTO zapchasty(naimenovanie,kolichestvo,price) VALUES(:naimen,:kolich,:pr)”)
query.bindValue(“:naimen”,a)
query.bindValue(“:kolich”,b)
query.bindValue(“:pr”,c)
query.exec_()
self.refresh()
self.my_form2.hide()
def del_zapis(self):Теперь ситуация следующая:
if self.table.currentIndex().row()>=0:
query=QtSql.QSqlQuery()
query.prepare(“DELETE FROM zapchasty WHERE id=:id”)
query.bindValue(“id”,self.table.item(self.table.currentIndex().row(),0).text())
query.exec_()
self.refresh()
else:
pass
tableWidget->setItem(0, 3, new QTableWidgetItem(query.value(3).toString()));Но это не канало да и как видешь я щас переделал так что не знаю че делать(((Короче вроде надо как то преобразовать типы.
Означает, что в позицию 0,3 устанавливаем новый экземпляр QTableWidgetItem, созданного с параметром query.value(3).toString()
P.S. Может здесь собака зарыта: Различные типы значений базы данных автоматически приводятся к ближайшему эквиваленту в Qt.И Так как id тоже не видно в ячейке то походу из-за этого и удаление не срабатывает(((
Отредактировано (Март 12, 2010 21:36:32)
Офлайн
Все сделал))) просто затупил нереально)))
При изучении этой фигни я и забыл что я на Питоне а не на С++ и тут нет toString()
А Здесь просто надо обернуть в str()
Вот что значит 6-8 часов кодинга в день)))
Спасибо тебе огромное за помощь.Если вдруг возникнут вопросы по редактированию я еще загляну сюда)))
P.S На будущее: если у тебя имеются какие-нибудь примеры где можно посмотреть как это же сделать с помощью model/view, т.е как я изначально и пытался сделать,то я буду тебе очень благодарен за такие примеры.
Просто где то читал что такой способ уже старая школа который был в старых версиях Qt, а сейчас все уже пользуются QTableView. т.е model/view. Да и типа если в базе будет до фига данных говорят что тогда лучше опять таки использовать модель!
Да и спасибо за разъяснения!
Вот в общем что получилось:
#!usr/bin/python
#-*- coding: utf-8 -*-
from PyQt4 import QtGui
from PyQt4 import QtSql
from PyQt4 import QtCore
import sys
def create_connection():
db=QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(":memory:")
if not db.open():
my_message=My_Messqge()
my_message.show()
my_message.exec_()
return False
query=QtSql.QSqlQuery()
query.exec("CREATE TABLE IF NOT EXISTS zapchasty(id INTEGER PRIMARY KEY AUTOINCREMENT, naimenovanie VARCHAR(50), kolichestvo INTEGER, price FLOAT)")
return True
class My_Gui(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.resize(520,300)
self.table=QtGui.QTableWidget(self)
self.table.resize(417,200)
self.table.setColumnCount(4)
self.table.setHorizontalHeaderItem(0,QtGui.QTableWidgetItem("№"))
self.table.setHorizontalHeaderItem(1,QtGui.QTableWidgetItem("Наименование"))
self.table.setHorizontalHeaderItem(2,QtGui.QTableWidgetItem("Количество"))
self.table.setHorizontalHeaderItem(3,QtGui.QTableWidgetItem("Цена"))
self.table.setColumnHidden(0,True)
self.button_add=QtGui.QPushButton("Добавить",self)
self.button_delete=QtGui.QPushButton("Удалить",self)
self.button_add.setIcon(QtGui.QIcon("logo/add2.png"))
self.buttons_wdget=QtGui.QWidget(self)
self.buttons_wdget.setGeometry(410,10,100,100)
self.buttons_kompanovka=QtGui.QVBoxLayout(self.buttons_wdget)
self.buttons_kompanovka.addWidget(self.button_add)
self.buttons_kompanovka.addWidget(self.button_delete)
self.button_add.clicked.connect(self.zapusk_form2)
self.button_delete.clicked.connect(self.del_zapis)
def zapusk_form2(self):
self.my_form2=My_Gui2()
self.my_form2.show()
self.my_form2.button_addd.clicked.connect(self.add_zapis)
def refresh(self):
n=self.table.rowCount()
i=0
while i<n:
if i<n:
self.table.removeRow(0)
i+=1
continue
else:
break
query=QtSql.QSqlQuery()
query.exec("SELECT * FROM zapchasty")
while query.next():
item0=QtGui.QTableWidgetItem(str(query.value(0)))
item0.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item1=QtGui.QTableWidgetItem(str(query.value(1)))
item1.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item2=QtGui.QTableWidgetItem(str(query.value(2)))
item2.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
item3=QtGui.QTableWidgetItem(str(query.value(3)))
item3.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
self.table.insertRow(0)
self.table.setItem(0,0,item0)
self.table.setItem(0,1,item1)
self.table.setItem(0,2,item2)
self.table.setItem(0,3,item3)
def add_zapis(self):
a=self.my_form2.edit_naimenovanie.text()
b=self.my_form2.edit_kolichestvo.text()
c=self.my_form2.edit_price.text()
query=QtSql.QSqlQuery()
query.prepare("INSERT INTO zapchasty(naimenovanie,kolichestvo,price) VALUES(:naimen,:kolich,:pr)")
query.bindValue(":naimen",a)
query.bindValue(":kolich",b)
query.bindValue(":pr",c)
query.exec_()
self.refresh()
self.my_form2.hide()
def del_zapis(self):
if self.table.currentIndex().row()>=0:
query=QtSql.QSqlQuery()
query.prepare("DELETE FROM zapchasty WHERE id=:id")
query.bindValue("id",self.table.item(self.table.currentIndex().row(),0).text())
query.exec_()
self.refresh()
else:
pass
class My_Gui2(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.resize(300,150)
self.setWindowModality(QtCore.Qt.ApplicationModal)
self.all_widget=QtGui.QWidget(self)
self.label_naimenovanie=QtGui.QLabel("Наименование")
self.edit_naimenovanie=QtGui.QLineEdit()
self.label_kolichestvo=QtGui.QLabel("Количество")
self.edit_kolichestvo=QtGui.QLineEdit()
self.label_price=QtGui.QLabel("Цена")
self.edit_price=QtGui.QLineEdit()
self.kompanovka=QtGui.QVBoxLayout(self.all_widget)
self.kompanovka.addWidget(self.label_naimenovanie)
self.kompanovka.addWidget(self.edit_naimenovanie)
self.kompanovka.addWidget(self.label_kolichestvo)
self.kompanovka.addWidget(self.edit_kolichestvo)
self.kompanovka.addWidget(self.label_price)
self.kompanovka.addWidget(self.edit_price)
self.button_addd=QtGui.QPushButton("Добавить",self)
self.button_addd.setGeometry(200,10,100,50)
class My_Messqge(QtGui.QMessageBox):
def __init__(self):
QtGui.QMessageBox.__init__(self)
self.setIcon(QtGui.QMessageBox.Warning)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint|QtCore.Qt.WindowTitleHint)
self.setWindowTitle("Ошибка открытия Базы Данных")
self.setText("Неудалось открыть Базу Данных!Нажмите кнопку Дальше чтобы продолжить работу с приложением.")
self.addButton("Дальше", QtGui.QMessageBox.AcceptRole)
class My_Messqge2(QtGui.QMessageBox):
def __init__(self):
QtGui.QMessageBox.__init__(self)
self.setIcon(QtGui.QMessageBox.Critical)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint|QtCore.Qt.WindowTitleHint)
self.setWindowTitle("Ошибка соединения с Базой Данных")
self.setText("Неудалось установить соединение с Базой Данных!Нажмите кнопку Выход чтобы завершить работу приложения.")
self.addButton("Выход",QtGui.QMessageBox.AcceptRole)
app=QtGui.QApplication(sys.argv)
if not create_connection():
my_message2=My_Messqge2()
my_message2.show()
my_message2.exec_()
else:
my_forma1=My_Gui()
my_forma1.show()
app.exec_()
Офлайн
apologize828Это вообще что такое? Это вообще как понимать? Вы меня извините, но так не пойдет.i=0
while i<n:
if i<n:
self.table.removeRow(0)
i+=1
continue
else:
break
n=self.table.rowCount()
for x in range(n) #для python2.x: xrange()
self.table.removeRow(0)
Офлайн
n=self.table.rowCount()
for x in range(n) #для python2.x: xrange()
self.table.removeRow(0)
Отредактировано (Март 13, 2010 13:24:56)
Офлайн