Can you explain why the openfile.py file does not open if you call it via main.py. When you click on the file menu and also click the open test button, the callee is immediately destroyed. Tell me the solution to this problem.

Main.py file

import sys import openfile from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * def center(): qr = root.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) root.move(qr.topLeft()) app = QApplication(sys.argv) root= QWidget() hbox = QHBoxLayout(root) topleft = QFrame(root) topleft.setFrameShape(QFrame.StyledPanel) topleft.resize(15,0) topright = QFrame(root) topright.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(topleft) splitter1.resize(0,20) splitter1.addWidget(topright) hbox.addWidget(splitter1) root.setLayout(hbox) root.setFixedSize(1000,1000) center() root.setWindowTitle('QSplitter') menubar = QMenuBar() exitAction = QAction( 'Открыть тест', root) exitAction.triggered.connect(openfile.openfilebox) fileMenu = menubar.addMenu('File') fileMenu.addAction(exitAction) hbox.setMenuBar(menubar) root.show() sys.exit(app.exec_()) 

Openfile.py file

 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * def openfilebox(): def center(): qr = windowsroot.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) windowsroot.move(qr.topLeft()) def setchoise(choise): print(choise.text()) windowsroot= QWidget() hbox = QHBoxLayout(windowsroot) topleft = QFrame(windowsroot) topleft.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(topleft) hbox.addWidget(splitter1) windowsroot.setLayout(hbox) choise = QListWidget(topleft) windowsroot.button_group = QButtonGroup() for b in range(30): choise.addItems([str(b)+'\n']) choise.resize(700,680) choise.setFont(QFont('Times', 13)) choise.itemDoubleClicked.connect(setchoise) choise.show() windowsroot.setFixedSize(400,700) windowsroot.setWindowTitle('Файл') windowsroot.show() 
  • one
    The question is not: 1) the structure of the project, 2) the error that arose in you. UPD. I opened, the main thing is that the scripts are in the same folder. But you have one problem in the code, because of which the widget window in openfilebox will be closed - the object reference to windowsroot will be destroyed after the function is executed, there are several ways and the easiest function to open is not the widget, but the dialog. But I would advise you to create your own class and work with it or in extreme cases make windowsroot global - gil9red
  • @ gil9red how to understand global i. just write to main.py global windowsroot ? I do not really understand how to make the division into frames in the dialog box so that you can bring it as an example. Thank you - Twiss
  • those. That variable should not be local inside the function, for example, put the variable to the level of the openfile.py module. But this is more extreme, the previous options are better, and by an order of magnitude - gil9red
  • @ gil9red Can't 2 windows open at once when I open main.py? if I take it out of the function - Twiss
  • @ gil9red can give an example on this code, but it’s not quite clear to me how it should work at all - Twiss

1 answer 1

If you make an application canonical, consider the correct way, then this is through classes and objects, i.e. OOP.

In the example, I showed how to create your own widgets, how to open another from one window, how to send events to the first through signals from the second widget:

 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * def log_uncaught_exceptions(ex_cls, ex, tb): text = '{}: {}:\n'.format(ex_cls.__name__, ex) import traceback text += ''.join(traceback.format_tb(tb)) print(text) QMessageBox.critical(None, 'Error', text) quit() import sys sys.excepthook = log_uncaught_exceptions class FileBox(QWidget): new_item_clicked = pyqtSignal(str) def __init__(self): super().__init__() self.setWindowTitle('Файл') self.choise = QListWidget() self.choise.setFont(QFont('Times', 13)) self.choise.addItems(['{}\n'.format(i) for i in range(30)]) self.choise.itemDoubleClicked.connect(self._on_set_choise) top_left = QFrame() top_left.setFrameShape(QFrame.StyledPanel) layout_top_left = QVBoxLayout() layout_top_left.addWidget(self.choise) top_left.setLayout(layout_top_left) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(top_left) hbox = QHBoxLayout() hbox.addWidget(splitter1) self.setLayout(hbox) def _on_set_choise(self, item): text = item.text() print(text) self.new_item_clicked.emit(text) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('MainWindow Test') self.my_left_label = QLabel('<NULL>') self.my_left_label.setFont(QFont('Times', 13)) self.my_right_label = QLabel('<NULL>') self.my_right_label.setFont(QFont('Times', 13)) self.file_box = FileBox() self.file_box.setFixedSize(400, 700) self.file_box.choise.itemDoubleClicked.connect(lambda item: self.my_left_label.setText(item.text())) self.file_box.new_item_clicked.connect(lambda text: self.my_right_label.setText(text)) top_left = QFrame() top_left.setFrameShape(QFrame.StyledPanel) layout_top_left = QVBoxLayout() layout_top_left.addWidget(self.my_left_label) top_left.setLayout(layout_top_left) top_right = QFrame() top_right.setFrameShape(QFrame.StyledPanel) layout_top_right = QVBoxLayout() layout_top_right.addWidget(self.my_right_label) top_right.setLayout(layout_top_right) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(top_left) splitter1.addWidget(top_right) self.setCentralWidget(splitter1) menu_bar = QMenuBar() file_menu = menu_bar.addMenu('File') action_exit = file_menu.addAction('Открыть тест') action_exit.triggered.connect(self._on_open_file_box) self.setMenuBar(menu_bar) def _on_open_file_box(self): self.file_box.show() def center(self): geometry = self.frameGeometry() pos = QDesktopWidget().availableGeometry().center() geometry.moveCenter(pos) self.move(geometry.topLeft()) if __name__ == '__main__': app = QApplication(sys.argv) mw = MainWindow() mw.resize(800, 600) mw.center() mw.show() sys.exit(app.exec_()) 

