# у меня python версии 3.5
# pyqt - 5-ой версии.
## Минимальная затравка для запуска кода :
# coding=UTF8
# это чтобы можно было переменные по русски называть.
# обязательно при этом сохранять py фаил в UTF
# импорты:
import sys
from PyQt5.Qt import QApplication, QPushButton, QFileDialog,\
QTableWidget, QTableWidgetItem, QGridLayout, QWidget, pyqtSignal
app = QApplication([])
# ну а теперь будем мудрить. Честно говоря ваш уровень
# владения python-м совсем не ясен. Потому начнём с супер нуля.
# None и pass - обозначают пустату (т.е. ничто).
# Она нам понадобится в дальнейшем :).
кнопка = None # надеюсь понятия переменные
# обьяснять не надо. Кнопку назовём кнопка.
# КЭП уплывёт, а кнопка останется в памяти интерпретатора.
# для начало нам нужно знать что всё что отображается
# на экране это какие то объекты, а не их описание.
class open_kn(QPushButton): pass # - это описание.
# Оно как ДНК для будущего ребёнка,
# но при этом само ребёнком не является.
# детки создаются как-то так:
open_kn() # - это создание экземпляра класса.
# Мы как бы говорим интерпретатору что хотим "породить"
# один экземпляр всего того что описано в "ДНК" open_kn.
# при этом обычно выполняются все инструкции в нутри
# конструктора класса (это тот который def __init__)
# но у нас пока что такой метод не назначен поэтому
# "ребёнок" просто унаследует всё что есть в QPushButton
# но созданный экземпляр как и КЭП появившись и
# пояснив компьютеру что мы от него хотим сразу самовыпиливается.
# поэтому нам нужна переменная для его хранения:
кнопка = open_kn() # кнопка - наш ребёнок, а open_kn - наше ДНК.
# так нам надо ещё сделать на ней текст и заставить отрисовыватся на экране:
# вообще эти два метода могли быть и в конструкторе :
class open_kn(QPushButton):
def __init__(self):
# а кстати да - методы создаются именно через
# def %название_метода%(аргументы):
self.setText('Open') # устанавливаем текст на кнопке
# но всё это нафиг не нужно если в вашем классе всего
# один метод, и тот конструктор -
# тогда зачем вам вообще такой класс?
кнопка = QPushButton()
кнопка.setText('Open')
def всё_что_будет_происходить_при_нажатии_на_кнопку():
# аналогично не обязательно переопределять целый класс FileDialog всего для одного метода...
# так с кнопкой разобрались. Теперь нам нужен диалог и таблица.
fileName = QFileDialog.getOpenFileName \
(кнопка, 'Простой пример', 'd:\\',"Текст (*.txt)")[0] # ваш код, не буду его коментировать.
f = open(fileName, 'r', encoding="utf8")
# я добавил encoding="utf8" потому что мои txt именно в таком формате
# кстати говоря именно ваши "try, except" и скрывают от вас настоящию ошибку.
# "Неожиданная ошибка:" - очень информативно...
# тут пока без изменеинй.
data = []
with f as f:
for i in f.readlines():
data.append(i)
# TableWidget.data = data # ага какой нафиг TableWidget когда мы его ещё не определили?
# впрочем х*@ с ним...
# вы же сами сказали что ваш table в HBox4 ? значит путь бедет примерно такой:
экземпляр_класса_HBox4.table.update(data) # мы просто напрямую вызываем нужный нам метод
# РИСУЕМ!
class TableWidget(QTableWidget):
# я немного переделал: сразу перенёс всю настройку таблици в метод update
def __init__(self, parent=None, data=[]):
super(TableWidget, self).__init__(parent)
self.update() # ну и чтобы не повторятся просто вызываю этот метод
def update(self, data=[]):
self.setColumnCount(1)
self.setRowCount(len(data))
for i, entry in enumerate(data, start=1): # у вас "нулевая" строка в txt
# - комментарий?
self.setRowCount(i)
item = QTableWidgetItem()
item.setText(str(entry))
self.setItem(i-1, 0, item) # - либо тут "-1" либо начинать с нулевого элемента,
# либо в setRowCount делать +1...
print(data) # - для отладки посмотрим: а вдруг данные всё таки передаются,
# а в таблицу не пишутся?
class HBox4(QGridLayout):
def __init__(self, parent=None):
super(HBox4, self).__init__(parent)
table = TableWidget() # - так не правильно.
# поясню: Вы только что создали переменную внутри метода.
# фишка в том что python по окончании метода
# забывает напроч обо всех созданных внутри него переменных. так-то.
self.table = TableWidget() # - так правильно. + мы сможем к нему обращятся.
self.addWidget(кнопка, 0, 0)
self.addWidget(self.table, 1, 0)
экземпляр_класса_HBox4 = HBox4()
# сам QGridLayout отображатся не умеет вне виджета
# я создам для него виджет.
widget = QWidget()
widget.setLayout(экземпляр_класса_HBox4)
widget.show() # пуф!..
# да мы забыли связать события нажатия на кнопку и наш метод:
кнопка.pressed.connect(всё_что_будет_происходить_при_нажатии_на_кнопку)
#В принципе на этом можно было бы и остановится,
# но в идеале было бы пользоватся сигналами и слотами:
# они вам понадобятся позже когда вы начнёте вызывать методы одновременно
# или например из потоков.
class TableWidget(QTableWidget):
my_signal_update = pyqtSignal(list) # придумываем сигнал my_signal_update
# (в качесте параметров он принимать будет list (там могло быть что угодно: int, str)
def __init__(self, parent=None, data=[]):
super(TableWidget, self).__init__(parent)
self.update()
self.my_signal_update.connect(self.update) # добавлено
def my_slot_update(self, data): # добавлено
print(data, flush=True) # добавлено
self.update() # добавлено
# ну а дальше без изменений.
def update(self, data=[]):
self.setColumnCount(1)
self.setRowCount(len(data))
for i, entry in enumerate(data, start=1):
self.setRowCount(i)
item = QTableWidgetItem()
item.setText(str(entry))
self.setItem(i-1, 0, item)
def всё_что_будет_происходить_при_нажатии_на_кнопку():
fileName = QFileDialog.getOpenFileName \
(кнопка, 'Пример с сигналом и слотом', 'd:\\', "Текст (*.txt)")[0]
f = open(fileName, 'r', encoding="utf8")
data = []
with f as f:
for i in f.readlines():
data.append(i)
table.my_signal_update.emit(data) # мы просто НЕ напрямую вызываем нужный нам метод...
кнопка.pressed.connect(всё_что_будет_происходить_при_нажатии_на_кнопку)
table = TableWidget()
экземпляр_класса_HBox4.addWidget(table, 2, 0)
# ну и последний кусочек для минимальнно рабочего приложения на pyqt
app.exec_() # без этого ничего не запустится...