Найти - Пользователи
Полная версия: Наследование и расширение методов родительского класса в PyQt5, GUI, Python 3.x
Начало » GUI » Наследование и расширение методов родительского класса в PyQt5, GUI, Python 3.x
1
Jeks
Доброго времени суток

Подскажите как можно унаследовать и расширить все методы суперкласса Ui_Authorization (родительского класса) в подклассе Ui_login (дочернем классе)? Или по-крайней мере расширить метод setupUi суперкласса Ui_Authorization.

Довольно много перекопал информации, но так и не смог понять.
Подскажите как можно расширить методы.

Модуль суперкласса (родительского класса) - Ui_Authorization:
 from PyQt5 import QtCore, QtGui, QtWidgets
 
class Ui_Authorization(object):
    def setupUi(self, Authorization):
        Authorization.setObjectName("Authorization")
        #идет много кода
 
    def retranslateUi(self, Authorization):
        _translate = QtCore.QCoreApplication.translate
       #идет много кода
 
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Authorization = QtWidgets.QMainWindow()
    ui = Ui_Authorization()
    ui.setupUi(Authorization)
    Authorization.show()
    sys.exit(app.exec_())

Модуль подкласса (дочернего класса) - Ui_login
 import Modules.login
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class Ui_login(Modules.login.Ui_Authorization):          # именно в данном подклассе Ui_login нужно расширить методы суперкласса Ui_Authorization
    def setupUi(self):
        Modules.login.Ui_Authorization.setupUi()
        self.login_pushButton.clicked.connect(self.LoginCheck)
        self.logout_pushButton.clicked.connect(self.quit)
        
    def LoginCheck(self):                                          
        print("Здравствуйте!")
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    login = QtWidgets.QMainWindow()
    ui = Ui_login()
    ui.setupUi(login)
    login.show()
    sys.exit(app.exec_())
PEHDOM
Jeks
Подскажите как можно унаследовать
не совсем понятно что вы хотите, создав класс наследник вы и так унаследовали все методы родителя.
Jeks
расширить все методы суперкласса Ui_Authorization
что значит “расширить”? вы хотите переопределить методы родительского класса, но при этом сохранить их изначальный функционал ? ну так вызывайте методы родителя напрямую передавая первым аргументом экземпляр дочернего класса, а потом уже выполняйте отсебятину.
 class A(): # Родитель
    def __init__(self):
        print('I`m class A method')
class B (A): #Наследник
    def __init__(self): # Переопределяем __init__
        super().__init__()  #  Вызываем __init__ родителя. Можно записать так,
        A.__init__(self)    # А можно и так записать.
        print('I`m class B method')
