Хм… Функции с принтом действительно работают на левый и правый клик, а вот реальная функция (поставленная на правый клик) с методом text() вызвала ошибку:
Нажатие левой кнопки выводит принт в Shell, а правой - запускает функцию self.lst_filter_LW
# Python 3
# -*- coding: utf-8 -*-
version = '2017.12.18' # Добавлены правый и левый клики на таблицу.
import sys, pickle
from PyQt4 import QtCore, QtGui, Qt
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
QGroupBox, QFileDialog, QMessageBox,
QTableWidget, QHeaderView, QStandardItemModel, QStandardItem,
QAbstractItemView, QTableWidgetItem,
QListWidget, QSortFilterProxyModel, QBrush, QColor)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
PyQT = 4
# ДАННЫЕ
db_tb = [{'магазин 2': '3', 'магазин 3': '7', 'Фрукты': 'апельсины', 'магазин 1': '4'},
{'магазин 2': '3', 'магазин 3': '9', 'Фрукты': 'яблоки', 'магазин 1': '16'},
{'магазин 2': '44', 'магазин 3': '3', 'Фрукты': 'мандарины', 'магазин 1': '16'},
{'магазин 2': '2', 'магазин 3': '7', 'Фрукты': 'мандарины', 'магазин 1': '4'},
{'магазин 2': '44', 'магазин 3': '7', 'Фрукты': 'яблоки', 'магазин 1': '2;16'},
{'магазин 2': '74', 'магазин 3': '5', 'Фрукты': 'мандарины', 'магазин 1': '16'},
{'магазин 2': '3', 'магазин 3': '7', 'Фрукты': 'апельсины', 'магазин 1': '4'},
{'магазин 2': '3', 'магазин 3': '9', 'Фрукты': 'яблоки', 'магазин 1': '16'},
{'магазин 2': '44', 'магазин 3': '3', 'Фрукты': 'мандарины', 'магазин 1': '16'},
{'магазин 2': '2', 'магазин 3': '7', 'Фрукты': 'мандарины', 'магазин 1': '4'},
{'магазин 2': '44', 'магазин 3': '7', 'Фрукты': 'яблоки', 'магазин 1': '2;16'},
{'магазин 2': '74', 'магазин 3': '5', 'Фрукты': 'мандарины', 'магазин 1': '16'},
{'магазин 2': '3', 'магазин 3': '7', 'Фрукты': 'апельсины', 'магазин 1': '4'},
{'магазин 2': '3', 'магазин 3': '9', 'Фрукты': 'яблоки', 'магазин 1': '16'},
{'магазин 2': '44', 'магазин 3': '3', 'Фрукты': 'мандарины', 'магазин 1': '16'},
{'магазин 2': '2', 'магазин 3': '7', 'Фрукты': 'мандарины', 'магазин 1': '4'},
{'магазин 2': '44', 'магазин 3': '7', 'Фрукты': 'яблоки', 'магазин 1': '2;16'},
{'магазин 2': '74', 'магазин 3': '5', 'Фрукты': 'мандарины', 'магазин 1': '16'}]
# ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
columnName = ["Фрукты", "магазин 1", "магазин 2",
"магазин 3"] # заголовки табл
rowCount = len(db_tb) # число строк
columnCount = len(columnName) # число столбцов
rowHeight = 20 # высота строки
db_tb_i = {}
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 10pt 'Courier New'")
sss = ("background-color: #456173; color: #f2f2f0; font: 10pt 'Arial'")
sss_err = ("color: #ff6161; font: bold 10pt 'Courier New'")
# КЛИК ПО ТАБЛИЦЕ
class QTbW(QTableWidget):
left_click = QtCore.pyqtSignal()
right_click = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def mousePressEvent(self, event):
if event.button() == Qt.Qt.LeftButton:
self.left_click.emit()
elif event.button() == Qt.Qt.RightButton:
self.right_click.emit()
# ГРАФИКА
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
x_win = 500 # ширина окна
# self.setMinimumSize(250, 300) # Ширина и высота окна
self.resize(x_win, 500) # шир / выс окна
self.setWindowTitle('QTableWidget + фильтры') # Заголовок
self.setWindowIcon(QIcon('icon.png')) # Иконка
# ПОДКЛЮЧЕНИЕ СТИЛЕЙ
sss = open('dark_blue.stylesheet', 'r')
self.styleData = sss.read()
sss.close()
self.setStyleSheet(self.styleData)
# БЛОК РАЗМЕТКИ
grid_os = QGridLayout()
# --- ---
lbl_name = QLabel('<center><h2>Наименование</h2></center>')
grid_os.addWidget(lbl_name, 0,0,1,2)
# --- ---
# >>> УПРАВЛЕНИЕ ТАБЛИЦЕЙ
grid_upr_tb = QGridLayout()
grid_upr_tb.setSpacing(5)
# --- ---
self.pix_f = QPixmap("search_512")
scaled_pix = self.pix_f.scaled(15, 15)
lbl_f = QLabel(self,alignment=QtCore.Qt.AlignCenter)
lbl_f.setPixmap(scaled_pix)
grid_upr_tb.addWidget(lbl_f, 0,0)
# --- ---
self.pole_find = QLineEdit()
self.pole_find.textChanged.connect(self.on_find_glob)
grid_upr_tb.addWidget(self.pole_find, 0,1,1,3)
# ---
self.button_up_row = QPushButton('▲')
self.button_up_row.clicked.connect(self.on_up_row)
grid_upr_tb.addWidget(self.button_up_row, 0,4)
# ---
self.button_down_row = QPushButton('▼')
self.button_down_row.clicked.connect(self.on_down_row)
grid_upr_tb.addWidget(self.button_down_row, 0,5)
# ---
self.button_prnt = QPushButton('Print ДБ')
self.button_prnt.clicked.connect(self.on_prnt)
grid_upr_tb.addWidget(self.button_prnt, 0,6,1,3)
# ---
self.button_del_row = QPushButton('–')
self.button_del_row.clicked.connect(self.on_del_row)
grid_upr_tb.addWidget(self.button_del_row, 0,9,1,3)
# ---
self.button_proba = QPushButton('Proba')
#self.button_proba.clicked.connect(self.on_sc)
grid_upr_tb.addWidget(self.button_proba, 0,12,1,3)
# ---
self.lbl_status = QLabel('')
self.lbl_status.setStyleSheet(sss_err)
grid_upr_tb.addWidget(self.lbl_status, 0,15)
# --- настройка
grid_upr_tb.setColumnStretch(15, 1)
# --- ---
# >>> КОНЕЦ: УПРАВЛЕНИЕ ТАБЛИЦЕЙ
# >>> ПАНЕЛЬ ПОИСКА ПО ТАБЛИЦЕ
grid_find = QGridLayout()
grid_find.setSpacing(1)
# --- ---
self.pix_f = QPixmap("search_512")
scaled_pix = self.pix_f.scaled(15, 15)
lbl_f = QLabel(self,alignment=QtCore.Qt.AlignCenter)
lbl_f.setPixmap(scaled_pix)
grid_find.addWidget(lbl_f, 0,0)
# --- ---
self.lines = [None for i in range(columnCount)]
self.lst_obj_name = ['line' + str(i) for i in range(columnCount)]
for col in range(columnCount):
line = QLineEdit()
line.setObjectName('line' + str(col))
self.lines[col] = line
self.lines[col].textChanged.connect(self.on_find)
grid_find.addWidget(line,0,col+1)
# >>> КОНЕЦ: ПАНЕЛЬ ПОИСКА ПО ТАБЛИЦЕ
# >>> ТАБЛИЦА
self.table = QTbW()
self.createTable(columnName, rowCount, columnCount, rowHeight)
# >>> КОНЕЦ: ТАБЛИЦА
# >>> ПАНЕЛЬ ФИЛЬТРА
grid_filter = QGridLayout()
grid_filter.setSpacing(5)
self.list = QListWidget()
grid_filter.addWidget(self.list, 0,0)
# --- ---
self.button_del_filter = QPushButton('Сбросить фильтр')
self.button_del_filter.clicked.connect(self.del_filter)
grid_filter.addWidget(self.button_del_filter, 1,0)
# >>> КОНЕЦ: ПАНЕЛЬ ФИЛЬТРА
# >>> КАРТОЧКА
frame_cart = QFrame()
frame_cart.setFrameShape(6)
frame_cart_lay = QGridLayout(frame_cart)
grid_cart = QGridLayout()
grid_cart.setSpacing(5)
frame_cart_lay.addLayout(grid_cart, 0,0)
# --- ---
lbl_1 = QLabel(columnName[0])
grid_cart.addWidget(lbl_1, 0,0)
# ---
self.pole_1 = QLineEdit()
grid_cart.addWidget(self.pole_1, 0,1)
# --- ---
lbl_2 = QLabel(columnName[1])
grid_cart.addWidget(lbl_2, 1,0)
# ---
self.pole_2 = QLineEdit()
grid_cart.addWidget(self.pole_2, 1,1)
# --- ---
lbl_3 = QLabel(columnName[2])
grid_cart.addWidget(lbl_3, 2,0)
# ---
self.pole_3 = QLineEdit()
grid_cart.addWidget(self.pole_3, 2,1)
# --- ---
lbl_4 = QLabel(columnName[3])
grid_cart.addWidget(lbl_4, 3,0)
# ---
self.pole_4 = QLineEdit()
grid_cart.addWidget(self.pole_4, 3,1)
# --- ---
lbl_end = QLabel('')
grid_cart.addWidget(lbl_end, 20,0)
# >>> КОНЕЦ: КАРТОЧКА
# >>> ПАНЕЛЬ УПРАВЛЕНИЯ КАРТОЧКОЙ
grid_upr_cart = QGridLayout()
grid_upr_cart.setSpacing(5)
frame_cart_lay.addLayout(grid_upr_cart, 1,0)
# --- ---
self.button_save_db = QPushButton('Сохр БД')
self.button_save_db.clicked.connect(self.save_in_file)
grid_upr_cart.addWidget(self.button_save_db, 0,0,1,3)
# --- ---
self.button_edit_row = QPushButton('Ред стр')
self.button_edit_row.clicked.connect(self.on_edit_row)
grid_upr_cart.addWidget(self.button_edit_row, 0,3,1,3)
# ---
self.button_save_row = QPushButton('Сохр стр')
self.button_save_row.clicked.connect(self.on_save_row)
grid_upr_cart.addWidget(self.button_save_row, 0,6,1,3)
# ---
self.button_del_row = QPushButton('Удалить стр')
self.button_del_row.clicked.connect(self.on_del_row)
grid_upr_cart.addWidget(self.button_del_row, 0,9,1,3)
# --- настройка
self.lbl_nas = QLabel('')
grid_upr_cart.addWidget(self.lbl_nas, 0,12)
grid_upr_cart.setColumnStretch(12, 1) # индекс / растяжение
# >>> КОНЕЦ: ПАНЕЛЬ УПРАВЛЕНИЯ КАРТОЧКОЙ
# --- ---
grid_os.addLayout(grid_upr_tb, 1,0,1,2)
grid_os.addLayout(grid_find, 2,0,1,2)
grid_os.addWidget(self.table, 3,0,1,2)
grid_os.addLayout(grid_filter, 4,0)
grid_os.addWidget(frame_cart, 4,1)
# настройка
grid_os.setRowStretch(3, 1) # индекс / растяжение
grid_os.setColumnStretch(0, 1) # индекс / растяжение
grid_os.setColumnStretch(1, 8) # индекс / растяжение
#self.grid_os.setRowStretch(2, 1) # поднимает вверх №-индекса строку; индекс/растяж
# --- ---
self.setLayout(grid_os)
# --- переменные ---
self.lst_in_column_open_uni = []
self.lst_open_row = []
self.lst_in_column = None
self.lst_in_column_open = None
self.lst_open_row = range(rowCount)
# ---
# === === ФУНКЦИИ РАБОТЫ ТАБЛИЦЫ ===
def on_tb(self):
#db_tb = self.viewport.db_tb
self.on_start()
def createTable(self, columnName, rowCount, columnCount, rowHeight):
# создание таблицы
'''создаем строки и столбцы в таблице
columnName - подписи шапки таблицы
rowCount - количество строк таблицы
columnCount - количество столбцов таблицы
rowHeight - высота строки'''
# Настройка заголовков и строк
if PyQT == 4:
self.table.verticalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
self.table.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
elif PyQT == 5:
self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
#self.table.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
#self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
#self.table.horizontalHeader().setMaximumSectionSize(100) # максимальная ширина столбца
#self.table.horizontalHeader().setMinimumSectionSize(50) # минимальная ширина столбца
#self.table.horizontalHeader().resizeSection(2,300)
# Режим выделения. Выделяем только строки. Выделяем только одну строку.
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table.setSelectionMode(QAbstractItemView.SingleSelection)
# Стилизуем шапку таблицы
self.table.horizontalHeader().setStyleSheet("QHeaderView::section{background-color: \
QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, \
stop: 0.6 #434343, stop:1 #656565); color: white; padding-left: 4px; \
border: 1px solid #6c6c6c;}");
# self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) # Запрет редактирования таблицы
self.table.setEditTriggers(QAbstractItemView.CurrentChanged) # выделение элемента
self.table.setEditTriggers(QAbstractItemView.DoubleClicked)
self.table.setRowCount(rowCount) # Устанавливаем количество строк
self.table.setColumnCount(columnCount) # Устанавливаем количество столбцов
i = 0 # формируем подписи шапки:
for name in columnName:
item = QTableWidgetItem()
item.setText(name)
self.table.setHorizontalHeaderItem(i,item)
i+=1
# Устанавливаем высоту строк
for i in range(0, rowCount):
self.table.setRowHeight(i, rowHeight)
#self.table.setColumnWidth(2, 50)
# СИГНАЛЫ И ДОП СВОЙСТВА
self.table.itemChanged.connect(self.cell_tabl_in_db) # сохр изменений в ячейке
#self.table.cellChanged.connect(self.predup) # предупреждение об изменении ячейки
self.table.left_click.connect(left_click)
self.table.right_click.connect(self.lst_filter_LW)
# АВТОЗАПУСК
self.on_start_tb(db_tb)
def on_start_tb(self, db_tb):
#print('start ',db_tb)
self.table.blockSignals(1) # блокировка сигналов (True)
for i in range(0,rowCount): # вставить базу данных в таблицу
for j in range(0,columnCount):
self.db_in_cell_tabl(i,j)
self.table.blockSignals(False) # отмена блокировки сигналов
def on_add_row (self):
row_index = len(db_tb)
self.table.insertRow(row_index)
self.table.setRowHeight(row_index, rowHeight) # высота строки
db_tb.append(dict.fromkeys(columnName,''))
self.on_status(1)
def paste_row(self, row,text):
self.table.blockSignals(True) # блокировка сигналов
self.table.setRowHeight(row, rowHeight) # высота строки
for j in range(0,columnCount): # в таблицу вставляем значения
self.db_in_cell_tabl(row,j)
self.table.blockSignals(False) # отмена блокировки сигналов
def db_in_cell_tabl(self, i,j): # из базы данных в ячейку
item = QTableWidgetItem()
item.setText(str(db_tb[i][columnName[j]]))
self.table.setItem(i,j,item)
def cell_tabl_in_db(self): # из ячейки табл в базу данных
i = self.table.currentRow() # индекс выделенной строки
j = self.table.currentColumn() # индекс выделенной строки
text = self.table.item(i,j).text() # извлечь текст из ячейки
db_tb[i][columnName[j]] = text # текст в базу
self.on_status(1)
def on_up_row (self): # перемещение строки вверх
row_index = self.table.currentRow() # индекс выделенной строки
if row_index == 0:
pass
else:
db_tb.insert(row_index-1,db_tb[row_index]) # вставить строку в базу
del db_tb[row_index+1] # удалить старую строку из базы
self.table.insertRow(row_index-1) # вставить строку в табл
self.table.removeRow(row_index+1) # удалить старую строку из табл
self.paste_row(row_index-1,db_tb[row_index-1])
self.table.selectRow(row_index-1)
self.on_status(1)
def on_down_row (self): # перемещение строки вниз
row_index = self.table.currentRow() # индекс выделенной строки
if row_index+1 == len(db_tb):
pass
else:
db_tb.insert(row_index+2,db_tb[row_index]) # вставить строку в базу
del db_tb[row_index] # удалить старую строку из базы
self.table.insertRow(row_index+2) # вставить строку в табл
self.table.removeRow(row_index) # удалить старую строку из табл
self.paste_row(row_index+1,db_tb[row_index+1])
self.table.selectRow(row_index+1) # выделяет передвинутую строку
self.on_status(1)
def on_del_row (self):
row_index = self.table.currentRow() # индекс выделенной строки
del db_tb[row_index] # удалить строку в базе
self.table.removeRow(row_index) # удалить строку в таблице
self.on_status(1)
def on_edit_row(self): # правка строки в полях ввода
row_index = self.table.currentRow() # индекс выделенной строки
db_tb_i = db_tb[row_index]
for i in range(0,len(self.polya)): # вставить строку из таблицы в поля
self.polya[i].setText(db_tb_i[columnName[i]])
def on_save_row(self): # изм строку в полях отправить в таблицу
# сбор данных для 1 строки
db_tb_i = dict(zip(columnName, [polya.text() for polya in self.polya]))
# конец: сбор данных
row_index = self.table.currentRow() # индекс выделенной строки
db_tb[row_index].update(db_tb_i) # обновление словаря
self.paste_row(row_index,db_tb_i)
self.clear_polya()
self.status()
def save_in_file(self): # сохранить базу в файл
with open('temp/db_grunt_m.pkl', 'wb') as f:
pickle.dump(db_tb, f)
self.on_status(0)
def on_status(self, x=None):
if x == 1: # не сохр
self.lbl_status.setStyleSheet("background-color: #c84361")
else: # сохр
self.lbl_status.setStyleSheet("background-color: #33927e")
def on_prnt(self): # вывод БД в Shell и в поле вывода
for i in range(0,len(db_tb)):
print(i,':',db_tb[i],sep='')
# === === END: ФУНКЦИИ РАБОТЫ ТАБЛИЦЫ ===
# === >>> ФИЛЬТР LISTWIDGET ===
def lst_filter_LW(self): # формирование списка значений фильтра
print('>'*20)
index_column = self.table.currentIndex().column()
self.lst_in_column = []
for i in range(self.table.rowCount()):
item_text = self.table.item(i,index_column).text()
if item_text.count(';') == 0: # результат - строка
self.lst_in_column.append(item_text)
else: # результат - список
item_text_lst = item_text.split(';')
self.lst_in_column.extend(item_text_lst)
print('self.lst_in_column =',self.lst_in_column)
# список открытых строк (значения) в выбранном столбце:
self.lst_in_column_open = list(self.lst_in_column[i] for i in self.lst_open_row)
self.lst_in_column_open_uni = [] # уникальный список строк выбранного столбца
for i in self.lst_in_column_open: # формирование уникального списка
if i not in self.lst_in_column_open_uni:
self.lst_in_column_open_uni.append(i)
self.lst_in_column_open_uni.sort()
print('self.lst_in_column_open_uni =',self.lst_in_column_open_uni)
# заполнение строк ListWidget
model_list = QStandardItemModel(self.list)
for i in range(0, len(self.lst_in_column_open_uni)):
item = QStandardItem(self.lst_in_column_open_uni[i])
model_list.appendRow(item)
self.list.clear()
self.list.addItems(self.lst_in_column_open_uni)
self.list.clicked.connect(self.tb_filter_LW)
def tb_filter_LW(self):
print('-'*20)
index_row = self.list.currentIndex().row()
index_column = self.table.currentIndex().column()
filter_name = self.lst_in_column_open_uni[index_row]
print('filter_name =',filter_name)
# применение фильтра:
for i in range(len(db_tb)):
item_text = self.table.item(i,index_column).text()
if item_text.count(';') == 0: # результат - строка
if filter_name != item_text:
self.table.hideRow(i)
else: # результат - список
item_text_lst = item_text.split(';')
hide = None
for j in range(len(item_text_lst)):
if filter_name == item_text_lst[j]:
hide = 'no'
if hide == None:
self.table.hideRow(i)
# список открытых строк (индексы)
self.lst_open_row = [] # обнуление списка
for i in range(len(db_tb)):
if self.table.isRowHidden(i) == False: # строка не скрыта
self.lst_open_row.append(i) # в список открытых строк / индексов
print('self.lst_open_row =',self.lst_open_row)
def del_filter(self): # сброс фильтра
self.lst_in_column_open_uni = []
self.lst_open_row = []
self.lst_in_column = None
self.lst_in_column_open = None
self.lst_open_row = range(rowCount)
for i in range(len(db_tb)):
self.table.showRow(i)
# === >>> КОНЕЦ: ФИЛЬТР LISTWIDGET ===
# ========= КОНЕЦ: ФУНКЦИИ ТАБЛИЦЫ
def on_find_glob(self):
text = self.pole_find.text()
#fff = self.table.findItems(text, 0, 0)
for i in range(self.table.rowCount()):
for j in range(columnCount):
lst_find = self.table.item(i,j).findItems(text, 0)
print('findItems =',lst_find)
row_index = 12
self.table.selectRow(row_index) # выделить строку
self.table.scrollTo(self.table.model().index(row_index,0), 3)
def on_find(self):
text = self.sender().text()
print('text =',text)
column_index = self.lst_obj_name.index(self.sender().objectName())
row_index = 12
self.table.selectRow(row_index) # выделить строку
self.table.scrollTo(self.table.model().index(row_index,0), 3)
def left_click(self):
print('left click')
# КОНЕЦ
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.move(40, 20) # сдвиг окна от верхнего левого угла экрана
pal = window.palette()
pal.setBrush(QPalette.Window, QBrush(QColor("#222831")))
window.setPalette(pal) # передаёт изменёный цвет окну
window.show() # запускает окно
sys.exit(app.exec_())