Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.58/141: Рейтинг темы: голосов - 141, средняя оценка - 4.58
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521

Pyqt. Класс QTableView

23.12.2018, 18:01. Показов 29854. Ответов 60
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!

Напишите, пожалуйста, примеры использования QTableview: указание количества строк/столбцов, заголовки столбцов, заполнение значениями. Вроде надо с помощью QAbstractItemModel. Гуглится в основном про QTableWidget.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.12.2018, 18:01
Ответы с готовыми решениями:

PyQt, редактируемый QTableView и автодобавление строк
Есть таблица, представляется классами myModel и myView. Не давно добавил возможность редактирования, с существующими значениями все хорошо,...

PYQT Вставить в ячейку QTableView произвольный виджет
Здравствуйте. Никак не могу понять, как вставить свой виджет отображения в ячейку QTableView. Есть назначение делегатов, но это...

Разница между PyQT 5 и PyQT 6
Добрый день, форумчане. Прошел тут курс всеми вами любимого автора, познакомился с GUI TKinter, и по вашим советам решил освоить PyQT. ...

60
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
03.01.2019, 07:40  [ТС]
Студворк — интернет-сервис помощи студентам
А посмотрите, пожалуйста, в чем ошибка при работе с делегатами. Хочу научиться. Делала по книжке. Вот класс делегата:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, options, index):
        # Компонент-редактор, используемый для правки значений количества позиций
        editor=QtWidgets.QSpinBox(parent)
        editor.setFrame(False)
        editor.setMinimum(1)
        editor.setMaximum(5)
        editor.setSingleStep(1)
        return editor
    def setEditorData(self, editor, index):
        # Заносим в компонент редактор значение количества
        value = int(index.model().data(index, QtCore.Qt.EditRole))
        editor.setValue(value)
    def updateEditorGeometry(self, editor, options, index):
        # Указываем размеры компонента-редактора
        editor.SetGeometry(options.rect)
    def setModelData(self, editor, model, index):
        # Заносим исправленное значение количества в модель
        value = str(editor.value())
        model.setData(index, value, QtCore.Qt.EditRole)
Вот так используется класс MyDelegate в функции __init__ класса MyWin
Python
1
2
3
4
5
6
7
8
9
class MyWin(QWidget):
    def __init__(self, data=None, parent=None):
        super().__init__()
        self.model = QStandardItemModel() # модель
        self.model.setHorizontalHeaderLabels(['Delegate', 'x', 'y(x)', 'sum(y)', 'Red-Green']) # заголовки модели
        self.table = QTableView() # таблица
        self.table.setModel(self.model) # передача модели в таблицу
        ..............................................................................
        self.table.setItemDelegateForColumn(0, MyDelegate())  # делегат в первом столбце таблицы
Вот главная функция:
Python
1
2
3
4
5
6
if __name__ == "__main__":
    app = QApplication([])
    myapp = MyWin(mass)
    myapp.setWindowTitle("Таблица и график")  # Заголовок окна
    myapp.show()
    app.exec_()
Когда запускаю и редактирую первый столбец таблицы, пишет: Прекращена работа Python.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
03.01.2019, 15:31
https://github.com/baoboa/pyqt... elegate.py

Добавлено через 23 секунды
тут много примеров

Добавлено через 50 минут
Цитата Сообщение от Simply me Посмотреть сообщение
Когда запускаю и редактирую первый столбец таблицы, пишет: Прекращена работа Python.
в консоли смотрите ошибки. у вас синтаксис и импорты
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
05.01.2019, 20:18  [ТС]
Спасибо) но я всё-таки не совсем понимаю, в чем принципиальная разница между этим кодом, моим кодом и кодом из книжки. Хочу научиться, а не просто заменять свой неработающий код на чужой работающий.

Добавлено через 2 минуты
В консоли у меня в pycharm почему-то пишет только с каким кодом выполнилось. Если не ноль, то ошибка.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
06.01.2019, 07:29
запускайте из терминала
Bash
1
python -v my_script
пайчарм не пользуюсь, для освоения вам вполне Geany хватит
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 08:38
КМК вы пытаетесь редактировать пустую модель, поэтому и вылетает
В PyQt5 ошибки Qt можно только в консоли увидеть. УМВР
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#/usr/local/bin/python3
 
