EDIT: Changed title, few mistakes in code were resolved (now working properly)
The GUI I am trying to make will be a simple QTabWidget, leading a user straightforwardly towards the end tab by tab.
For now, I have three *.py files - main.py, tab1.py, tab2.py. In main.py is the main window of the app and function to run the app like this (simplified just to focus on my question):
import sys
import tab1
import tab2
import PyQt5.QtWidgets as qtw
def main():
app = qtw.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
class MainWindow(qtw.QmainWindow):
def __init__(self):
super().__init__()
self.tabwidget = qtw.QTabWidget()
self.setCentralWidget(self.tabwidget)
self.tab1 = tab1.Tab_1()
self.tab2 = tab2.Tab_2()
# This is how I now passing the information from tab1 to tab2
self.tab1.path_line.textChanged.connect(self.tab2.path_widget.setText)
self.tabwidget.addTab(self.tab1, 'tab1')
self.tabwidget.addTab(self.tab2, 'tab2')
if __name__ == '__main__':
main()
In the tab1.py is a defined class for a tabwidget which will serve as an input data tab. There is a button to open filedialog, read filename, and write the path into the QLineEdit widget:
import PyQt5.QtWidgets as qtw
class Tab_1(qtw.QWidget):
def __init__(self):
super().__init__()
self.path_line = qtw.QLineEdit()
self.but = qtw.QPushButton('Open')
self.but.clicked.connect(self.openfile)
layout_1 = qtw.QVBoxLayout()
layout_1.addWidget(self.but)
self.setLayout(layout_1)
def openfile(self):
filename, _ = qtw.QFileDialog.getOpenFileName(self, 'Title', 'File types')
if filename:
self.path_line.setText(filename)
else:
self.path_line.setText('No file was selected!')
Now I want to in another file tab2.py use the path I got from qtw.OpenFileDialog. So the defined class Tab_2() looks like this:
import PyQt5.QtWidgets as qtw
class Tab_2(qtw.QWidget):
def __init__(self):
super().__init__()
# Retrieving the information by QLabel widget
self.path_widget = qtw.QLabel()
# Transform the information into string variable
self.path_string = self.path_widget.text()
layout_2 = qtw.QVBoxLayout()
layout_2.addWidget(self.path_widget) # The path from QFileDialog (Tab1) should appered on Tab2
self.setLayout(layout_2)
My question is, is this the proper way to do it? Should I use MainWindow class as a "getter" and "passer" of the information like that or should that be implemented in the tab classes themselves? It works but I do not want to learn to do something bad way and eventually get used to it. I understand classes and their inheritance to some point (a lot of examples of dog classes or employee classes which I understand how it works but in my case I am confused.). In combination with GUI, it messing up my head. Also, I want to have each tab as a separate class in a separate *.py file to make it clear and easy to add another one in the future. I see, that it might not be the right way to uses classes but each tab will have a different layout.
After some testing, I found out that the best way to pass variable across QTabWidgets is, in my case, by class inheritence. For this idea, thanks to #S. Nick from Code Review.
I have main.py for the QMainWindow of the app and then two another *.py files, each containing a TabWidget class. Since I am creating imported Tab widgets classes in the main.py, the best solution for my question was to save a variable into the QMainWindow and then access it via Tab classes through the "self-parent thing". I am really a programming beginner, therefore I do not know if this is a basic knowledge or not. But by storing a variable into the parent QMainWindow class I can access it from any widget class created in the QMainWindow by including the "self" parameter. Here is the variance of the final code I used:
import sys
import PyQt5.QtWidgets as qtw
#from tab1 import Tab_1
class Tab_1(qtw.QWidget):
""" In this class I obtain a file path """
def __init__(self, parent=None): # + parent
super().__init__()
self.parent = parent # + parent
self.but_1 = qtw.QPushButton('Open')
self.but_1.clicked.connect(self.open_file)
layout_1 = qtw.QVBoxLayout(self)
layout_1.addWidget(self.but_1)
self.setLayout(layout_1)
def open_file(self):
filename, _ = qtw.QFileDialog.getOpenFileName(self, 'Title', 'File types')
if filename:
self.parent.file_path = filename # + parent
else:
self.parent.file_path = 'No file was selected' # + parent
#from tab2 import Tab_2
class Tab_2(qtw.QWidget):
""" In this class I want to use the file path from Tab 1 """
def __init__(self, parent=None): # + parent
super().__init__()
self.parent = parent # + parent
self.but_2 = qtw.QPushButton('Load path')
self.but_2.clicked.connect(self._load_path)
self.path_widget = qtw.QLabel('') # will show path to file after the button-click
layout_2 = qtw.QVBoxLayout(self)
layout_2.addWidget(self.but_2)
layout_2.addWidget(self.path_widget)
self.setLayout(layout_2)
def _load_path(self):
self.path_widget.setText(self.parent.file_path)
class MainWindow(qtw.QMainWindow):
def __init__(self):
super().__init__()
self.file_path = '' # + file_path
self.tabwidget = qtw.QTabWidget()
self.setCentralWidget(self.tabwidget)
self.tab1 = Tab_1(self) # + self
self.tab2 = Tab_2(self) # + self
self.tabwidget.addTab(self.tab1, 'Tab 1')
self.tabwidget.addTab(self.tab2, 'Tab 2')
def main():
app = qtw.QApplication(sys.argv)
window = MainWindow()
window.resize(400, 300)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
What I want to achieve in python PyQt5 is when I open the script I open a parent window automatically with a button on the middle of the screen. When I click this button a new window suppose to open, and when I close the window I can close separately the parent window and the child window. I want to be able to close the parent window first. I've done that and it works but there is a weird behavior when I open more than 10 windows sometimes when I close a window it recreates another window by itself, and sometimes one of the windows closes all of the other opened windows. How to fix this issue, the code has no errors, but it does not work as intended.
I've tried to convert the first child window to a parent window, and if all parent windows are closed the remaining child windows to become parent. This is somewhat successful, but not what I want. Here is the code:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QAction, QFileDialog
from PyQt5.QtGui import QKeySequence
from PyQt5.QtCore import Qt
class WindowManager(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.button = QPushButton("Create New Window", self)
self.button.clicked.connect(self.new_window)
self.setCentralWidget(self.button)
self.children = []
if self.parent() is not None and len(self.parent().children) > 0 and self.parent().children[0] == self:
self.is_first_child = True
else:
self.is_first_child = False
def new_window(self):
window_manager = WindowManager(self)
window_manager.resize(self.size())
window_manager.setWindowModality(Qt.NonModal)
window_manager.setWindowFlag(Qt.Window)
window_manager.create_new_window_on_close = True
self.children.append(window_manager)
window_manager.show()
def closeEvent(self, event):
if self.parent() is None:
if self.children:
if all(child.parent() is not None for child in self.children):
self.children[0].setParent(None)
self.children[0].setWindowModality(Qt.NonModal)
self.children[0].setWindowFlag(Qt.Window)
self.children[0].show()
self.children[0].children = self.children[1:]
self.close()
else:
if self in self.parent().children:
self.parent().children.remove(self)
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window_manager = WindowManager()
window_manager.show()
sys.exit(app.exec_())
Code 2 :
import sys
from random import randint
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QMenu,
QMenuBar,
QPushButton,
QVBoxLayout,
QWidget,
)
class AnotherWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.label = QLabel("Another Window % d" % randint(0, 100))
layout.addWidget(self.label)
self.setLayout(layout)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.windows1 = []
menubar = self.menuBar()
self.file_menu = menubar.addMenu("File")
self.button1 = QPushButton("New")
self.button1.clicked.connect(self.create_window1)
self.file_menu.addAction(self.button1.text(), lambda: self.create_window1())
def create_window1(self):
window = QMainWindow(None)
window.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
menubar = window.menuBar()
menubar.addMenu(self.file_menu)
self.windows1.append(window)
window.show()
def closeEvent(self, event):
event.accept()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
I rewrote your script to fix the bugs, but I removed some unused parts:
is_first_child flag
create_new_window_on_close flag
Unused QKeySequence, QAction and QFileDialog imports
The main problem I found about was the WindowManager.children reference which messed up in the code. From what I could understand, only the parent should contain the current reference to the children list with updated data. Whenever the parent would be closed, this updated reference should be passed into one of the children.
The main flaw was in this line:
def new_window(self):
# ... code ...
self.children.append(window_manager)
# ... code ...
You're always inserting a new child into the current's instance reference of child. That is, if you click on the child QPushButton, you're never updating the parent's children list. You're always updating the current instance one.
In short words: it got confusing. So I reworked that into using a single shared list between all instances of WindowManager. Whenever a parent window is created, it creates it's own list. Whenever a child is created, it acquires the parent's list reference.
Here's my version of your script:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
from PyQt5.QtCore import Qt
from random import randint
# Store taken indexes
taken = []
# If you're on Windows, this might not work unless you use another terminal
# application that allows ansi colors. (default windows console does not
# support it)
red = '\033[91m%s\033[0m'
green = '\033[92m%s\033[0m'
# With this we can open 1000 different windows on our testing environment
# ensuring each window contains a different index value
def uniqueIndex():
idx = randint(0, 1000)
while (idx in taken):
idx = randint(0, 1000)
taken.append(idx)
return idx
class WindowManager(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
# Get an unique identifier (only for testing)
self.index = uniqueIndex()
# If this instance is the parent, create a new shared reference.
if (parent is None):
self.children = []
# Otherwise, acquire the reference from the parent window, and add
# itself inside it.
else:
self.children = parent.children
# print on terminal that we're adding a window
print('%s %d' % (green % 'Adding: ', self.index))
# Update the window title, and add it to the shared children list
self.update_parent(parent)
self.children.append(self)
self.button = QPushButton("Create New Window", self)
self.button.clicked.connect(self.new_window)
self.setCentralWidget(self.button)
self.setMinimumWidth(300)
def new_window(self):
window_manager = WindowManager(self)
window_manager.resize(self.size())
window_manager.setWindowModality(Qt.NonModal)
window_manager.setWindowFlag(Qt.Window)
window_manager.show()
# Used just for testing.
def update_parent(self, parent=None):
if (parent is None):
self.setWindowTitle('Parent %d' % self.index)
else:
self.setWindowTitle('Parent %d: Index %d' % (parent.index, self.index))
self.setParent(parent)
def closeEvent(self, event):
# Remove the self from the shared children list
self.children.remove(self)
# print on the terminal that we're removing a window
print('%s: %d' % (red % 'Removing:', self.index))
# If the array is not empty:
if (self.children):
# Reparent all children based on the current parent (which can be None)
for child in self.children:
if (child.parent() == self):
child.update_parent(self.parent())
# set parent clears all window flags.
child.setWindowModality(Qt.NonModal)
child.setWindowFlag(Qt.Window)
# ensure the child is visible
child.show()
# Ensure we're closing the current window.
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window_manager = WindowManager()
window_manager.show()
sys.exit(app.exec_())
In my MainApp I have a QTreeView populated by items from a QStandardItemModel. By clicking a button I use subprocess.Popen to launch a 3D software (in this case Maya2020). Once Maya is running I execute a snippet of code inside of its script editor to open a widget called SubApp.
I'd like to pass MainApp's model data to SubApp's QTreeView somehow. In my real code when I launch SubApp I use environment variables to send some key values (UUID and list of UUID parents) to reconstruct the model/view again. This feels over complicated and I'm wondering if there's a better way to share data?
My code: (Note! I've included MainApp and SubApp in the same module for simplicity, but these classes are decoupled in the real thing)
main_launch.py
import os
import sys
import subprocess
from Qt import QtWidgets, QtGui
class MainApp(QtWidgets.QWidget):
""" This is the main launcher app that holds the model data
"""
def __init__(self, parent=None):
super(MainApp, self).__init__(parent)
# Model/View
view = QtWidgets.QTreeView()
model = QtGui.QStandardItemModel()
view.setModel(model)
# Populate data
for i in range(3):
parent1 = QtGui.QStandardItem('Parent {}'.format(i))
for j in range(3):
child1 = QtGui.QStandardItem('Child {}'.format(i * 3 + j))
child2 = QtGui.QStandardItem('row: {}, col: {}'.format(i, j + 1))
child3 = QtGui.QStandardItem('row: {}, col: {}'.format(i, j + 2))
parent1.appendRow([child1, child2, child3])
model.appendRow(parent1)
# span container columns
view.setFirstColumnSpanned(i, view.rootIndex(), True)
# GUI
btn_launch = QtWidgets.QPushButton('launch sub app')
btn_launch.clicked.connect(self.on_launch_sub_app)
# Layout
main_layout = QtWidgets.QHBoxLayout(self)
main_layout.addWidget(view)
main_layout.addWidget(btn_launch)
self.setLayout(main_layout)
self.root_path = os.path.join(os.path.dirname(os.path.realpath(__file__))).replace('\\', '/')
# Copy this path when it prints and paste it into "maya_snippet"s "root_path"
print(self.root_path)
def on_launch_sub_app(self):
""" Opens software (maya in this case) and then you launch SubApp from within maya's script editor.
Is there any way to send the model data using subprocess.Popen?
"""
# Maya location
app_exe = r'C:/Program Files/Autodesk/Maya2020/bin/maya.exe'
proc = subprocess.Popen(
[app_exe]
)
class SubApp(QtWidgets.QWidget):
""" Running the "maya_snippet.py" code from within maya will launch this window
"""
def __init__(self, parent=None):
super(SubApp, self).__init__(parent)
# Model/View
view = QtWidgets.QTreeView()
# Would like to set the model from the MainApp
model = QtGui.QStandardItemModel()
view.setModel(model)
# Layout
main_layout = QtWidgets.QHBoxLayout(self)
main_layout.addWidget(view)
self.setLayout(main_layout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainApp()
window.resize(400, 400)
window.show()
sys.exit(app.exec_())
maya_snippet.py (Run this from within Maya to launch SubApp (after you've launched Maya from MainApp))
import sys
# Change root_path to the directory holding main_launch.py
root_path = 'path/to/directory/holding/main_launch'
if not root_path in sys.path:
sys.path.append(root_path.replace('\\', '/')
import main_launch
w = main_launch.SubApp()
w.show()
I am using QFileDialog.getOpenFileName(self,'Remove File', "path", '*.pdf') to select a file and get the path in order to remove it from my application. The issue is the QFileDialog.getOpenFileName window button says 'Open' when selecting a file which will be confusing to the user.
Is there any way to change the button text from 'Open' to 'Remove'/'Delete'
When using the static method QFileDialog::getOpenFileName() the first thing is to obtain the QFileDialog object and for that we use a QTimer and the findChild() method:
# ...
QtCore.QTimer.singleShot(0, self.on_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(...,
options=QtWidgets.QFileDialog.DontUseNativeDialog)
def on_timeout(self):
dialog = self.findChild(QtWidgets.QFileDialog)
# ...
Then you can get the text iterating over the buttons until you get the button with the searched text and change it:
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == "&Open":
btn.setText("Remove")
That will work at the beginning but every time you interact with the QTreeView they show, update the text to the default value, so the same logic will have to be applied using the currentChanged signal from the selectionModel() of the QTreeView but for synchronization reasons it is necessary Update the text later using another QTimer.singleShot(), the following code is a workable example:
import sys
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Press me")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
#QtCore.pyqtSlot()
def on_clicked(self):
QtCore.QTimer.singleShot(0, self.on_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
"Remove File",
"path",
"*.pdf",
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
def on_timeout(self):
dialog = self.findChild(QtWidgets.QFileDialog)
dialog.findChild(QtWidgets.QTreeView).selectionModel().currentChanged.connect(
lambda: self.change_button_name(dialog)
)
self.change_button_name(dialog)
def change_button_name(self, dialog):
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == self.tr("&Open"):
QtCore.QTimer.singleShot(0, lambda btn=btn: btn.setText("Remove"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
The first step can be avoided if the static method is not used and create the dialog using an instance of QFileDialog:
import sys
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Press me")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
#QtCore.pyqtSlot()
def on_clicked(self):
dialog = QtWidgets.QFileDialog(
self,
"Remove File",
"path",
"*.pdf",
supportedSchemes=["file"],
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
self.change_button_name(dialog)
dialog.findChild(QtWidgets.QTreeView).selectionModel().currentChanged.connect(
lambda: self.change_button_name(dialog)
)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
filename = dialog.selectedUrls()[0]
print(filename)
def change_button_name(self, dialog):
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == self.tr("&Open"):
QtCore.QTimer.singleShot(0, lambda btn=btn: btn.setText("Remove"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
While I appreciate the solution provided by #eyllanesc, I'd like to propose a variation.
Under certain circumstances, the code for that answer might fail, specifically:
the delay that X11 suffers from mapping windows;
the checking of localized button strings;
the selection using the file name edit box;
Considering the above, I propose an alternate solution, based on the points above.
For obvious reasons, the main point remains: the dialog must be non-native.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class FileDialogTest(QWidget):
def __init__(self):
super().__init__()
layout = QHBoxLayout(self)
self.fileEdit = QLineEdit()
layout.addWidget(self.fileEdit)
self.selectBtn = QToolButton(icon=QIcon.fromTheme('folder'), text='…')
layout.addWidget(self.selectBtn)
self.selectBtn.clicked.connect(self.showSelectDialog)
def checkSelectDialog(self):
dialog = self.findChild(QFileDialog)
if not dialog.isVisible():
# wait for dialog finalization, as testOption might fail
return
# dialog found, stop the timer and delete it
self.sender().stop()
self.sender().deleteLater()
if not dialog.testOption(dialog.DontUseNativeDialog):
# native dialog, we cannot do anything!
return
def updateOpenButton():
selection = tree.selectionModel().selectedIndexes()
if selection and not tree.model().isDir(selection[0]):
# it's a file, change the button text
button.setText('Select my precious file')
tree = dialog.findChild(QTreeView)
button = dialog.findChild(QDialogButtonBox).button(
QDialogButtonBox.Open)
# check for selected files on open
updateOpenButton()
# connect the selection update signal
tree.selectionModel().selectionChanged.connect(
lambda: QTimer.singleShot(0, updateOpenButton))
def showSelectDialog(self):
QTimer(self, interval=10, timeout=self.checkSelectDialog).start()
path, filter = QFileDialog.getOpenFileName(self,
'Select file', '<path_to_file>',
"All Files (*);;Python Files (*.py);; PNG Files (*.png)",
options=QFileDialog.DontUseNativeDialog)
if path:
self.fileEdit.setText(path)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = FileDialogTest()
ex.show()
sys.exit(app.exec())
Obviously, for PyQt6 you'll need to use the proper Enum namespaces (i.e. QFileDialog.Option.DontUseNativeDialog, etc.).
I have a piece of python code like this:
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
--snip--
self.ui.pushButton.clicked.connect(self.selectFile)
someParameter = someFunction(self.filename) # (1)
def selectFile(self):
self.ui.lineEdit.setText(QtGui.QFileDialog.getOpenFileName())
self.filename = self.ui.lineEdit.text() # I want to use "filename" variable in (1)
--snip--
I want to catch the name of the file which is selected by QFileDialog and do two things; firstly, show the address of the file in a lineEdit widget and secondly, store the address of the file in a variable so I can use it later on the rest of the process. How should I do that, and what is the proper way?
It seems you are not accustomed with object oriented programming.
In object oriented programming, there is a member and method in a Class.
In your case you should define member like this so that you can handle it later. So you should learn about what member is in object oriented programming.
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.filename = ""
self.someParameter = None
--snip--
self.ui.pushButton.clicked.connect(self.selectFile)
def setParameter(self):
self.someParameter = someFunction(self.filename)
def selectFile(self):
self.filename = QtGui.QFileDialog.getOpenFileName()
self.ui.lineEdit.setText(self.filename)
self.setParameter()
--snip--
Edited
Here is some sample code which use QFileDialog.getOpenFileName. Try this.
from PyQt5.QtWidgets import QWidget, QPushButton, QFileDialog, QVBoxLayout, QApplication
from PyQt5 import QtGui
class my_ui(QWidget):
def __init__(self, parent=None):
super(my_ui, self).__init__()
self.filename = ""
self.button1 = QPushButton("show dialog", parent)
self.button2 = QPushButton("do something", parent)
self.button1.clicked.connect(self.show_dialog)
self.button2.clicked.connect(self.do_something)
self.layout = QVBoxLayout()
self.layout.addWidget(self.button1)
self.layout.addWidget(self.button2)
self.setLayout(self.layout)
def show_dialog(self):
self.filename = QFileDialog.getOpenFileName()
print("filename updated: '%s'"%str(self.filename))
def do_something(self):
print("filename = '%s'"%str(self.filename))
app = QApplication([])
sample_ui = my_ui()
sample_ui.show()
app.exec_()
In my application,
I have three same QGroupBoxes with some pushbuttons.
I want to have same names for pushbuttons and acces to them through QGroupBox name.
Is that possible?
QGroupBox_one.button_export
QGroupBox_one.button_import
QGroupBox_two.button_export
QGroupBox_two.button_import
Than I could make method with QGroupBox as parameter and configure buttons easier.
Thanks.
I think a clean way of doing what you want is making a new class (MyQGroupBoxes) that has the push buttons and the configure method you need.
from PyQt4 import QtGui
class MyQGroupBoxes(QtGui.QGroupBox):
def __init__(self, parent):
QtGui.QGroupBox.__init__(self, parent)
self.button_export = QtGui.QPushButton("Export", self)
self.button_import = QtGui.QPushButton("Import", self)
layout = QtGui.QVBoxLayout(self)
self.setLayout(layout)
layout.addWidget(self.button_export)
layout.addWidget(self.button_import)
def config_export(self):
# config your button
pass
def config_import(self):
# config your button
pass
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
my_box1 = MyQGroupBoxes(None)
my_box2 = MyQGroupBoxes(None)
my_boxes = [my_box1, my_box2]
# Config all the boxes
for my_box in my_boxes:
my_box.config_export()
my_box.config_import()
my_box.show()
app.exec_()