Многостраничное приложение PyQt5: разделение основного класса на несколько файлов?

#python #pyqt5

#python #pyqt5

Вопрос:

Я пытаюсь создать довольно сложное приложение с графическим интерфейсом, используя PyQt5 и python 3.8, и я застрял на том, как разделить код на управляемые файлы. Я новичок в программировании с графическим интерфейсом и объектно-ориентированном программировании в целом и перепробовал несколько решений, которые смог найти в Интернете, но ни одно из них не работало на меня. Поэтому я прошу прощения, если этот вопрос задавался много раз раньше, но я думаю, что мне нужны некоторые подсказки, специально адаптированные к моему проекту.

Мне пока не разрешено публиковать изображения, поэтому вот ссылка, как выглядит приложение вместо этого: графический интерфейс приложения

В моем приложении есть боковая панель, которая всегда видна, и многоуровневый виджет, который содержит несколько страниц (видимый по ссылке выше — 14 WEL). У меня есть один main.py файл, который я хочу использовать для настройки пользовательского интерфейса и подключения кнопок всех страниц. Затем я хотел бы иметь несколько файлов .py для обработки пользовательского ввода и вычислений (по одному файлу на страницу). У меня также есть helper_functions.py файл для хранения нужных мне функций более чем на одной странице. Что сработало до сих пор, так это импортировать класс страницы (например, OutWelPageControl) в класс MainWindow в init, но тогда я, похоже, не могу вызвать createPreview() из GetFile() в OutWelPageControl (приложение завершается с кодом = 1073741845, когда я нажимаю кнопку, которая запускает GetFile()). Без вызова createPreview(self, welFiles_num) это действительно работает.

main.py:

 import sys
import os
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
from helper_functions import *

# GUI FILE
from ui_main import Ui_MainWindow

class MainWindow(qtw.QMainWindow):
    def __init__(self):
        qtw.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        ## PAGE CONNECTION
        ########################################################################
        self.ui.btn_out_wel.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.page_out_wel))
        #... (other pages)

        
        # This is probably wrong
        from out_wel import OutWelPageControl
        
        ## BUTTONS
        # How I want it to work
        self.ui.btn_file.clicked.connect(lambda: OutWelPageControl.getFile(self))

        self.show()
    
if __name__ == "__main__":
    app = qtw.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())
 

helper_functions.py:

 from main import *

class HelperFunctions(MainWindow):
    def getFile(self):
        fnames = qtw.QFileDialog.getOpenFileNames(self, 'WEL-Datei öffnen', 'C:\',"*.WEL")[0]
        return (fnames)
 

Страница out_wel.py:

 from main import *
from helper_functions import *

class OutWelPageControl(MainWindow):
    def getFile(self):
        welFiles = HelperFunctions.getFile(self)

        # Label Input File
        welFiles_string = []
        for wel in welFiles:
            welFiles_string.append(os.path.basename(wel))
        welFiles_string2 = ', '.join(welFiles_string)
        self.ui.lbl_filepath.setText(welFiles_string2)

        welFiles_num = []
        for wel in welFiles:
            welFiles_num.append(os.path.splitext(os.path.basename(wel))[0])
        
        # Call another function
        createPreview(self, welFiles_num)
    
    def createPreview(self, welFiles_num):
        pass
 

Итак, мой вопрос в основном заключается в том, как я могу разделить код приложения, чтобы каждая страница имела свой собственный файл .py и при этом могла изменять элементы пользовательского интерфейса? Должны ли файлы страниц содержать подклассы MainWindow или есть другой вариант, чтобы заставить его работать?

Ответ №1:

Здесь довольно много кода без какой-либо конкретной проблемы, но я могу попытаться дать несколько общих советов и посмотреть, поможет ли это вам каким-либо образом.

  1. В helper_functions вы не можете иметь from main import * as при импорте helper_functions в main, это приводит к циклическому импорту (они импортируют друг друга снова и снова)
  2. Также в helper_functions это не обязательно должен быть класс, если все, что вам нужно, это несколько функций, доступных на разных страницах. Вы можете просто иметь там функции и вызывать их с помощью helper_functions.func_name(args) .
  3. from out_wel import OutWelPageControl должно быть в верхней части файла .py, а не внутри инициализации основного класса
  4. Для импорта и использования кода пользовательского интерфейса используйте двойное наследование, чтобы вам не приходилось использовать self.ui везде:
 class MainWindow(qtw.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self.setup_ui()
 
  1. Вы не должны создавать подклассы своего основного класса в других классах, которые вы создали для разных страниц.
  2. Я хотел бы взглянуть на эту страницу о том, как использовать сложенные виджеты. Но я полагаю, что вам нужно было бы подклассировать QWidget для ваших разных классов «страниц», чтобы они были виджетами, которые вы могли добавить в виджет с накоплением.
  3. Если вы создаете классы, вы должны создавать экземпляры объектов, например, в main вы должны иметь self.out_wel_page = OutwelPageControl()
  4. Если вам нужна какая-то функциональность родительского виджета в функции дочернего виджета, вы всегда можете перейти self от родительского виджета к дочернему

Дайте мне знать, если что-нибудь из этого помогло, не смог найти что-то конкретное, чтобы исправить проблемы, с которыми вы столкнулись, но хотел попытаться помочь.

Комментарии:

1. Большое спасибо, я ценю любые предложения! Я подробнее рассмотрю ссылку, которую вы предложили, я чувствую, что есть много вещей, которых я еще не знаю. Я не обязательно хочу создавать подклассы, если есть лучший способ сделать это. Теперь я использовал функции как для функций helper_functions, так и для функций страницы, и, похоже, это работает! Поэтому я отмечаю этот вопрос как решенный. Пункт 7: отсутствуют ли скобки OutwelPageControl(), или это какая-то концепция, с которой я еще не знаком? Еще раз спасибо, что указали мне правильное направление!

2. Рад быть хоть немного полезным, все это очень пугает при обучении кодированию, так как есть чему поучиться, и я могу многое понять. И нет, хороший улов, он предназначен для того, чтобы иметь скобки, которые я отредактирую