from PyQt5.QtWidgets import (QApplication, QWidget, QTableView, QPushButton,
QStyledItemDelegate,QDoubleSpinBox, QMenu)
from PyQt5.QtGui import QFont,QColor
from PyQt5.QtCore import (Qt, QAbstractTableModel, QModelIndex, QAbstractItemModel)
 
import numpy as np
 
class NpModel(QAbstractTableModel):
    def __init__(self, data = np.array([[]]), parent=None):
        super().__init__()
        self.npdata = data
        
    def rowCount(self,index=QModelIndex()):
        return len(self.npdata)
        
    def columnCount(self,index=QModelIndex()):
        return len(self.npdata[0])
    
    def data(self,index,role):
        if not index.isValid(): return None
        row = index.row()
        col = index.column()
        val = self.npdata[row,col]
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return str(round(val,3))
        elif role == Qt.BackgroundRole:
            if col == 0: return QColor(0,0,0,8)
                        
    def flags(self,index):
        if not index.isValid(): return Qt.ItemIsEnabled
        if index.column() == 0:
            return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
        return Qt.ItemIsEnabled | Qt.ItemIsEditable
        
    def setData(self,index,value,role):
        if not index.isValid():
             return False
        if role == Qt.EditRole:
            try : f = float(value.replace(',','.'))
            except: return False
            self.npdata[index.row(),index.column()] = f
            self.dataChanged.emit(index,index)
            return True
        return False
 
    def headerData(self,section,orientation,role):
        if role != Qt.DisplayRole: return None
        if orientation == Qt.Horizontal:
            return 'Col:' + str(section + 1)
        else: return str(section + 1)
        
    def load(self,arr):
        self.beginResetModel()
        self.npdata = arr
        self.endResetModel()
        
class SpinDelegate(QStyledItemDelegate):
    def createEditor(self, parent, options, index):
        editor = QDoubleSpinBox(parent)
        editor.setFrame(False)
        editor.setRange(1,5)
        editor.setSingleStep(1)
        return editor
        
    def setEditorData(self, editor, index):
        value = index.model().data(index, Qt.EditRole)
        editor.setValue(float(value))
        
    def updateEditorGeometry(self, editor, options, index):
        editor.setGeometry(options.rect)
    
    def setModelData(self, editor, model, index):
        value = str(editor.value())
        model.setData(index, value, Qt.EditRole)
        
 
class NpView(QTableView):
    def __init__(self,parent=None):
        super().__init__()
        self.horizontalHeader().setSectionResizeMode(1)
        self.setSelectionMode(1)
        self.viewport().setAttribute(Qt.WA_StaticContents)
 
        
    def keyPressEvent(self,e):
        if e.key() == Qt.Key_Escape:
            self.clearSelection()
        
    def contextMenuEvent(self,e):
        pos = self.mapToGlobal(e.pos())
        mnu = QMenu()
        mnu.addAction('Cancel').setObjectName('cancel')
        mnu.addSeparator()
        mnu.addAction('Div').setObjectName('div')
        mnu.addSeparator()
        mnu.addAction('Mul').setObjectName('mul')
        ret  = mnu.exec_(pos)
        if ret:
            obj = ret.objectName()
            if obj == 'cancel':
                self.clearSelection()
                return
            rows = [i.row() for i in self.selectedIndexes()]
            if obj == 'div':
                for i in rows:
                    model.npdata[i,1:] /= model.npdata[i,0]
            elif obj == 'mul':
                for i in rows:
                    model.npdata[i,1:] *= model.npdata[i,0]
            self.model().layoutChanged.emit()
 
if __name__ == "__main__":
    app = QApplication([])
    l = np.arange(1,31,dtype=float).reshape(5,6)
    l[:,0] = 1
    model = NpModel(l)
    w = NpView()
    w.setItemDelegateForColumn(0,SpinDelegate())
    w.setModel(model)
    w.setFont(QFont('Times',16))
    w.resize(600,400)
    w.show()
    app.exec_()