If you import only the necessary objects:

 from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtWidgets import QApplication, QWidget, QListWidget, QFrame, QVBoxLayout, QSplitter, QHBoxLayout, QMessageBox, QMainWindow, QLabel, QMenuBar, QDesktopWidget from PyQt5.QtGui import QFont 

Either you need to import a Qt module, and for each object that applies to it to assign a module: QWidget -> QtWidgets.QWidget

 from PyQt5 import QtCore from PyQt5 import QtWidgets from PyQt5 import QtGui 

enter image description here


The corrected code from the question, which uses not a widget, but a modal dialog: It suffices to correct openfile.py:

 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * def openfilebox(): def center(): qr = windowsroot.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) windowsroot.move(qr.topLeft()) def setchoise(choise): print(choise.text()) windowsroot = QDialog() hbox = QHBoxLayout(windowsroot) topleft = QFrame(windowsroot) topleft.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(topleft) hbox.addWidget(splitter1) windowsroot.setLayout(hbox) choise = QListWidget(topleft) windowsroot.button_group = QButtonGroup() for b in range(30): choise.addItems([str(b)+'\n']) choise.resize(700,680) choise.setFont(QFont('Times', 13)) choise.itemDoubleClicked.connect(setchoise) choise.show() windowsroot.setFixedSize(400,700) windowsroot.setWindowTitle('Файл') windowsroot.exec() 

You need to import after creating QApplication, since Widgets can't exist without QApplication, and in openfile.py, the widget will just be created when importing

in main.py:

 ... app = QApplication(sys.argv) # Сначала нужно создать QApplication import openfile root= QWidget() ... 

Implementation through a global variable, you need to correct the code in both files.

Remove windowsroot from a function, making it global (code is somehow working, but you don’t need to do that).

openfile.py:

 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * windowsroot = QWidget() def openfilebox(): def center(): qr = windowsroot.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) windowsroot.move(qr.topLeft()) def setchoise(choise): print(choise.text()) hbox = QHBoxLayout(windowsroot) ... 
  • Why not do so? How does that affect speed? - Twiss
  • one
    @ Dmitri, deal in global variables. They themselves are not bad, but the code makes it more confusing, especially if their value changes somewhere inside. It's very easy to make a mistake with them. It is better to use local variables, since you need to think about them in their field of view. - gil9red
  • Many thanks for the explanation. This question is certainly not in this topic, but you don’t know how to make a Qlistwidget interval, Qlistwidget I’ll have it as a digit output and '\n' goes) - Twiss
  • one
    Not sure I understood, probably this: doc.qt.io/qt-4.8/qlistview.html#spacing-prop If you create a question and leave a link, I can answer with code and example - gil9red
  • one
    @Reishin, well, how many classes with the Q prefix have you seen and are you using in your code? Oh. And in general, if this is bad, then why hasn’t this import been removed yet? And that issue is more than 10 years old, during which time there could be a lot of things to change. And I will include in the answer import with the specified objects - gil9red