I am attempting to generate output information in a tabbed layout using PyQT5. In the case that I have multiple devices, I would expect multiple tabs to show up in the output with information corresponding to their respective device.
For some reason, I am getting a single tab, and a single button. Basically like the information is getting written over. The issue is that I do not know how to dynamically add new tabs and hold on to all of the information inside them properly upon each iteration. I will not know the number of devices or device parameters ahead of time, so I can not set this information in code. It must be dynamic.
Here is my current code:
# $description: Testing
# $show-in-menu
import pya
import json
import re, sys
from pe import generateDeviceParameters
from datetime import datetime
import os
import subprocess, os, platform
import functools
class CommandWindow( pya.QPlainTextEdit ):
def __init__( self, parent ):
super( CommandWindow, self ).__init__( parent )
self.setPlaceholderText( "Command Window" )
self.setReadOnly( True )
def log( self, text ):
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
self.insertPlainText(f"{current_time}: {text}\n")
self.repaint()
class CommandWindowButton( pya.QPushButton ):
def __init__( self, parent ):
super( CommandWindowButton, self ).__init__( parent )
self.app = parent
self.text = "Clear Command Window"
def clearText( self ):
self.app.commandWindow.setPlainText( "" )
class MyApp( pya.QDialog ):
def __init__( self, parent ):
super( MyApp, self ).__init__( parent )
# Change title
self.windowTitle = 'Automated Parameter Extraction'
self.resize( 1250, 500 )
# Set application font
self.font = pya.QFont("Arial", 10)
self.setFont(self.font)
# Create a vertical layout for the main widget
self.layout = pya.QGridLayout()
self.setLayout(self.layout)
# Create the first panel
self.first_panel = pya.QWidget()
self.first_layout = pya.QVBoxLayout()
self.first_panel.setLayout(self.first_layout)
# Create and connect the combo box to switch between pages
self.deviceCombo = pya.QComboBox()
self.deviceCombo.addItems( ["Multiple Devices (Config File)"] )
self.deviceCombo.activated = self.switchPage
self.first_layout.addWidget( self.deviceCombo )
# Create the inputs related to a single device
self.createPages()
self.first_layout.addWidget( self.deviceGroupBox )
# Create command window
self.commandWindow = CommandWindow( self )
self.first_layout.addWidget( self.commandWindow )
self.cwClearButton = CommandWindowButton( self )
self.cwClearButton.clicked = self.cwClearButton.clearText
self.first_layout.addWidget( self.cwClearButton )
# Add first panel to the main layout
self.layout.addWidget(self.first_panel, 0, 0, 1, 1)
# Create the second panel (scroll layout)
self.second_panel = pya.QWidget()
self.second_layout = pya.QVBoxLayout()
self.second_panel.setLayout( self.second_layout )
# Create a scroll area
self.scroll_area = pya.QScrollArea()
self.scroll_widget = pya.QWidget()
self.scroll_layout = pya.QVBoxLayout()
self.scroll_widget.setLayout( self.scroll_layout )
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget( self.scroll_widget )
# Add scroll area to the second layout
self.second_layout.addWidget( self.scroll_area )
# Analysis button
self.ok = pya.QPushButton( "Run Extraction" )
self.ok.clicked = self.runPE
self.second_layout.addWidget( self.ok )
# Add second panel to the main layout
self.layout.addWidget(self.second_panel, 0, 1, 1, 1)
def createPages( self ):
# Initialize
self.deviceGroupBox = pya.QGroupBox( 'Extraction Information' )
self.stackedLayout = pya.QStackedLayout()
self.deviceGroupBox.setLayout( self.stackedLayout )
self.page1 = pya.QWidget()
self.page1_layout = pya.QGridLayout()
self.edit1_pane = pya.QWidget()
self.edit1_layout = pya.QVBoxLayout()
self.edit1_pane.setLayout( self.edit1_layout )
self.button1_pane = pya.QWidget()
self.button1_layout = pya.QVBoxLayout()
self.button1_pane.setLayout( self.button1_layout )
# Create output location edit field
self.outputLocation = pya.QLineEdit( self )
self.button1 = pya.QPushButton()
self.edit1_layout.addWidget( self.outputLocation )
self.button1_layout.addWidget( self.button1 )
# Create top cell choice edit field
self.topCell = pya.QLineEdit( self )
self.button2 = pya.QPushButton()
self.edit1_layout.addWidget( self.topCell )
self.button1_layout.addWidget( self.button2 )
# Create unit cell choice edit field
self.unitCell = pya.QLineEdit( self )
self.button3 = pya.QPushButton()
self.edit1_layout.addWidget( self.unitCell )
self.button1_layout.addWidget( self.button3 )
# Create edge cell choice edit field
self.edgeCell = pya.QLineEdit( self )
self.button4 = pya.QPushButton()
self.edit1_layout.addWidget( self.edgeCell )
self.button1_layout.addWidget( self.button4 )
# Reformat
self.page1_layout.addWidget( self.edit1_pane, 0, 0, 1, 1 )
self.page1_layout.addWidget( self.button1_pane, 0, 1, 1, 1 )
self.page1.setLayout( self.page1_layout )
self.stackedLayout.addWidget( self.page1 )
# Initialize
self.page2 = pya.QWidget()
self.page2_layout = pya.QGridLayout()
self.edit2_pane = pya.QWidget()
self.edit2_layout = pya.QVBoxLayout()
self.edit2_pane.setLayout( self.edit2_layout )
self.button2_pane = pya.QWidget()
self.button2_layout = pya.QVBoxLayout()
self.button2_pane.setLayout( self.button2_layout )
# Create input files location edit field
self.inFiles = pya.QLineEdit( self )
self.button5 = pya.QPushButton()
self.edit2_layout.addWidget( self.inFiles )
self.button2_layout.addWidget( self.button5 )
# Create config file location edit field
self.configFile = pya.QLineEdit( self )
self.button6 = pya.QPushButton()
self.edit2_layout.addWidget( self.configFile )
self.button2_layout.addWidget( self.button6 )
# Reformat
self.page2_layout.addWidget( self.edit2_pane, 0, 0, 1, 1 )
self.page2_layout.addWidget( self.button2_pane, 0, 1, 1, 1 )
self.page2.setLayout( self.page2_layout )
self.stackedLayout.addWidget( self.page2 )
def switchPage( self ):
self.stackedLayout.setCurrentIndex(self.deviceCombo.currentIndex)
def runPE( self ):
self.multipleDevice()
def multipleDevice( self ):
# Create tab widget within croll layout
self.tab_widget = pya.QTabWidget()
self.scroll_layout.addWidget( self.tab_widget )
tab = []
tab_layout = []
data_for_tabs = dict()
data_for_tabs["Device1"] = dict()
data_for_tabs["Device1"]["Parameter1"] = dict()
data_for_tabs["Device1"]["Parameter1"]["x"] = 1.2
data_for_tabs["Device1"]["Parameter1"]["y"] = 1.5
data_for_tabs["Device1"]["Parameter2"] = dict()
data_for_tabs["Device1"]["Parameter2"]["x"] = 1.4
data_for_tabs["Device1"]["Parameter2"]["y"] = 1.3
data_for_tabs["Device2"] = dict()
data_for_tabs["Device2"]["Parameter1"] = dict()
data_for_tabs["Device2"]["Parameter1"]["x"] = 2.2
data_for_tabs["Device2"]["Parameter1"]["y"] = 2.5
data_for_tabs["Device2"]["Parameter2"] = dict()
data_for_tabs["Device2"]["Parameter2"]["x"] = 2.4
data_for_tabs["Device2"]["Parameter2"]["y"] = 2.3
# First generate tabs
tabNumber = 0
for key in data_for_tabs.keys():
# Create tab
tab.append( pya.QWidget() )
tab_layout.append( pya.QVBoxLayout() )
tab[tabNumber].setLayout( tab_layout[tabNumber] )
self.tab_widget.addTab( tab[tabNumber], key )
self.tab = tab[tabNumber]
self.tab_layout = tab_layout[tabNumber]
self.runExtraction( data_for_tabs[key], self.tab, self.tab_layout )
tabNumber += 1
def runExtraction( self, data, tab, tab_layout ):
row = 0
for key, value in data.items():
outGroupBox = pya.QGroupBox( key )
self.out_layout = pya.QHBoxLayout()
for pkey, pval in value.items():
txtlbl = pya.QLabel( tab )
txtlbl.setText(f"{pkey} = ")
txt = pya.QLineEdit( tab )
txt.setText(f"{pval}")
txt.setReadOnly( True )
self.out_layout.addWidget( txtlbl )
self.out_layout.addWidget( txt )
self.button = pya.QPushButton()
self.button.text = f"{key}"
self.out_layout.addWidget( self.button )
# Reformat
outGroupBox.setLayout( self.out_layout )
outGroupBox.update()
setattr( self, "outGroupBox" + str(row), outGroupBox )
tab_layout.addWidget( getattr( self, "outGroupBox" + str(row) ) )
row += 1
# Add stretch so everything sits at the top
tab_layout.addStretch()
# Create the app instance and run the event loop
peDialog = MyApp( pya.Application.instance().main_window() )
peDialog.show()
Please feel free to leave comments or provide any help. My guess is that I will need to create some sort of class for the tabbed layout, but I am not sure.
I have tried using a variation of setattr and getattr in order to dynamically create tab widgets and layouts for each tab and device parameter. For some reason this causes the app to not see anything however.
I am hoping to see multiple tabs with their respective device. And then each tab should have the information given from that device.