Добавлено через 2 часа 25 минут
ДЛЯ ПРАКТИКИ- найдите ошибку
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
07.01.2019, 09:04  [ТС]
Цитата Сообщение от vic5710 Посмотреть сообщение
КМК вы пытаетесь редактировать пустую модель
Вроде не пустая модель. Таблица заполнена числами. И все столбцы, кроме того, которому присвоен делегат, нормально редактируются. а при редактировании первого столбца вылетает.

Запустила из терминала такой командой: python -v main. Вывел очень много текста. Первая часть вывода во вложении. Может, можно как-то запустить, чтобы только ошибки выводились?

Цитата Сообщение от vic5710 Посмотреть сообщение
ДЛЯ ПРАКТИКИ- найдите ошибку
Лучше Вы в моем коде
Миниатюры
Pyqt. Класс QTableView  
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 09:20
Цитата Сообщение от Simply me Посмотреть сообщение
чтобы только ошибки выводились?
Bash
1
python myscript
Добавлено через 56 секунд
Цитата Сообщение от Simply me Посмотреть сообщение
Лучше Вы в моем коде
я то найду, но сами писать так вы не научитесь
1
07.01.2019, 09:23  [ТС]

Не по теме:

Ну сложно начинать с разбора 100 строчек не своего кода)

0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 09:25
покажите весь код
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
07.01.2019, 09:36  [ТС]
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import sys
# Импорт numpy
import numpy
# Импорт интерфейса
from test import *
 
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QTableView, QWidget, QGridLayout, QPushButton, QTreeView, QListView, QSpinBox
from PyQt5.QtGui import QStandardItemModel, QStandardItem
 
# Массив значений
mass = numpy.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], int)
 
 
# Класс делегата
class MyDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, options, index):
        # Компонент-редактор, используемый для правки значений количества позиций
        editor=QtWidgets.QSpinBox(parent)
        editor.setFrame(False)
        editor.setMinimum(1)
        editor.setMaximum(5)
        editor.setSingleStep(1)
        return editor
    def setEditorData(self, editor, index):
        # Заносим в компонент редактор значение количества
        value = int(index.model().data(index, QtCore.Qt.EditRole))
        editor.setValue(value)
    def updateEditorGeometry(self, editor, options, index):
        # Указываем размеры компонента-редактора
        editor.SetGeometry(options.rect)
    def setModelData(self, editor, model, index):
        # Заносим исправленное значение количества в модель
        value = str(editor.value())
        model.setData(index, value, QtCore.Qt.EditRole)
 
 
class MyWin(QWidget):
    def __init__(self, data=None, parent=None):
        super().__init__()
        self.model = QStandardItemModel() # модель
        self.model.setHorizontalHeaderLabels(['Delegate', 'x', 'y(x)', 'sum(y)', 'Red-Green']) # заголовки модели
        self.table = QTableView() # таблица
        self.table.setModel(self.model) # передача модели в таблицу
        self.table.horizontalHeader().setSectionResizeMode(1) # размер таблицы по содержимому
        self.btnLoad = QPushButton("Load") # кнопка загрузки данных
        #self.btnCalc = QPushButton("Calc") # кнопка расчета
        #self.btnGet = QPushButton('Get') # кнопка расчета
        self.btnLoad.clicked.connect(self.load_data)
        #self.btnCalc.clicked.connect(self.calc)
        #self.btnGet.clicked.connect(self.get_data)
        grid = QGridLayout(self)
        grid.setContentsMargins(1, 1, 1, 1)
        grid.addWidget(self.table, 0, 0, 4, 4)
        grid.addWidget(self.btnLoad, 4, 0, 1, 1)
        #grid.addWidget(self.btnCalc, 4, 1, 1, 1)
        #grid.addWidget(self.btnGet, 4, 3, 1, 1)
        self.data = data
        self.table.setItemDelegateForColumn(0, MyDelegate())  # делегат в первом столбце таблицы
 
    def load_data(self):
        rows = len(self.data)
        cols = len(self.data[0])
        for row in range(rows):
            for col in range(cols):
                item = QStandardItem(str(self.data[row][col]))
                self.model.setItem(row, col, item)
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    myapp = MyWin(mass)
    myapp.setWindowTitle("Таблица и график")  # Заголовок окна
    myapp.show()
    app.exec_()
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 09:47
ну и где данные?
Миниатюры
Pyqt. Класс QTableView  
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 09:50
Bash
1
2
3
4
  File "t.py", line 31, in updateEditorGeometry
    editor.SetGeometry(options.rect)
AttributeError: 'QSpinBox' object has no attribute 'SetGeometry'
Abort trap: 6
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
07.01.2019, 10:00  [ТС]
Данные будут, если на кнопку load нажать. Вообще они в переменной mass. Они передаются в экземпляр класса MyWin. Как я понимаю.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 10:02
я вам уже ошибку показал
1
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
07.01.2019, 10:33  [ТС]
Спасибо, действительно у класса QSpinBox нет свойства setGeometry. Хотя во всех просмотренных мной примерах создания делегата используется это свойство этого класса. Наверное, с версией связано. Подумаю, как по-другому задать размер делегата.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
07.01.2019, 10:55
Цитата Сообщение от Simply me Посмотреть сообщение
Спасибо, действительно у класса QSpinBox нет свойства setGeometry. Хотя во всех просмотренных мной примерах создания делегата используется это свойство этого класса. Наверное, с версией связано. Подумаю, как по-другому задать размер делегата.
вы серьезно?
https://github.com/baoboa/pyqt... elegate.py
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
08.01.2019, 07:43  [ТС]
Серьезно. В коде по ссылке тоже используется свойство setGeometry класса QSpinBox
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
08.01.2019, 08:02
а не проще писать без ошибок?
Цитата Сообщение от vic5710 Посмотреть сообщение
editor.SetGeometry(options.rect)
Цитата Сообщение от vic5710 Посмотреть сообщение
editor.setGeometry(options.rect)
1
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
08.01.2019, 08:05  [ТС]
Спасибо! Не заметила)))
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
12.01.2019, 09:15  [ТС]
vic5710, а можно поспрашивать по коду из сообщения 19?

1. Метод headerData класса NpModel, по-моему, нигде не вызывается. Но заголовки подписываются. Почему так?
2. Зачем beginResetModel, endResetModel, layoutChanged.emit? emit - это вроде имитация события.
3. Где запрещается редактирование ячеек пользователем?

В моем коде пользователь может редактировать ячейки. Но введенные значения не попадают в модель. Функция calc считает по изначально загруженным значениям. А если расскомментировать эту строчку, то программа вылетает:
Python
1
self.model.itemChanged.connect(self.calc)
Вот функция calc
Python
1
2
3
4
5
6
7
8
9
10
def calc(self):
        # пересчет значений 3 столбца из значений 2 столбца
        # в 4 столбце накопленные значения из 3 столбца
        for i in range(len(self.data)):
            self.data[i][2] = 100 * self.data[i][1]
            self.load_data()
            self.data[0][3] = self.data[0][2]
            for i in range(1, len(self.data)):
                self.data[i][3] = self.data[i - 1][3] + self.data[i][2]
            self.load_data()
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.01.2019, 09:15
Помогаю со студенческими работами здесь

Из QT в PyQt
Здравствуйте, подскажите правильно ли у меня получился перевод из QT в PyQt? Интересует именно выполнение класса QCoreApplication и...

PyQt, Qt и ScrollArea
Доброй ночи. В этот раз кода не будет, так как клин. Из русскоязычных мануалов по PyQt только Прохоренок, которого все хаят (а...

PyQt + PyCharm
Как подключить PyQT5 к pycharm 4.5.3 ? python 3.4

PyQt и Spyder 3
Доброго времени суток! Возyикает проблема после установки PyQt - перестает запускаться Spyder 3, никаких ошибок, ничего. Запускаешь IDE,...

Paint pyqt
Добрый вечер, помогите разобраться с кодом я в Python (pyqt, Desinger) новичок. Можете обяснить по подробнее с "Class Canvas"...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru