Python и PyQt обзор виджета QTableWidget и практическое использование
Vložit
- čas přidán 10. 05. 2018
- Python и PyQt, в этом видео рассказываю, что из себя представляет класс QTableWidget и как эффективно его использовать. В видео привожу теорию и практику использования QTableWidget в программах на Python. Показываю как настроить внешний вид таблицы с помощью стилей qss, загрузить данные в таблицу, настроить заголовки рядов и столбцов. Управлять данными в таблице с целью использования в других частях программы. В завершении видео демонстрирую практическое использование таблицы в программе для отображения данных на графике (диаграмма рассеяния).
Подробнее на Портале: PyScientist
pyscientist.ucoz.net
www.lfd.uci.edu/~gohlke/pytho... - ссылка на библиотеку PyQt4 которая вам понадобится для работы, она включает в себя QTableWidget;
doc.qt.io/archives/qt-4.8/styl... - ссылка на документацию по стилям Qt;
doc.qt.io/qt-5/qtablewidget.html - ссылка на документацию по классу QTableWidget (родная Qt);
srinikom.github.io/pyside-doc... - ссылка на документацию по классу QTableWidget(PySide).
В случае если Вам необходимо получить пароль от архива с материалами к видео:
pyscientist.ucoz.net/load/arkh...
прошу Вас писать мне запрос на e-mail: sergei-dmitriev@mail.ru.
Это просто формальность, чтобы мой код не распространялся бесконтрольно.
Если У вас есть какие либо вопросы по видео, либо по работе программы, любые приложения по сотрудничеству буду рад Вам помочь, пожалуйста обращайтесь на мою почту sergei-dmitriev@mail.ru либо пишите Ваши предложения в комментариях
Ссылки на предыдущие видео по теме:
Видео 1: Python настройка рабочего пространства, использование PyCharm
• Python и PyCharm(IDE) ...
Видео 2: Python функции
• Python функции tutoria...
Видео 3: Python классы
• Python и классы на при...
Видео 4: Графический интерфейс Qt для Python, или PyQt
• Python и Qt библиотека...
Видео 5: Python компиляция программ, cx_Freeze и другие компиляторы
• Python exe tutorial ко...
Видео 6.1: Библиотека Matplotlib создание графиков для анализа данных
• Python Matplotlib граф...
Видео 6.2: Библиотека matplotlib и Qt встраивание графиков в графический интерфейс Qt
• Python и Matplotlib py...
Видео 7: Matplotlib модуль Animation класс FuncAnimation (автообновление графиков)
• Python и Matplotlib мо...
Видео 8: Библиотека Matplotlib, отображение графиков функции с использованием библиотеки numexpr (ввод функции из текстовой строки)
• Python и Matplotlib py...
Видео 9.1: Классы QListWidget и QListView сопоставительный анализ, простой пример применения QListWidget
• Python и PyQt (QListWi...
Видео 9.2: Класс QListView пример применения с использованием QtCore.QabstractListModel
• Python PyQt и QListV...
Видео 10: Python и Excel взаимодействие с excel (библиотеки xlrd, xlwt, openpyxl, win32com)
• Python и Excel (библио...
Очень хороший видеоурок, спасибо вам большое
Благодарю за урок, все понятно
Спасибо за урок! Очень помогло)
Спасибо, хороший урок.
What do you mean, what is flixzone?
Спасибо! Всё по существу.
Спасибо за урок! В интернете не так много актуальной обучающей информации по Python, PyQt5 особенно для научных целей
Да к сожалению на русском не много, на английском существенно больше. Если будут вопросы по конкретной тематике, то задавайте, буду рад помочь.
Кратко и понятно
Отличный урок. Покажите вывод в таблицу данных из БД, например, из sqlite, а также как можно эти данные редактировать в таблице и обновлять в бд. Ещё интересует как сделать, чтобы при щелчке мышью в ячейке там появлялся combobox, заполненный значениями из другой таблицы, типа, сделать, чтобы в определённые ячейки можно было вставлять только определённые значения из combobox. И покажите ещё, как правильно из одного окна вызывать другое и передавать между ними значения.
Про sqlite расскажу в ближайшее время 13 видео, с сигналами и слотами также по плану было 20 но по вашей просьбе перенесу на пораньше. В 15 расскажу про окна и их взаимодействие между собой.
Спасибо за внимание и Ваши комментарии.
Отличное видео, ай молодца. В самом конце видео "миу" улыбнуло - это звуковой эффект или питомец? ))
Ага секретный питомец)
def prepare_one_row_data(row_name, table):
#Подготовка данных одного столбца из табличного виджета по имени ряда
column_container = [] # создаем пустой контейнер для ряда
for column in range(0, table.columnCount()): #Цикл перебор имен в шапке
column_name = table.horizontalHeaderItem(column).text()
if column_name == row_name:
y = column #Присвоение номера колонки
try:
for x in range(0, table.rowCount()): # перебираем ряды
column_container.append(table.item(x, y).text())
return column_container
except:
return column_container
def prepare_two_row_data(x_row_name, y_row_name, table):
column_one_container = []
column_two_container = []
for column in range(0, table.columnCount()): #Цикл перебор имен в шапке
column_name = table.horizontalHeaderItem(column).text()
if column_name == x_row_name:
y = column #Присвоение номера колонки для первой переменной
if column_name == y_row_name:
z = column #Присвоение номера колонки для второй переменной
try:
for x in range(0, table.rowCount()): # перебираем ряды складируем колонку с первым индексом в список
column_one_container.append(table.item(x, y).text())
for x in range(0, table.rowCount()): # перебираем ряды складируем колонку с вторым индексом в список
column_two_container.append(table.item(x, z).text())
return column_one_container, column_two_container
except:
return column_one_container, column_two_container
Привет. Спасибо за видео. Но не понял. В таблицу INT нельзя передавать ? Только str() ? Просто сортировка в таком видео очень плохая.
Да все правильно в данном видео таблица сортирует только с учетом символов. Если хотите использовать QTableWidget то можно искусственно сделать в сортируемом столбце все значения одной длинны дополнив их пробелами с начала.... но это конечно химия, а вообще рекомендую Вам QTableView для таких целей, но тут быстро не ответишь и это тема отдельного видео с соответствующим кодом.
Если самостоятельно не получится разобраться то попробую Вам помочь, пишите!
Добрый день! Подскажите пожалуйста: Как настроить ширину колонки, т.е сделать разную фиксированную ширину для колонок. Не подстроить под содержимое, а именно фиксированную ширину, для каждой колонки разную. Буду благодарен за любую помощь!
Попробуйте почитать про это QTableWidgetItem.setSizeHint(), установка размера итема! Если поменять скажем первый итем в колонке, то и вся колонка должна стать такой-же ширины.
@@PyScientist self.tableWidget.setColumnWidth(column number, width) всё оказалось куда проще. Сам не понимаю почему очень долго не мог найти ответ в Интернете.
Здравствуйте, подскажите пожалуйста на Вашем сайте какой из архивов проекта является последней версией? В видео вы показываете версию 2.0.2, но в то же время говорите о версии 2.0.3, подскажите можно ли посмотреть весь код программы? Она есть в архиве? Для получения пароля еще актуально писать Вам на почту? Можете еще рассказать подробнее про таблицы, а именно работа с заголовками таблицы, если требуется объединить несколько столбцов в один но только в заголовке, или строке. А также как строить график , в котором можно заполнять на определенных промежутках по вертикали (данные по разрезу скважины) каким-нибудь паттерном? Тем самым представляя графическую характеристику(песчаник,глины.. и т.д.)(литология)
За паролем, да на почту. Крайняя версия на сайте. можно посмотреть. По вопросам. Можно. Но это тема отдельного разговора.
Добрый день! Подскажите пожалуйста, как изменить шапку таблицы(т.е. 1,2,3 стандартные и тд на например названия столбцов "Фио", "Телефон" и тп) ? и как для строк?
Добрый день, оч просто.
TableWidget.setHorizontalHeaderLabels(['имя','фамилия'])
@@PyScientist а если я ещё не знаю заранее, сколько у меня будет столбцов(зависит от значения слайдера) , а хочется чтобы столбцы назывались a1,
a2, ... an то как вы посоветуете это сделать?
Для каждого положения слайдера запускать ту же функцию, на вход список с названиями
@@PyScientist спасибо)
f откуда взять def main_application, откуда его скопировали Вы?
Из программы которую до этого писал, можно вот отсюда взять
pyscientist.ucoz.net/index/video_11_qtablewidget/0-14
а если я хочу, что бы пользователь по мере заполнения таблицы сам называл колонки и если нужно добавлял по 1му ряду по мере необходимости?
Спасибо за уроки.
Но по теме есть вопрос.
Суть в том что в основном все видосы по теме заполнения таблиц идут от изначального написания кода и затем просмотра что же получилось с интерфейсом программы в натуре и следующей подгонкой по эстетике с исправлением кода.
Я пошел от обратного. В QtDesigner слепил интерфейс (десяток кнопок, большое окно лайнэдит, и окно таблвиджет) . В том же дизайнере изначально проименовал кнопки и задал в таблице количество столбцов и строк и их имена. Окончательный проект
( Ui ) переформатирован в ( py) и благополучно открыт в IDLE для дальнейшей работы с кодом. Т.е. добрая портянка кода была написана программой QtDesigner. Далее в питоне я благополучно прописал вывод текста от кнопок на лайнэдит, но суть в том что от нажатия кнопки, на лайнэдит должен идти определённый текст, а вот в таблвиджет совершенно другая (database) инфа. И на этом я чота заглючил.... пересмотрел кучу уроков, копипастил до пробела, но таблвиджет мертвый.
Это вообще мой первый опыт в написании кода, учусь по видосам.
Возможно есть нюанс по моей проблеме - в смысле изначально использован ку_дизайнер и потом уже работа в питоне...мож там ближайшие родственники не прописались автоматом или.... ну я ж впервОй...
версия питона 3.8.5
Буду рад помощи и общению по теме.
Вы же можете в основном окне любой виджет найти по его имени. Этот параметр называется objectName. Смотрите в qtdesigner справа, где свойства.
К нему можно обратиться "имя экземпляра основного окна"."имя виджета". Если я правильно понял вашу проблему.
Решили проблему?
@@PyScientist
Спасибо за участие.
С дизайнером проблем нет. Как раз таки дизайнер оказался более доступен к освоению. Т.е. посмотрев пару видосов от хауди хо и какого-то индийца вопросов к дизайнеру по сути не осталось.
В дизайннере окончательно был сформирован интерфейс будущей проги ( т.е. бэкграундколор всего чего хотелось, шрифты, тексты, окна и кнопки на своих местах) и ! - в дизайнере была сформирована tableWidget с количеством строк и столбцов и заданы имена столбцам.
Проект конвертирован (Ui > Py). Открыт в идоле. И там всё собраное в дизайнере присутствует.
я прописываю вывод текста на лайн эдит с кнопки
# puchbatton in textedit
def bp():
ui.textEdit.setText( " Кнопка 1 Внесено в базу. " )
ui.pushButton.clicked.connect( bp )
и оно работает. работают все кнопки , т.е к этой части кода вопросов пока нет.
Но с этой же кнопки на tableWidget должно уйти и сохраниться со сдвигом вниз инфа типа
id - 0000001. data 1- xx123xx. data2 - zz123zz. time - 11/22/33 (как время туда загнать ещё нигде не видел)
Вот здесь мой мосх уже не асиливает.
Т.е я честно копирую ваш код, неумеючи пытаюсь привязать его к кнопке и ничего не происходит....
# pushbutton data in base table
bd = sqlite3.connect( ' tableWidget ' )
sql = bd.cursor()
a = QtGui.QTableWidgetItem( ' ide ' )
b = QtGui.QTableWidgetItem( ' xx123xx ' )
c = QtGui.QTableWidgetItem( ' zz123zz ' )
d = QtGui.QTableWidgetItem( ' time ')
def bp():
self.QTableWidgetItem(0, ui.pushbutton, 0. d)
ui.pushButton.clicked.connect( bp )
И вот я весь в растеряных соплях уже даже не могу чётко сформировать свой вопрос
- Вы сначала пишите код затем смотрите что получилось. Т.е копируете библиотеки , указываете близких и дальних родственников.....мне СТРАШНО - яж их не знаю - яж ламер ваще поэтому и начал с дизайнера.
Дизайнер (надеюсь) подтянул всё что нужно, ошибок при открытии (ру) проекта нет - это наверное первый вопрос - ( а подтянул ли он что нужно?)
2 - я не пишу ту часть Вашего кода которую уже написал дизайнер
так - для примера;
self.pushButton_29.setFont(font)
self.pushButton_29.setStyleSheet("background-color: rgb(243, 243, 243);")
self.pushButton_29.setObjectName("pushButton_29")
self.textEdit = QtWidgets.QTextEdit(Dialog)
self.textEdit.setGeometry(QtCore.QRect(30, 20, 1021, 361))
self.textEdit.setStyleSheet("background-color: rgb(237, 255, 251);")
self.textEdit.setObjectName("textEdit")
self.tableWidget = QtWidgets.QTableWidget(Dialog)
self.tableWidget.setGeometry(QtCore.QRect(460, 410, 591, 241))
self.tableWidget.setStyleSheet("background-color: rgb(240, 255, 229);")
self.tableWidget.setRowCount(1000000)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
т.е дизайнер написал огромную часть кода за меня и без ошибок.
И видимо на этой стадии возникает моя проблема - кнопка не коннектица с таблицей.
Понятно что вникать в мой бред ,,нисмишно,,
- может видос?
Резюмируя) вы хотите а табличку вставить кнопку? Да?
@@PyScientist
нет. куча кнопок есть , инфа от кнопки постоянное значение но емкое, писать его займёт много времени поэтому применена кнопка . с кнопки в базу ( tableWidget) и должна инфа уходить без потери времени.
ну типа - кнопка 1 нажалась - на лайнэдит пошёл текст ,, дед повесился,, а в tableWidget должна пойти инфа - id процесса 000001, опять самоубийство через повешение, процент повешений превышает количество оставшихся в живых дедов, подать команду на ограничение продаж мыла и верёвок и снизить цену на газ - пусть травяца, время процесса 11,22,33.
Использую qt designer, никак не могу настроить цвет ячеек в названии колонок и строк. Весь Table Widget окрашивается в нужный мне цвет кроме column и row
Делаю курсач и застрял на этом моменте
Вы оперируйте item
Можно задать свойства им как в css
Использую версию интерпретатора 3.7.1, библиотеку PyQt5 Одна маленькая особенность - внутри "QtGui" не находит "QTableWidgetItem"
Он в pyqt5.qtwidgets с 5й версии
@@PyScientist QtWidgets.QTableWidgetItem - есть
Было бы интересно узнать о создании нод в PyQt czcams.com/video/t32smf6ZlTU/video.html по этой теме вообще практически пусто в сети
Был в легком отпуске, посмотрим, что можно показать по этой теме!
Посмотрел тематику нод в pyqt, к сожалению на данный момент тема слабо связана с основными направлениями и требует предварительной подготовки. Тема несомненно интересна буду иметь в виду эти возможности, ранее с ними не сталкивался при случае расскажу как и где возможно применение. Но могу констатировать, что в ближайшее время этого видео не планирую. Может у Вас есть мысли по применению данного средства визуализации?
Ноды широко используются в сфере компьютерной графики, видео композинга , 3д моделирования, процедурного текстурирования ... Ноды позволяют более гибко использовать функционал программы с визуальным графическим представлением, в ноды можно заключать функции, классы, структуры данных со своими настройками соединяя их между собой позволяя пользователю самому выстраивать функционал в зависимости от задачи и имеющимся набором нод, по сути это визуальное программирование без написания кода и использоваться может где угодно.
Да, на примере работы с графикой видел как используется. Есть некоторые примеры, в частности, библиотека nuke. Задача интересная. К тому же у меня есть некоторые контакты по графическоиу дизайну. Постараюсь разобратся и осознать тему. Спасибо Вам за участие и подробный ответ.
я работаю на тв художником комп графики, если что по графике интересует могу помочь, а nuke это программа видео композинга в ней хорошо реализован питон
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------QTableWidgetExample.py-----------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QApplication, QMainWindow
def get_items_from_header(TableWidget):
# Функция для получения элементов заголовков колонок QTableWidget
headers = []
for column in range(0, TableWidget.columnCount()): # Цикл перебора имен в шапке таблицы
column_name = TableWidget.horizontalHeaderItem(column).text() #Получение текстового значения из заголовка колонки
headers.append(column_name)
return headers
def get_items_from_row_names(TableWidget):
# Функция для получения элементов заголовков рядов QTableWidget
rows_names = []
for row in range(0, TableWidget.rowCount()): # Цикл перебора имен в заголовках рядов
row_name = TableWidget.verticalHeaderItem(row).text() #Получение текстового значения из заголовка ряда
rows_names.append(row_name)
return rows_names
class Ui_QTableWidgetWindow(object): #QTableWidget User Interface
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(450, 450) # устанавливаем размер основного окна
self.centralWidget = QtGui.QWidget(MainWindow) # добавляем центральный виджет
self.centralWidget.resize(400,400) # устанавливаем размер центрального виджета
vbox = QtGui.QVBoxLayout(self.centralWidget) #Создаем вертикальное размещение
self.TableWidget=QtGui.QTableWidget() #Инициализируем таблицу
vbox.addWidget(self.TableWidget) #Добавляем таблицу в размещение
self.TableWidget.setColumnCount(3) #Устанавливаем количество колонок равное 3-м для таблицы
self.TableWidget.setRowCount(3) #Устанавливаем количество рядов равное 3-м для таблицы
a = QtGui.QTableWidgetItem(100) #Работать не будет, на вход нужно подавать строку
b = QtGui.QTableWidgetItem(str(100)) #Передача числа в объект итем Widget
c = QtGui.QTableWidgetItem('rrr') #Передача символов в объект итем Widget
self.TableWidget.setItem(0, 0, a) #установка экземпляра QTableWidgetItem в первый столбец первый ряд
self.TableWidget.setItem(0, 1, b) #установка экземпляра QTableWidgetItem в второй столбец первую ряд
self.TableWidget.setItem(1, 1, c) #установка экземпляра QTableWidgetItem в второй столбец второй ряд
button = QtGui.QPushButton()
button.setText('Кнопка')
combobox = QtGui.QComboBox()
self.TableWidget.setCellWidget(1, 2, button)
self.TableWidget.setCellWidget(2, 2, combobox)
self.column_label =['column one', 'column tow', 'column three']
self.row_label = ['row one', 'row tow', 'row three']
self.TableWidget.setHorizontalHeaderLabels(self.column_label) #устанавливаем заголовки для колонок
self.TableWidget.setVerticalHeaderLabels(self.row_label) #устанавливаем заголовки для рядов
self.TableWidget.setSortingEnabled(True) #включаем возможность сортировки для рядов
#Устанавливаем стили для таблицы
# Подготавливаем необходимый нам стиль (для управления стилями используется синтаксис css)
style = '''
QTableWidget::item {background-color: white;
border-style: outset;
border-width: 3px; border-radius: 7px; border-color: green}
QTableWidget::item:selected {background-color: red;
border-width: 5px; border-radius: 7px; color: green; border-color: blue}
'''
# Применяем стили к основному окну программы от которого все наследуется
self.setStyleSheet(style)
# Получаем заголовки колонок и рядов таблицы QTableWidget
headers = get_items_from_header(self.TableWidget)
rows_names = get_items_from_row_names(self.TableWidget)
print(headers, rows_names)
self.TableWidget.clear() #Удаляем все содержимое таблицы
self.TableWidget.clearContents() #Удаляем все содержимое ячеек (заголовки рядов и столюцов остаются)
class MainWindow(QMainWindow, Ui_QTableWidgetWindow):
def __init__(self, parent=None, *args, **kwargs):
QMainWindow.__init__(self)
#Настройка основного GUI
self.setupUi(self)
def main_application():
'''
функция для инициализации и отображения нашего основного окна приложения
'''
# Класс QApplication руководит управляющей логикой ГПИ и основными настройками.
# Здеь мы создаем экземпляр класса QAplication передавая ему аргументы из коммандной строки.
app = QApplication(sys.argv) # где sys.argv список аргументов командной строки, передаваемых сценарию Python.
app.setStyle('cleanlooks')
# Здсь мы создаем экземпляр класса MainWindow.
main = MainWindow()
main.show()
# Метод show() отображает виджет на экране.Виджет сначала создаётся в памяти, и
# только потом(с помощью метода show) показывается на экране.
sys.exit(app.exec_())
# exec_ запускает цикл обработки сообщений
# и ждет, пока не будет вызвана exit() или не
# будет разрушен главный виджет, и возвращает значение установленное в exit().
# Здесь sys.exit обеспечивает чистый выход из приложения.
#Исполнение основной функции
if __name__ == '__main__':
main_application()
Подскажите а можно ли использовать css стили для одной отдельно взятой ячейки в таблице?
Да конечно, нужно применить стиль к QTableWidgetitem ссылку на него можно получить по ряду и столбцу таблицы.
@@PyScientist Да я так пробовала только QTableWidgetitem применяется почему то ко всем ячейкам. Вот например в qt прописываю вот так QTableWidget::item {
background-color: rgb(255, 0, 0);} и закрашиваются все ячейки
@@PyScientist А если например указать вот так ячейку QTableWidget::item(1,0) то ничего не происходит
@@hazymyma Последний стиль не сработает он некорректно записан.
С помощью стилей внешний вид одной ячейки не настраивается по ряду причин, например, вы хотите изменить толщину границы, тогда другие ячейки фактически ломаются, поэтому для ячеек в отдельности такого нет. Это можно организовать через делегата, но это на пальцах трудно объяснить. В вашем случае возможно воспользоваться стандартными установщиками свойств для итема.
например
def modify_cell(cell):
text_color = QColor(0,255,0)
cell.setForeground(text_color)
fill_color = QColor(0,23,60)
cell.setBackground(fill_color)
далее запускаем функцию на нужную ячейку
modify_cell(TableWidget.item(row, column))
Для более сложных заливок можно обратится к QBrush вместо QColor