b= B()
>>> 
I`m class A method
I`m class A method
I`m class B method
>>> 
Jeks
PEHDOM
что значит “расширить”?
Спасибо за помощь, уважаемый PEHDOM. При попытке “расширить” (вызвать метод родительского класса (то есть все его атрибуты) и добавить в него еще новые атрибуты, т.н. отсебятину) метод setupUi следующим образом:
 import Modules.login
import Modules.SystemOfUsersManagement
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class Ui_login(Modules.login.Ui_Authorization):
    def setupUi(self):
        Modules.login.Ui_Authorization.setupUi(self, Modules.login.Authorization)       # вот та самая line 17
        self.login_pushButton.clicked.connect(self.LoginCheck)
        self.logout_pushButton.clicked.connect(self.quit)
    def LoginCheck(self):                                          
        print("Здравствуйте!")
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    login = QtWidgets.QMainWindow()
    ui = Ui_login()
    ui.setupUi(login)
    login.show()
    sys.exit(app.exec_())
программа выдает ошибку в консоли:
   File "C:/Users/USER/Desktop/StatEdu/login/main.py", line 17, in setupUi
    Modules.login.Ui_Authorization.setupUi(self, Modules.login.Authorization)
AttributeError: module 'Modules.login' has no attribute 'Authorization'
Однако, в случае если убрать аргумент Modules.login.Authorization в методе setupUi, то выдает такую ошибку:
   File "C:/Users/USER/Desktop/StatEdu/login/main.py", line 17, in setupUi
    Modules.login.Ui_Authorization.setupUi(self)
TypeError: setupUi() missing 1 required positional argument: 'Authorization'
Соответственно, если убрать все аргументы, то он будет требовать их оба:
   File "C:/Users/USER/Desktop/StatEdu/login/main.py", line 17, in setupUi
    Modules.login.Ui_Authorization.setupUi()
TypeError: setupUi() missing 2 required positional arguments: 'self' and 'Authorization'
Обязательно ли применять конструктор __init__ в родительском и дочернем классах? Пытался также через этот конструктор __init__ делать - также выдает ошибку, как и в первом случае: AttributeError: module ‘Modules.login’ has no attribute ‘Authorization’. Как можно избавиться от ошибки?
PEHDOM
ну смотрите давайте по порядку:
Modules.login.Ui_Authorization.setupUi(self, Modules.login.Authorization)
понятно что первый аргумент это self, тоесть наш инстанс класса Ui_login, а второй аргумен у вас что? Если листинг в первом посте это весь модуль Modules.login то оно естественно вам выдаст атрибут еррор, так как нету там атрибута Authorization. Если посмотреть на код в Modules.login то:
 #
class Ui_Authorization(object):
    def setupUi(self, Authorization):
......
if __name__ == "__main__":
    ......
    Authorization = QtWidgets.QMainWindow()
    ui = Ui_Authorization()
    ui.setupUi(Authorization)
   .....
Мы видим что метод Ui_Authorization.ui.setupUi кушает вторым аргументом инстанс класса QtWidgets.QMainWindow(), а вы ему скармливаете неизвестно что.
по идее вам нужно делать както так:
 ...
class Ui_login(Modules.login.Ui_Authorization):
    def setupUi(self, auth):
        Modules.login.Ui_Authorization.setupUi(self, auth)       # вот та самая line 17
 .....
    login = QtWidgets.QMainWindow()
    ui = Ui_login()
    ui.setupUi(login)

Jeks
Обязательно ли применять конструктор __init__ в родительском и дочернем классах?
необязательно, все зависит от задачи, но это сильно облегчает жизнь, если ваши классы не на две строчки и наследование состоит не из одного поколения. Возьмите тот же PyQt. есть QObject, от него наследует QWidget, от него QAbstractButton, а от него например QPushButton. Вы хотите создать свою кнопку отнаследовав QPushButton. Чтобы она унаследовала все атрибуты и методы всех родителей начиная от QObject и заканчивая QPushButton вам нужно написать всего лишь одну строчку: super().__init__(), вместо того чтобы лазить в документацию/исходники и смотреть какие же методы нужно дергнуть из QPushButton , какие из QWidget, а какие из QObject чтобы ваша кнопка хоть както заработала.
А если у вас сложное наследование(например от двух и более классов), то вообще “ховайсь у жито” при вашем подходе.



Jeks
PEHDOM
по идее вам нужно делать как-то так
Огромное спасибо, дружище PEHDOM)) Заработало) Можно еще 2 вопроса, пожалуйста, ибо в моем окружении нету профессионалов вашего уровня.
1)Как можно вызвать все методы класса Management в методе Admin класса Ui_login, чтобы открыть окно класса Management? При попытке вызвать класс Management подобным образом self.newWin.show() выдается ошибка в консоли: AttributeError: ‘Management’ object has no attribute ‘show’. В случае, если вызвать класс Management с одним из его методов, он открывает окно, но другие методы класса Management не работают. Это представлено все в коде ниже:
 import Modules.login
import Modules.SystemOfUsersManagement
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class Ui_login(Modules.login.Ui_Authorization):
    def setupUi(self, auth):
        Modules.login.Ui_Authorization.setupUi(self, auth)
        self.login_pushButton.clicked.connect(self.LoginCheck)
        self.logout_pushButton.clicked.connect(login.close)
        
    def LoginCheck(self):                                           # Процесс авторизации пользователя
        username = self.login_lineEdit.text()
        password = self.password_lineEdit.text()
        connection  = sqlite3.connect("login.db")
        result = connection.execute("SELECT * FROM USERS WHERE Логин = ? AND Пароль = ?", (username, password))
        if (len(result.fetchall()) > 0):
            self.Admin()
        else:
            self.showMessageBox('Ошибка авторизации пользователя', 'Введенные вами данные неверны. Введите правильный пароль и логин или обратитесь к администратору.')  
            
    def Admin(self):          # Открывает Окно Системы Менеджмента Пользователей для Администратора
        login.close()
        self.newWin = Management()
        self.newWin.ManagWindowShow().show()     # Если убрать ManagWindowShow() он выдает ошибку AttributeError: 'Management' object has no attribute 'show'
 
    def showMessageBox(self, title, message):                        # Выводит сообщение о неверной авторизации
        msgBox = QtWidgets.QMessageBox()
        # вызов MsgBox
 
 
class Management(Modules.SystemOfUsersManagement.Ui_Admin):
    def ManagWindowShow(self):                                             # Показывает форму второго окна
        self.AdminWindow = QtWidgets.QMainWindow()
        self.ui = Modules.SystemOfUsersManagement.Ui_Admin()
        self.ui.setupUi(self.AdminWindow)
        self.AdminWindow.show()
     
    def setupUi(self, adm):
        Modules.SystemOfUsersManagement.Ui_Admin.setupUi(self, adm)
        self.exit_pushButton.clicked.connect(self.Back)                  # Возвращение к окну авторизации
     
    def Back(self):                                                 # Возвращает к окну авторизации пользователя
        AdminWindow.close()
        OldWin = Ui_login()
        OldWin.show()
 
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    login = QtWidgets.QMainWindow()
    ui = Ui_login()
    ui.setupUi(login)
    login.show()
    sys.exit(app.exec_())
И вот код суперкласса Ui_Admin у которого дочерний класс Management. Однако думаю он не особо нужен для решения проблемы:
 from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Admin(object):
    def setupUi(self, Admin):
        Admin.setObjectName("Admin")
        # Идет много кода
    def retranslateUi(self, Admin):
        _translate = QtCore.QCoreApplication.translate
        # Идет много кода
 
 
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Admin = QtWidgets.QMainWindow()
    ui = Ui_Admin()
    ui.setupUi(Admin)
    Admin.show()
    sys.exit(app.exec_())
2)В случае если я хочу создать нового пользователя для этой программы без прав администратора, чтобы он заходил в третье окно, которое я пока не создал, при этом чтобы он не заходил во второе окно для администратора класса Management, как его можно отделить от администратора? Вот здесь допустим я создам нового обычного пользователя:
 import sqlite3
def createTable():
    connection = sqlite3.connect("login.db")
    
    connection.execute("CREATE TABLE USERS (Логин TEXT NOT NULL, Пароль TEXT)")
    connection.execute("INSERT INTO USERS VALUES (?, ?)", ("Администратор", "Администратор"))
    connection.execute("INSERT INTO USERS VALUES (?, ?)", ("Пользователь", "Пользователь"))
    connection.commit()
    result = connection.execute("SELECT * FROM USERS")
    for data in result:
        print("Логин : ", data[0])
        print("Пароль : ", data[1])
        connection.close()
createTable()
А в коде окна первого вопроса, т. е. в методе def LoginCheck класса Ui_login идет процесс авторизации администратора. Для авторизации обычного пользователя будет нужно создать новый метод или в методе авторизации администратора вести условный оператор if с условием разделения на обычного пользователя и администратора? Как можно это примерно реализовать?
PEHDOM
Jeks
1)Как можно вызвать все методы класса Management в методе Admin класса Ui_login, чтобы открыть окно класса Management? При попытке вызвать класс Management подобным образом self.newWin.show() выдается ошибка в консоли: AttributeError: ‘Management’ object has no attribute ‘show’
Ну все правильно ,у вас в классе Management есть метод show()? Нету, а у его родителя Ui_Admin? тоже нету , а у родителя Ui_Admin object? Нет. собственно вот вы и получаете AttributeError. А все потому что ваши классы не наследуют QtWidgets.QMainWindow, а являються обертками над этим классом. Подобный код , насколько я знаю любит генерировать КуТеДизайнер. Поэтому ваши классы содержат только те атрибуты и методы которые вы сами написали. А все методы QMainWindow типа show() и тд. у вас в обьекте котороый вы подаете вторым аргументом в setupUi.
Опять же по логике вещей если вы хотитет использовать композицию\агрегацию. то вам отпять же нужно сначала создать обьект типа QMainWindow а потом скормить его уже вашему классу-обертке.
 def Admin(self):          # Открывает Окно Системы Менеджмента Пользователей для Администратора
        login.close()
        ''' Вот тут ИМХО вообще неправильно, ваш класс, в данном случае,
         не должен знать что есть некая глобальная переменная login.
         По хорошему нужно както так:
         class Ui_login(Modules.login.Ui_Authorization):
         ...
             def setupUi(self, auth):
                self.loginWindow = auth  #а еще лучше вынести это в __init__
             ....
             def Admin(self):
                 self.loginWindow.close()
             ...
         '''
        self.managmentWindow = QtWidgets.QMainWindow() #1 И эти 4 строчки вам придеться писать каждый раз при создании нового обьекта Management()
        self.newWin = Management()                     #2 А вообще нужно отказываться от подобного, ваши классы должны быть максимально независимы
        self.newWin.setupUi(self.managmentWindow)      #3 и не знать о существовании  друг друга
        self.managmentWindow.show()                    #4 Используйте систему сигналов-слотов из КуТе для взаимодействия между окнами.
 
ну там и дальше косяк на косяке … уже не стал разбитрть.
Jeks
Для авторизации обычного пользователя будет нужно создать новый метод или в методе авторизации администратора вести условный оператор if с условием разделения на обычного пользователя и администратора? Как можно это примерно реализовать?
Все зависит насколько интерфейс администратор отличается от интерфейса пользователя. Если они кардинально отличаются, то просто модуль авторизации должен вызывать разные методы в зависимости от прав пользователя. Если пользователь в группе “Администраторы” - показываем одно окно, если в группе“ пользователи” - другое.
Если интерфейс пользователя является урезаным интерфейсом администратора, то нужно писать динамически формируемый интерфейс, зависимый от группы пользователя.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB