Python. Виджет QTableWidget

Рассмотрим последовательно решение задачи:

Вам дан файл в формате csv с ценами на товары некоторого магазина, содержащий название товара и его цену через разделитель ’;’. С помощью виджетов PyQT отобразите содержимое файла в виде таблицы и добавьте колонку «Количество», в которой значения для каждого из товаров первоначально будет равно нулю. Пользователь может менять значение в поле «Количество».

Кроме того, добавьте отображение итоговой суммы покупок, используя наиболее подходящий для этого на ваш взгляд виджет. Отображаемое значение в виджете должно рассчитываться как сумма цен товаров, умноженных на их количество. При изменении количества любого из товаров должна пересчитываться итоговая сумма.

Имеем файл rez.csv, содержащий информацию о продуктах.

Начнем с добавления таблицы с 3 столбцами и 10 строками:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QHeaderView
from PyQt5 import QtCore, QtGui, QtWidgets
import csv


class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        self.loadTable('rez.csv')
        
    def loadTable(self, table_name):        
        self.setGeometry(500, 300, 400, 300)
        self.tableWidget = QtWidgets.QTableWidget(self)
        self.tableWidget.setGeometry(QtCore.QRect(10, 10, 380, 280))
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setRowCount(10)
       

app = QApplication(sys.argv)
ex = MyWidget()
ex.show()
sys.exit(app.exec_())

Теперь удалим строки кода, задающие количество строк и столбцов. Откроем файл, сначала считаем первую строку в список title = next(reader). И зададим количество столбцов как количество элементов в списке title, увеличенное на 1. Также к нашему списку добавим значение Количество и методом setHorizontalHeaderLabels выведем заголовок таблицы.

Далее используется функция enumerate(), которая  применяется для итерируемых коллекций (строки, списки, словари и др.) и создает объект, который генерирует кортежи, состоящие из двух элементов — индекса элемента и самого элемента. При считывании очередной строки у нас увеличивается количество строк. Обращаю внимание, что мы дважды перебираем элементы — row будет содержать целиком строку, а elem — элемент этой строки.

Команда self.tableWidget.setItem(i, j, QTableWidgetItem(elem)) записывает в ячейку (i,j) значение elem. Попробуйте в конце приписать код  self.tableWidget.setItem(2, 2, QTableWidgetItem(«Ура»)) и заметьте, как изменится таблица.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QHeaderView
from PyQt5 import QtCore, QtGui, QtWidgets
import csv


class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        self.loadTable('rez.csv')
        
    def loadTable(self, table_name):        
        self.setGeometry(500, 300, 400, 300)
        self.tableWidget = QtWidgets.QTableWidget(self)
        self.tableWidget.setGeometry(QtCore.QRect(10, 10, 380, 280))
        csvfile = open(table_name, encoding="utf8")
        reader = csv.reader(csvfile, delimiter=';', quotechar='"')
        title = next(reader)
        self.tableWidget.setColumnCount(len(title) + 1)     
        self.tableWidget.setHorizontalHeaderLabels(title + ["Количество"])
        self.tableWidget.setRowCount(0)
        for i, row in enumerate(reader):
            self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
            for j, elem in enumerate(row):
                self.tableWidget.setItem(i, j, QTableWidgetItem(elem))       
      
app = QApplication(sys.argv)
ex = MyWidget()
ex.show()
sys.exit(app.exec_())

 

Теперь нам надо определить, что при изменении значений в ячейках необходимо вызвать обработчик. Это делаем так:  self.tableWidget.itemChanged.connect(self.update_check). Но для этого предварительно добавляем текстовое поле и немного изменяем размеры элементов. Также для простоты добавил, что изначальное количество товара везде равно 0.

Окончательно получаем следующий код:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QHeaderView
from PyQt5 import QtCore, QtGui, QtWidgets
import csv


class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        self.loadTable('rez.csv')
        self.textEdit = QtWidgets.QTextEdit(self)
        self.textEdit.setGeometry(10, 240, 380, 40)
        self.tableWidget.itemChanged.connect(self.update_check)

    def loadTable(self, table_name):
        self.setGeometry(500, 300, 400, 300)
        self.tableWidget = QtWidgets.QTableWidget(self)
        self.tableWidget.setGeometry(QtCore.QRect(10, 10, 380, 240))
        csvfile = open(table_name, encoding="utf8")
        reader = csv.reader(csvfile, delimiter=';', quotechar='"')
        title = next(reader)
        self.tableWidget.setColumnCount(len(title) + 1)
        self.tableWidget.setHorizontalHeaderLabels(title + ["Количество"])
        self.tableWidget.setRowCount(0)
        for i, row in enumerate(reader):
            self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
            for j, elem in enumerate(row):
                self.tableWidget.setItem(i, j, QTableWidgetItem(elem))
                self.tableWidget.setItem(i, 2, QTableWidgetItem("0"))

    def update_check(self):
        price = [int(self.tableWidget.item(i, 1).text()) 
                 for i in range(self.tableWidget.rowCount())]        
        count = [int(self.tableWidget.item(i, 2).text()) 
                 for i in range(self.tableWidget.rowCount())]
        sum_of = 0
        for i in range(len(price)):
            sum_of += price[i] * count[i]        
        self.textEdit.setText("Общая сумма: " + str(sum_of))

app = QApplication(sys.argv)
ex = MyWidget()
ex.show()
sys.exit(app.exec_())

 

Поделиться:
  • Добавить ВКонтакте заметку об этой странице
  • Мой Мир
  • Facebook
  • Twitter
  • LiveJournal
  • FriendFeed
  • В закладки Google
  • Google Buzz
  • Яндекс.Закладки
  • StumbleUpon
  • Technorati
  • БобрДобр
  • Memori.ru
  • МоёМесто.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.