Не работают сигналы, при исопльзовании QTabWidget
Странно работает QTabWidget, если не использовать его в классе MyTab, то будут пустые вкладки, если не использовать его в MainWindow.createCommonTab() то будет всё отрисовано но ничего не будет работать.
Но если я использую QTabWidget и там и там, то все работает, но отрисовывается ещё по одной пустой вкладке с повторяющися названием.
Где найти золотую серидину?
main.py
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import random
import string
import traceback
def log_uncaught_exceptions(ex_cls, ex, tb):
text = '{}: {}:\n'.format(ex_cls.__name__, ex)
text += ''.join(traceback.format_tb(tb))
print(text)
QMessageBox.critical(None, 'Error', text)
sys.exit(1)
sys.excepthook = log_uncaught_exceptions
def random_char(y):
return ''.join(random.choice(string.ascii_letters) for x in range(y))
class MyTab(QWidget):
about_time_update = pyqtSignal(str)
def __init__(self, name, init, rangeDevic, deviceName, tabWidget):
super().__init__()
# Создание Вкладки
self.tab = QWidget()
# Если избавиться от таб виджета то будут пустые вкладки ---------------1
self.tabWidget = tabWidget
self.tabWidget.addTab(self.tab, name)
# Всякое повторяющееся из вкладки во вкладку
self.validator = QIntValidator(0, 3600000, self.tab)
self.currentDisplayLable = QLabel('Текущее показание:', self.tab)
self.init = init
self.currentDisplayLineE = QLineEdit(''+self.init, self.tab)
self.currentDisplayLineE.setReadOnly(True)
self.timeToUpdateLable = QLabel('Период обновлений, мс:', self.tab)
self.timeToUpdateLineE = QLineEdit('100', self.tab)
self.timeToUpdateLineE.setValidator(self.validator)
self.rangeDeviceLable = QLabel('Диапазон:', self.tab)
self.rangeDeviceComboB = QComboBox(self.tab)
self.rangeDevice = rangeDevic
if type(self.rangeDevice) == str:
self.rangeDeviceComboB.addItem(self.rangeDevice)
else:
self.rangeDeviceComboB.addItems(self.rangeDevice)
self.lcdNumber = QLCDNumber(self.tab)
self.widgetsData = QWidget()
self.startPlotBtn = QPushButton('Старт', self.widgetsData)
self.pausePlotBtn = QPushButton('Пауза', self.widgetsData)
self.graphModeLabel = QLabel('Режим отображения графика', self.widgetsData)
self.graphModeComboB = QComboBox(self.widgetsData)
self.graphModeComboB.addItems(('Линия', 'Линия с точками', 'Точка'))
self.linkModeLabel = QLabel('Режим связки', self.widgetsData)
self.linkModeComboB = QComboBox(self.widgetsData)
self.linkModeComboB.addItem('-')
self.deviceName = deviceName
self.linkModeComboB.addItem(self.deviceName)
# Нужно для того чтобы плот не ел кнопки старта и паузы
self.notEatPlot = QFrame(self.widgetsData)
# Расположение
self.commonTabGrib = QGridLayout(self.tab)
self.commonTabGrib.addWidget(self.currentDisplayLable, 0, 0)
self.commonTabGrib.addWidget(self.currentDisplayLineE, 0, 1)
self.commonTabGrib.addWidget(self.timeToUpdateLable, 1, 0)
self.commonTabGrib.addWidget(self.timeToUpdateLineE, 1, 1)
self.commonTabGrib.addWidget(self.rangeDeviceLable, 2, 0)
self.commonTabGrib.addWidget(self.rangeDeviceComboB, 2, 1)
self.commonTabGrib.addWidget(self.lcdNumber, 3, 0, 2, -1)
self.commonTabGrib.addWidget(self.widgetsData, 5, 0, -1, -1)
self.plotGrid = QGridLayout(self.widgetsData)
self.plotGrid.addWidget(self.startPlotBtn, 2, 0)
self.plotGrid.addWidget(self.pausePlotBtn, 2, 1)
self.plotGrid.addWidget(self.graphModeLabel, 3, 0)
self.plotGrid.addWidget(self.graphModeComboB, 3, 1)
self.plotGrid.addWidget(self.linkModeLabel, 4, 0)
self.plotGrid.addWidget(self.linkModeComboB, 4, 1)
self.startPlotBtn.pressed.connect(self.errrors)
self.timeToUpdateLineE.textChanged.connect(self.timeUpdate)
def timeUpdate(self):
self.timeCurrentUpdate = self.timeToUpdateLineE.text()
print('Text:', self.timeCurrentUpdate)
self.about_time_update.emit(self.timeCurrentUpdate)
def errrors(self):
print(2)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Intler")
self.resize(600, 400)
self.initUI()
def initUI(self):
# Создание виджета для Вкладок
self.tabWidget = QTabWidget()
self.tabWidget.setDocumentMode(True)
# Вкладка 1
self.mainTab = QWidget()
self.tabWidget.addTab(self.mainTab, 'Подключение:')
# Кнопки
self.connectPortBtn = QPushButton('Подключиться', self.mainTab)
# Error Лайбл
self.errorsLabel = QLabel('Ошибок не обнаружено', self.mainTab)
self.errorsLabel.setWordWrap(True)
# Расположение виджетов во вкладке 'Подключение:'
self.mainTabVert = QVBoxLayout()
self.tab1Grib = QGridLayout(self.mainTab)
self.mainTabVert.addWidget(self.tabWidget)
self.mainTabVert.addWidget(self.errorsLabel)
self.tab1Grib.addWidget(self.connectPortBtn, 2, 3)
self.setLayout(self.mainTabVert)
# Подключение виджетов(кнопок и тд и тп)
self.connectPortBtn.pressed.connect(self.connectToLab)
def connectToLab(self):
# Очистка вкладок
while self.tabWidget.count() > 1:
self.tabWidget.removeTab(1)
i = 0
while i != 3:
self.createCommonTab(random_char(5), random_char(
4), ('asd', 'fsa', 'gea'), random_char(2), self.tabWidget)
i += 1
def createCommonTab(self, name, init, rangeDevic, deviceName, tabWidget):
tab = MyTab(name, init, rangeDevic, deviceName, tabWidget)
# Если избавиться тут то будет отрисовано всё, но ничего не будет работать ---------------2
self.tabWidget.addTab(tab, name)
tab.about_time_update.connect(self.on_about_tab_time_update)
# self.tabWidget.addTab(tab, name)
# tab.startPlotBtn.pressed.connect(self.errrors)
def on_about_tab_time_update(self, time_update: str):
tab: MyTab = self.sender()
print(tab, time_update)
def timeUpdate(self):
self.timeCurrentUpdate = self.timeToUpdateLineE.text()
print(self.timeCurrentUpdate)
# Запуск
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec())
Ответы (1 шт):
Автор решения: gil9red
→ Ссылка
Проблемы и замечания:
- У вас в конструкторе
MyTabбыло создание вкладки отQWidgetи добавление ее с таким же имененем - Не думаю, что нужно передавать виджет
tabWidgetв вкладки - Не думаю, что нужно передавать виджет
tabWidgetв методы (типаcreateCommonTab) самогоMainWindow- он и так доступен - Не нужно виджетам указывать родителя, т.к. при использовании компоновщиков (
Q*Layout) родитель и так будет указан. Поэтому убралself.tabиз конструкторов виджетов (хотя в вашем случае там был быself, но и его можно не указывать)
Теперь работает:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import random
import string
import traceback
def log_uncaught_exceptions(ex_cls, ex, tb):
text = '{}: {}:\n'.format(ex_cls.__name__, ex)
text += ''.join(traceback.format_tb(tb))
print(text)
QMessageBox.critical(None, 'Error', text)
sys.exit(1)
sys.excepthook = log_uncaught_exceptions
def random_char(y):
return ''.join(random.choice(string.ascii_letters) for x in range(y))
class MyTab(QWidget):
about_time_update = pyqtSignal(str)
def __init__(self, name, init, rangeDevic, deviceName):
super().__init__()
self.setWindowTitle(name)
# Всякое повторяющееся из вкладки во вкладку
self.validator = QIntValidator(0, 3600000)
self.currentDisplayLable = QLabel('Текущее показание:')
self.init = init
self.currentDisplayLineE = QLineEdit(''+self.init)
self.currentDisplayLineE.setReadOnly(True)
self.timeToUpdateLable = QLabel('Период обновлений, мс:')
self.timeToUpdateLineE = QLineEdit('100')
self.timeToUpdateLineE.setValidator(self.validator)
self.rangeDeviceLable = QLabel('Диапазон:')
self.rangeDeviceComboB = QComboBox()
self.rangeDevice = rangeDevic
if type(self.rangeDevice) == str:
self.rangeDeviceComboB.addItem(self.rangeDevice)
else:
self.rangeDeviceComboB.addItems(self.rangeDevice)
self.lcdNumber = QLCDNumber()
self.widgetsData = QWidget()
self.startPlotBtn = QPushButton('Старт', self.widgetsData)
self.pausePlotBtn = QPushButton('Пауза', self.widgetsData)
self.graphModeLabel = QLabel('Режим отображения графика', self.widgetsData)
self.graphModeComboB = QComboBox(self.widgetsData)
self.graphModeComboB.addItems(('Линия', 'Линия с точками', 'Точка'))
self.linkModeLabel = QLabel('Режим связки', self.widgetsData)
self.linkModeComboB = QComboBox(self.widgetsData)
self.linkModeComboB.addItem('-')
self.deviceName = deviceName
self.linkModeComboB.addItem(self.deviceName)
# Нужно для того чтобы плот не ел кнопки старта и паузы
self.notEatPlot = QFrame(self.widgetsData)
# Расположение
self.commonTabGrib = QGridLayout(self)
self.commonTabGrib.addWidget(self.currentDisplayLable, 0, 0)
self.commonTabGrib.addWidget(self.currentDisplayLineE, 0, 1)
self.commonTabGrib.addWidget(self.timeToUpdateLable, 1, 0)
self.commonTabGrib.addWidget(self.timeToUpdateLineE, 1, 1)
self.commonTabGrib.addWidget(self.rangeDeviceLable, 2, 0)
self.commonTabGrib.addWidget(self.rangeDeviceComboB, 2, 1)
self.commonTabGrib.addWidget(self.lcdNumber, 3, 0, 2, -1)
self.commonTabGrib.addWidget(self.widgetsData, 5, 0, -1, -1)
self.plotGrid = QGridLayout(self.widgetsData)
self.plotGrid.addWidget(self.startPlotBtn, 2, 0)
self.plotGrid.addWidget(self.pausePlotBtn, 2, 1)
self.plotGrid.addWidget(self.graphModeLabel, 3, 0)
self.plotGrid.addWidget(self.graphModeComboB, 3, 1)
self.plotGrid.addWidget(self.linkModeLabel, 4, 0)
self.plotGrid.addWidget(self.linkModeComboB, 4, 1)
self.startPlotBtn.pressed.connect(self.errrors)
self.timeToUpdateLineE.textChanged.connect(self.timeUpdate)
def timeUpdate(self):
self.timeCurrentUpdate = self.timeToUpdateLineE.text()
print('Text:', self.timeCurrentUpdate)
self.about_time_update.emit(self.timeCurrentUpdate)
def errrors(self):
print(2)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Intler")
self.resize(600, 400)
self.initUI()
def initUI(self):
# Создание виджета для Вкладок
self.tabWidget = QTabWidget()
self.tabWidget.setDocumentMode(True)
# Вкладка 1
self.mainTab = QWidget()
self.tabWidget.addTab(self.mainTab, 'Подключение:')
# Кнопки
self.connectPortBtn = QPushButton('Подключиться', self.mainTab)
# Error Лайбл
self.errorsLabel = QLabel('Ошибок не обнаружено', self.mainTab)
self.errorsLabel.setWordWrap(True)
# Расположение виджетов во вкладке 'Подключение:'
self.mainTabVert = QVBoxLayout()
self.tab1Grib = QGridLayout(self.mainTab)
self.mainTabVert.addWidget(self.tabWidget)
self.mainTabVert.addWidget(self.errorsLabel)
self.tab1Grib.addWidget(self.connectPortBtn, 2, 3)
self.setLayout(self.mainTabVert)
# Подключение виджетов(кнопок и тд и тп)
self.connectPortBtn.clicked.connect(self.connectToLab)
def connectToLab(self):
# Очистка вкладок
while self.tabWidget.count() > 1:
self.tabWidget.removeTab(1)
i = 0
while i != 3:
self.createCommonTab(random_char(5), random_char(4), ('asd', 'fsa', 'gea'), random_char(2))
i += 1
def createCommonTab(self, name, init, rangeDevic, deviceName):
tab = MyTab(name, init, rangeDevic, deviceName)
# Если избавиться тут то будет отрисовано всё, но ничего не будет работать ---------------2
self.tabWidget.addTab(tab, name)
tab.about_time_update.connect(self.on_about_tab_time_update)
# self.tabWidget.addTab(tab, name)
# tab.startPlotBtn.pressed.connect(self.errrors)
def on_about_tab_time_update(self, time_update: str):
tab: MyTab = self.sender()
print(tab, time_update)
def timeUpdate(self):
self.timeCurrentUpdate = self.timeToUpdateLineE.text()
print(self.timeCurrentUpdate)
# Запуск
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec())