Pyqt5: dyamically add a table to a tab - python

In my main program, I have a Dock widget (Vertical layout) containing a TabWidget (layouts added per tab). In my first tab I have added a static table, which resizes with the dock.
I am trying to allow the user to dynamically add a tab by importing a TableWidget design from another file into a tab; however, I am having trouble getting the layout to mimic the first tab.
Below is my code. I can make the table appear in the freshly made tab, just not fully adjust to the dock window.
My python start file:
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import mainwindow, sys, os, PyQt5, resources, dataTable
class dataForm(QtWidgets.QWidget, dataTable.Ui_Form)
def __init__(self, parent=None):
super(dataForm, self).__init__(parent)
self.setupUi(self)
class Example(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.setupUi(self)
self.shortcut.activated.connect(self.addTabs)
def Resolution(self):
app = QtWidgets.QApplication([])
resolution = app.desktop().screenGeometry()
width, height = resolution.width(), resolution.height()
self.setMaximumSize(QtCore.QSize(width, height))
def addTabs(self):
self.DataSets.setUpdatesEnabled(True)
self.tab = QtWidgets.QWidget()
self.tab.setAutoFillBackground(False)
self.tab.setObjectName("userAdded")
pages = self.count()
# Set the tab layout
self.tableLayout = QtWidgets.QVBoxLayout(self.tab)
self.tableLayout.setContentsMargins(1, 0, 1, 0)
self.tableLayout.setSpacing(0)
self.tableLayout.setObjectName("tableGrid")
# Add table to the new tab widget
self.table = dataForm(self.tab)
# Add table to layout
self.tableLayout.addWidget(self.table)
self.tableLayout.addStretch()
# Add the tab and go to that location
self.DataSets.insertTab((pages-1), self.tab, "Set %d" %(pages))
self.DataSets.setCurrentIndex(pages-1)
def main():
app = QtWidgets.QApplication(sys.argv)
form = Example()
form.showMaximized()
app.exec_()
if __name__ == '__main__':
main()
and my dataTable.ui form:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(242, 450)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.tableWidget = QtWidgets.QTableWidget(Form)
self.tableWidget.setGeometry(QtCore.QRect(1, 0, 240, 450))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
self.tableWidget.setAutoFillBackground(True)
self.tableWidget.setStyleSheet("QHeaderView::section { background-color:rgb(140, 200, 172)};\n"
"")
self.tableWidget.setFrameShape(QtWidgets.QFrame.Panel)
self.tableWidget.setFrameShadow(QtWidgets.QFrame.Plain)
self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.tableWidget.setDragEnabled(True)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setGridStyle(QtCore.Qt.SolidLine)
self.tableWidget.setRowCount(35)
self.tableWidget.setColumnCount(10)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
brush = QtGui.QBrush(QtGui.QColor(50, 0, 0))
brush.setStyle(QtCore.Qt.NoBrush)
item.setForeground(brush)
self.tableWidget.setItem(0, 1, item)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
self.tableWidget.horizontalHeader().setDefaultSectionSize(70)
self.tableWidget.horizontalHeader().setHighlightSections(True)
self.tableWidget.horizontalHeader().setMinimumSectionSize(39)
self.tableWidget.verticalHeader().setVisible(True)
self.tableWidget.verticalHeader().setDefaultSectionSize(20)
self.tableWidget.verticalHeader().setSortIndicatorShown(True)
self.tableWidget.verticalHeader().setStretchLastSection(False)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.tableWidget.setSortingEnabled(True)
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
I'm pretty close, I think. Any suggestions?
Edit: Updated code to make the dataTable classified as a QWidget & passed self.tab as its parent in def AddTabs. Also, I added a part of the layout of AddTabs that was cut out accidentally.

Related

Embedding a custom widget into a stacked widget page WITHOUT using qtdesigner

I am trying to embed two custom widgets into the pages of a stacked widget on a dialog page. I have mocked up my problem using the main script dialog.py which has a stacked widget with two pages promoting widget_1_UI from widget_1.py and widget_2_UI from widget_2.py to each page, respectively. It doesn't throw any errors when run but also doesn't show the content from the two modules in the stacked widget.
dialog.py
from PyQt5 import QtCore, QtGui, QtWidgets
from widget_1 import widget_1_UI
from widget_2 import widget_2_UI
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setWindowTitle("Dialog")
Dialog.resize(640, 480)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.stackedWidget = QtWidgets.QStackedWidget(Dialog)
self.page_1 = widget_1_UI()
self.stackedWidget.addWidget(self.page_1)
self.page_2 = widget_2_UI()
self.stackedWidget.addWidget(self.page_2)
self.verticalLayout.addWidget(self.stackedWidget)
self.btn_nextPage = QtWidgets.QPushButton(Dialog)
self.btn_nextPage.setText("PushButton")
self.verticalLayout.addWidget(self.btn_nextPage)
self.btn_nextPage.clicked.connect(self.nextPage)
def nextPage(self):
pageNum = self.stackedWidget.currentIndex()
if pageNum == 0:
self.stackedWidget.setCurrentIndex(1)
else:
self.stackedWidget.setCurrentIndex(0)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
widget_1.py
from PyQt5 import QtCore, QtGui, QtWidgets
class widget_1_UI(QtWidgets.QWidget):
def setupUi(self, Form):
Form.resize(614, 411)
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.label = QtWidgets.QLabel(Form)
font = QtGui.QFont()
font.setPointSize(26)
self.label.setFont(font)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setText("AY YO BBY GRILL")
self.verticalLayout.addWidget(self.label)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setText("Dis one do nuffin")
self.verticalLayout.addWidget(self.pushButton)
widget_2.py
from PyQt5 import QtCore, QtGui, QtWidgets
class widget_2_UI(QtWidgets.QWidget):
def setupUi(self, Form):
Form.resize(614, 411)
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.label = QtWidgets.QLabel(Form)
font = QtGui.QFont()
font.setPointSize(26)
self.label.setFont(font)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setText("HOW YOU DOIN")
self.verticalLayout.addWidget(self.label)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setText("Dis do nuffin 2")
self.verticalLayout.addWidget(self.pushButton)
Figured it out! In dialog.py widget_1_UI() is set as the promoted widget for the first page of the stacked widget but there is nothing to tell it what should be inside it. Adding self.page_1.setupUi(self.page_1) does just that.
self.page_1 = widget_1_UI()
self.page_1.setupUi(self.page_1)
self.stackedWidget.addWidget(self.page_1)
The same is applied to widget_2_UI.

PyQt5 changing QlineEdit text automatically

i have a main window with a read-only QlineEdit that displays today date and a button that opens calendar widget window (from another module in the project) to choose another date ,the problem that when i choose another date the QlineEdit text in Gui do not change although the variable that stores the value changes successfully ,i searched a lot with no clue
before using QlineEdit i tried Qlabel but could not achieve the result also
here is the main window:
import sys
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit
from PyQt5 import QtCore, QtGui, QtWidgets
from cal_window import prev_day, today_str, UiCalWindow
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("My App")
self.setGeometry(50, 50, 800, 600)
self.label = QLineEdit(self)
self.label.setFont(QFont("Arial", 20))
self.label.setReadOnly(True)
self.label.setText(today_str)
self.setCentralWidget(self.label)
self.btn = QPushButton('open calender', self)
self.btn.move(50, 50)
self.btn.clicked.connect(self.choose_date)
def choose_date(self):
self.window = QtWidgets.QMainWindow()
self.ui = UiCalWindow()
self.ui.setupUi(self.window)
self.window.show()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
and here is the calendar sub-window:
from PyQt5 import QtCore, QtGui, QtWidgets, Qt
from datetime import date
today = date.today()
today_str = today.strftime("%Y-%m-%d")
prev_day = "2000-01-01"
class UiCalWindow(object):
def get_date(self, qDate):
global prev_day
self.day = '{0}-{1}-{2}'.format(qDate.year(), qDate.month(), qDate.day())
prev_day = self.day
print(prev_day)
def setupUi(self, cal_window):
cal_window.setObjectName("cal_window")
cal_window.setWindowModality(QtCore.Qt.ApplicationModal)
cal_window.resize(800, 600)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
cal_window.setFont(font)
self.centralwidget = QtWidgets.QWidget(cal_window)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.calendarWidget.setFont(font)
self.calendarWidget.setLayoutDirection(QtCore.Qt.RightToLeft)
self.calendarWidget.setFirstDayOfWeek(QtCore.Qt.Monday)
self.calendarWidget.setGridVisible(True)
self.calendarWidget.setVerticalHeaderFormat(QtWidgets.QCalendarWidget.NoVerticalHeader)
self.calendarWidget.setObjectName("calendarWidget")
self.gridLayout.addWidget(self.calendarWidget, 0, 0, 1, 1)
self.calendarWidget.clicked.connect(self.get_date)
self.ok_dt_btn = QtWidgets.QPushButton(self.centralwidget)
self.ok_dt_btn.setMinimumSize(QtCore.QSize(0, 50))
self.ok_dt_btn.setObjectName("ok_dt_btn")
self.ok_dt_btn.clicked.connect(cal_window.close)
self.gridLayout.addWidget(self.ok_dt_btn, 1, 0, 1, 1)
cal_window.setCentralWidget(self.centralwidget)
self.retranslateUi(cal_window)
QtCore.QMetaObject.connectSlotsByName(cal_window)
def retranslateUi(self, cal_window):
_translate = QtCore.QCoreApplication.translate
cal_window.setWindowTitle(_translate("cal_window", "MainWindow"))
self.ok_dt_btn.setText(_translate("cal_window", "go"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
cal_window = QtWidgets.QMainWindow()
ui = UiCalWindow()
ui.setupUi(cal_window)
cal_window.show()
sys.exit(app.exec_())```
You have concept problems:
Do not modify the code generated by Qt Designer (it is recommended that you restore cal_window.py.
Do not use global variables, they are unnecessary and generate more problems than solutions.
That the variable "prev_day" is updated does not imply that the text displayed by the QLabel is updated, the QLabel copies the information and does not monitor the string.
The logic is to use the signal to update the text.
import sys
from PyQt5.QtCore import pyqtSignal, QDate
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit
from cal_window import UiCalWindow
class CalendarWindow(QMainWindow, UiCalWindow):
def __init__(self, parent=None):
super(CalendarWindow, self).__init__(parent)
self.setupUi(self)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("My App")
self.setGeometry(50, 50, 800, 600)
self.label = QLineEdit(self)
self.label.setFont(QFont("Arial", 20))
self.label.setReadOnly(True)
self.setCentralWidget(self.label)
self.btn = QPushButton("open calender", self)
self.btn.move(50, 50)
self.cal = CalendarWindow()
self.cal.calendarWidget.clicked.connect(self.handle_date_clicked)
self.btn.clicked.connect(self.cal.show)
def handle_date_clicked(self, date):
self.label.setText(date.toString("yyyy-MM-dd"))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

PySide create horizontal tabs with horizontal text

I am trying to use this solution by #eyllanesc:
pyqt qtabwidget horizontal tab and horizontal text in QtDesigner.
My main window has a QStackedWidget in which one of the pages is the page with horizontal tabs. I used Qt designer to create a dialog with a tab widget, and set the tabPosition to West. Then I promoted the TabWidget like shown in the original post.
This is what the resulting window looks like. There are no outlines around the tabs, and the tabs are not clickable:
This is my main code:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from tabs import TabsUi_Dialog
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.mainMenuWidget = MainStack(self)
self.setCentralWidget(self.mainMenuWidget)
self.show()
class MainStack(QWidget):
def __init__(self,parent=None):
super(MainStack,self).__init__(parent)
self.initUI()
def initUI(self):
layout = QVBoxLayout(self)
self.stack = QStackedWidget(parent=self)
self.tabPage = TabPage()
#Add Pages to Stack
self.stack.addWidget(self.tabPage)
#Add Stack to Layout
self.stack.setCurrentWidget(self.tabPage)
layout.addWidget(self.stack)
class TabPage(QWidget):
def __init__(self,parent=None):
super(TabPage,self).__init__(parent)
self.tabs = TabsUi_Dialog()
self.tabs.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
ret = app.exec_()
sys.exit( ret )
And this is the tabs.py file created after converting the Qt Designer UI file with py-uic:
from PySide import QtCore, QtGui
class TabsUi_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.verticalLayout = QtGui.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget = TabWidget(Dialog)
self.tabWidget.setTabPosition(QtGui.QTabWidget.West)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtGui.QWidget()
self.tab.setObjectName("tab")
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtGui.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.verticalLayout.addWidget(self.tabWidget)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QtGui.QApplication.translate("Dialog", "Tab 1", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QtGui.QApplication.translate("Dialog", "Tab 2", None, QtGui.QApplication.UnicodeUTF8))
from tabwidget import TabWidget

PyQt5 How to identify and grab data from a QT combobox that has been created along with other combobox using a function

I wrote a script that automatically creates a QT "object" made up of a category label, a combobox_1 with possible attributes, a push button and a combobox_2 to list all values available for the attribute selected. the script creates as many of these "objects" as necessary.
For each "object" the push button created is meant to grab the selected attribute in combobox_1 and use this information to retrieve relevant values from the database and populate combobx_2
Now the problem I have is that I can't figure out how to reference the comboboxes once they have been created. For the buttons, I use the serve function which listen to any button for a click so that's fine, but how can I reference combobox that have been created with a function. Although they all have different setObjectName, there doesn't seem to be a way of referencing that attribute so when I click on any button they all return the value of the last object's combobox instead of the value of its related comboxbox to which they are attached.
here is the Frontend script:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(709, 357)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.gridLayout_4 = QtWidgets.QGridLayout()
self.gridLayout_4.setObjectName("gridLayout_4")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_4.addItem(spacerItem, 1, 1, 1, 1)
self.VLayout_0 = QtWidgets.QVBoxLayout()
self.VLayout_0.setObjectName("VLayout_0")
self.HLayout_0 = QtWidgets.QHBoxLayout()
self.HLayout_0.setObjectName("HLayout_0")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
self.HLayout_0.addItem(spacerItem1)
self.CB_L0 = QtWidgets.QComboBox(self.centralwidget)
self.CB_L0.setObjectName("CB_L0")
self.HLayout_0.addWidget(self.CB_L0)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setMaximumSize(QtCore.QSize(40, 16777215))
self.pushButton.setObjectName("pushButton")
self.HLayout_0.addWidget(self.pushButton)
spacerItem2 = QtWidgets.QSpacerItem(50, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
self.HLayout_0.addItem(spacerItem2)
self.VLayout_0.addLayout(self.HLayout_0)
spacerItem3 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.VLayout_0.addItem(spacerItem3)
self.gridLayout_4.addLayout(self.VLayout_0, 1, 0, 1, 1)
self.PB_create_cb = QtWidgets.QPushButton(self.centralwidget)
self.PB_create_cb.setObjectName("PB_create_cb")
self.gridLayout_4.addWidget(self.PB_create_cb, 0, 1, 1, 1)
self.gridLayout.addLayout(self.gridLayout_4, 0, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 709, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "search"))
self.PB_create_cb.setText(_translate("MainWindow", "Create dropdown"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
and here is the backend example (which creates two "objects"):
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QAction, QTableWidget, QTableWidgetItem, QVBoxLayout, QMessageBox, QDialog, QLineEdit, QPushButton, QMenu, QSizePolicy, QLabel,QTreeWidget,QTreeWidgetItem
from PyQt5.QtWidgets import (QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
import sys
from test3 import *
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Run_script, self).__init__(parent)
self.setupUi(self)
print("Run script initizalised")
self.PB_create_cb.clicked.connect(self.click_select)
def create_V_0_object(self,List_attributes):
V_list = []
for i,x in enumerate(List_attributes):
for k,v in x.items():
if type(v) == dict:
for k1,v1 in v.items():
if type(v) == dict:
self.HLayout_1 = QtWidgets.QHBoxLayout()
self.HLayout_1.setObjectName("H_layout_1")
self.VLayout_0 = QtWidgets.QVBoxLayout()
self.VLayout_0.setObjectName("V_L2"+k+str(i))
self.Attr_label = QtWidgets.QLabel(self.centralwidget)
self.Attr_label.setObjectName(k)
self.Attr_label.setText(k)
self.VLayout_0.addWidget(self.Attr_label)
self.attr_list = []
for k1,v1 in v.items():
self.attr_list.append(k1)
print("K1 is "+str(k1))
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("CB_"+k)
self.comboBox.addItems(self.attr_list)
self.comboBox.setToolTip("CB_"+k)
self.VLayout_0.addWidget(self.comboBox)
self.comboBox1 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox1.setObjectName("CB_l2_"+k)
self.comboBox1.setToolTip("CB_l2_"+k)
self.VLayout_0.addWidget(self.comboBox1)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setMaximumSize(QtCore.QSize(40, 16777215))
PB_name = "PB_"+str(k)
self.pushButton.setObjectName(PB_name)
self.pushButton.setToolTip("Search " + str(PB_name))
self.pushButton.setText(PB_name)
self.pushButton.clicked.connect(self.buttonClicked)
self.HLayout_1.addLayout(self.VLayout_0)
self.HLayout_1.addWidget(self.pushButton)
else:
pass
V_list.append(self.HLayout_1)
return V_list
def buttonClicked(self):
sender = self.sender()
cat_l_0 = sender.text()
for i in range(self.VLayout_0.count()):
name = self.VLayout_0.itemAt(i).widget().objectName()
print("this is:",name)
def click_select(self):
self.selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1":"test3","Attr2":"test4"}}]
self.v = self.create_V_0_object(self.selection)
self.create_horizontal_display(self.v)
def deleteItemsOfLayout(self,layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
self.deleteItemsOfLayout(item.layout())
def create_horizontal_display(self,vertical_layout_list):
self.deleteItemsOfLayout(self.HLayout_0)
for i,x in enumerate(vertical_layout_list):
self.HLayout_0.addLayout(x)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = Run_script()
prog.show()
sys.exit(app.exec_())
to create the objects just press the "create dropdown" button
You have many bad practices:
The variables that are created in a loop are generally not going to be a member of the class because they are temporary variables, so do not use them as they will be overwritten, therefore when accessing self.VLayout_0 you will always get the last element.
Another bad habit is that everything you want to do in one place, as you say the "object" s are similar except for the data so you should create a class that builds it, as they say: divide and conquer.
You have other errors but they are minor, correcting the above you have the following:
from PyQt5 import QtCore, QtGui, QtWidgets
from test3 import Ui_MainWindow
class Widget(QtWidgets.QWidget):
clicked = QtCore.pyqtSignal()
def __init__(self, text, values, parent=None):
super(Widget, self).__init__(parent)
hlay = QtWidgets.QHBoxLayout(self)
vlay = QtWidgets.QVBoxLayout()
self.label = QtWidgets.QLabel(text)
self.combobox_1 = QtWidgets.QComboBox()
self.combobox_1.addItems(values.keys())
self.combobox_2 = QtWidgets.QComboBox()
vlay.addWidget(self.label)
vlay.addWidget(self.combobox_1)
vlay.addWidget(self.combobox_2)
hlay.addLayout(vlay)
self.button = QtWidgets.QPushButton(text)
self.button.clicked.connect(self.clicked)
hlay.addWidget(self.button)
self.setFixedSize(self.sizeHint())
class Run_script(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Run_script, self).__init__(parent)
self.setupUi(self)
print("Run script initizalised")
self.PB_create_cb.clicked.connect(self.click_select)
def create_V_0_object(self, attributes):
v_list = []
for x in attributes:
for key, value in x.items():
w = Widget(key, value)
w.clicked.connect(self.buttonClicked)
v_list.append(w)
return v_list
def buttonClicked(self):
w = self.sender()
print(w.combobox_1.currentText())
print(w.combobox_2.currentText())
print(w.label.text())
print(w.button.text())
def click_select(self):
selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1": "test3", "Attr2": "test4"}}]
v = self.create_V_0_object(selection)
self.create_horizontal_display(v)
def deleteItemsOfLayout(self,layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
self.deleteItemsOfLayout(item.layout())
def create_horizontal_display(self, vertical_layout_list):
self.deleteItemsOfLayout(self.HLayout_0)
for i, x in enumerate(vertical_layout_list):
self.HLayout_0.addWidget(x)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
prog = Run_script()
prog.show()
sys.exit(app.exec_())

Python (QtDesigner) Opening multiple .py files in MdiArea window with buttons

I used QtDesigner to create all of my windows, the main window uses mdiArea so that other windows fit inside of it when called. My main problem is when I close a window inside the mdiArea it disappears and I can't reopen it, id either like the window to not have a exit button or make a window with buttons that will open the files if its not there.
Output Screenshot
The window that is minimized is ValveSimulator and if I close it it doesn't exist anymore and I can't open it
my main code: CreateWindow makes the window with the buttons and CreateValveSimulator is my main program that I want to open from the button when I close it
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget,QWidget, QMdiSubWindow
import ValveSim
import MainWindow
import Window
class Win1(QMainWindow):
def __init__(self):
QWidget.__init__(self)
self.vtn = MainWindow.Ui_MainWindow()
self.vtn.setupUi(self)
self.subwindow = QMdiSubWindow()
self.CreateValveSimulator()
self.CreateWindow()
def CreateValveSimulator(self):
widget = QMainWindow()
self.VSim_subwindow = ValveSim.Ui_ValveSim()
self.VSim_subwindow.setupUi(widget)
self.subwindow = QMdiSubWindow(self.vtn.mdiArea)
widget.setParent(self.subwindow)
self.subwindow.setWidget(widget)
self.vtn.mdiArea.addSubWindow(self.subwindow)
widget.show()
self.subwindow.show()
self.subwindow.widget().show()
def CreateWindow(self):
widget = QMainWindow()
self.win_subwindow = Window.Ui_MainWindow()
self.win_subwindow.setupUi(widget)
self.subwindow = QMdiSubWindow(self.vtn.mdiArea)
widget.setParent(self.subwindow)
self.subwindow.setWidget(widget)
self.vtn.mdiArea.addSubWindow(self.subwindow)
widget.show()
self.subwindow.show()
self.subwindow.widget().show()
if __name__=='__main__':
app =QApplication(sys.argv)
win = Win1()
win.show()
sys.exit(app.exec_())
I connected the self.pushbutton to a function called openvs which I hope to open the Valve Simulator window when its closed as shown in my main code,however it just crashes when I click the button
Table with buttons code:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QWidget, QMdiSubWindow, QAction
import Untitled
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.WindowModal)
MainWindow.resize(351, 442)
MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(85, 125, 75, 23))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(85, 195, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(200, 125, 75, 23))
self.pushButton_3.setObjectName("pushButton_3")
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton.clicked.connect(self.openvs)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Open Valve Simulator"))
self.pushButton_2.setText(_translate("MainWindow", "Open Module Program"))
self.pushButton_3.setText(_translate("MainWindow", "Open Metal Sizing"))
def openvs(self):
Untitled.Win1.CreateValveSimulator()
You must create the windows independently, and add them to each QMdiSubWindow. When the widget is displayed in the subwindow this will cause the subwindow to be displayed. To open normally with the button you must use the clicked signal and call the showNormal function.
The complete code is here.
class HomeWindow(QMainWindow, Ui_HomeWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
class ValveSim(QMainWindow, Ui_ValveSim):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
class Win1(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent=parent)
self.setupUi(self)
self.vs = ValveSim()
self.hw = HomeWindow()
self.CreateValveSimulator()
self.CreateWindow()
def CreateValveSimulator(self):
subwindow = QMdiSubWindow()
subwindow.setWidget(self.vs)
self.mdiArea.addSubWindow(subwindow)
subwindow.setFixedSize(500, 500)
# self.subwindow.close()
def CreateWindow(self):
self.hw.pushButton.clicked.connect(self.vs.showNormal)
subwindow = QMdiSubWindow()
subwindow.setWindowFlags(Qt.CustomizeWindowHint | Qt.Tool)
subwindow.setWidget(self.hw)
self.mdiArea.addSubWindow(subwindow)

Categories