Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a [RSS Feed]

#1 Апрель 19, 2017 08:52:06

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Оффтоп

PEHDOM
что конкретно непонятно?
Возьмём Ваш код (я пониамю, что он переделывался из моего, но всё равно):
  # -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        names_pole = ['12','7','4']
        for i,name in enumerate(names_pole):
            pole = QtGui.QLineEdit(name)
            self.grid.addWidget(pole,i,0)
            pole.textChanged.connect(self.on_start) # сигнал изм текста
            pole = QtGui.QLineEdit()
            self.grid.addWidget(pole,i,1)
        # КНОПКИ
        names_button = ['Copy', 'Copy', 'Copy']
        for i, name  in enumerate(names_button):
            button = QtGui.QPushButton(name+str(i))
            self.grid.addWidget(button, i,2)
            button.clicked.connect(self.on_click)
        self.setLayout(self.grid)
    def on_start(self):
        pole = self.sender()                #Лайн едид отправитель сигнала
        idx = self.grid.indexOf(pole)       # индекс отправителя сигнала
        location = self.grid.getItemPosition(idx) # положение в гриде
        poleX2 = self.grid.itemAtPosition(location[0],location[1]+1).widget() # соседнее поле
        poleX2.setText(pole.text()*2)
        print('старт', pole.text()*2)
    def on_click(self):
        button = self.sender()
        idx = self.grid.indexOf(button)
        location = self.grid.getItemPosition(idx)
        pole = self.grid.itemAtPosition(location[0],location[1]-1).widget()
        print(pole.text(),'клик')
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.show()
sys.exit(app.exec_())
Здесь написано
 self.grid = QtGui.QGridLayout()
Почему не написать
 grid = QtGui.QGridLayout()
?
Ведь self должен подставится автоматом?

Вот код пользователя vic:
  #!/usr/bin/env python
#-*-coding:utf-8-*-
from PyQt4.Qt import *
class Widget(QWidget):  # Класс Widget  наследует класс QWidget
    def __init__(self): # Создаёт конструктор класса
        QWidget.__init__(self)
        self.edit1 = QLineEdit() # Создаём верхнее поле
        self.edit2 = QLineEdit() # Создаём нижнее поле
        self.lbl = QLabel() # Создаём текстовую строку
        self.btn = QPushButton("Calc") # Создаём кнопку с именем calc
        # Блок задаёт расположение виджетов по вертикали
        self.lay = QVBoxLayout(self) 
        self.lay.addWidget(self.edit1)
        self.lay.addWidget(self.edit2)
        self.lay.addWidget(self.lbl)
        self.lay.addWidget(self.btn)
        
        self.edit2.returnPressed.connect(self.on_click) # Вернуть при нажатии - сигнал
        # обработчик - соединить
        self.btn.clicked.connect(self.on_click)
    def on_click(self):
        self.lbl.setText('Value: '+str(float(self.edit1.text())*float(self.edit2.text())))
if __name__=="__main__":
    app = QApplication([])
    w = Widget()
    w.move(0,0)
    w.resize(400,100)
    w.show()
    app.exec_()
Везде стоят self'ы.

А это с
wiki.python.su
 #!/usr/bin/python
# fontdialog.py
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class FontDialog(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        hbox = QtGui.QHBoxLayout()
        self.setGeometry(300, 300, 250, 110)
        self.setWindowTitle('FontDialog')
        button = QtGui.QPushButton('Dialog', self)
        button.setFocusPolicy(QtCore.Qt.NoFocus)
        button.move(20, 20)
        hbox.addWidget(button)
        self.connect(button, QtCore.SIGNAL('clicked()'), self.showDialog)
        self.label = QtGui.QLabel('Knowledge only matters', self)
        self.label.move(130, 20)
        hbox.addWidget(self.label, 1)
        self.setLayout(hbox)
    def showDialog(self):
        font, ok = QtGui.QFontDialog.getFont()
        if ok:
            self.label.setFont(font)
app = QtGui.QApplication(sys.argv)
cd = FontDialog()
cd.show()
app.exec_()
Здесь есть такая строчка:
  self.label = QtGui.QLabel('Knowledge only matters', self)
Здесь с селфом вообще не понятно.

Офлайн

#2 Апрель 19, 2017 09:06:07

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Kyrym
Это я знаю. Вопрос в том, как это применять на практике. Я читал, про self, но пока так и не понял.
Так без понимания, будет очень трудно.
Попробую объяснить, в скобках буду указывать аналогию реального мира:
К примеру создадим класс (чертеж) “Тумбочка”, созданные объекты (тумбочки) этого класса (чертежа) могут быть с двумя или тремя ящиками (на выбор заказчика).
Приходит в магазин Иван и хочет купить такую тумбочку с двумя ящиками, а за ним следом заходит Илья, и ему нужна тумбочка с тремя ящиками. Продавец записывает пожелания заказчиков (Ивана и Ильи) и отправляет заявки сборщику.
 class Тумбочка():
    ящики = None
    def __init__(self, кол_ящ = None): 
        self.ящики = кол_ящ
тумбочка_Ивана = Тумбочка(2)
тумбочка_Ильи = Тумбочка(3)

В данном примере при создании объекта “тумбочка_Ивана”, под self будет подразумеваться именно “тумбочка_Ивана”, аналогично и для “тумбочка_Ильи”.
Допустим, если бы в магазине работал ну очень тупой сборщик и ему бы передали чертеж в котором нарисована тумбочка без ящиков и отсутствует информация, что они там вообще могут быть. Чтобы он тогда сделал, когда ему продавец прислал бы заявку в котором сказано: “Ивану нужна тумбочка с двумя ящиками”? (конечно же ничего бы он не сделал). В коде это будет выглядеть так
 class Тумбочка():
    ящики = None
тумбочка_Ивана = Тумбочка(2)
тумбочка_Ильи = Тумбочка(3)

Надеюсь будет понятно, хоть немного (если что спрашивайте). Названия переменных, функций и классов дал на русском только для лучшего понимания (в реальности так делать НЕЛЬЗЯ), в некоторых моментах я мог не совсем правильно выразиться, так что извиняйте.

Офлайн

#3 Апрель 19, 2017 09:55:27

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Мне кажется, стоило написать так:

 class Тумбочка():
    def __init__(self, кол_ящ = None): 
        self.ящики = кол_ящ
тумбочка_Ивана = Тумбочка(2)
тумбочка_Ильи = Тумбочка(3)
print('тумбочка_Ивана = ',тумбочка_Ивана.ящики)
print('тумбочка_Ильи = ',тумбочка_Ильи.ящики)

Строчка “ящики = None”, думаю, не нужна.
Идея примера мне понравилась. А почему же здесь self автоматически не назначается для ящиков? Типа:
“ящики = кол_ящ”, а программа бы сама сделала “self.ящики = кол_ящ”, ведь в описании метода мы заложили self: “def __init__(self, кол_ящ = None):”?

MrViktor
чертеж в котором нарисована тумбочка без ящиков и отсутствует информация, что они там вообще могут быть.
Да, это понятно, вопрос в том, когда для этой переменной нужно писать self (если он ставится автоматом), а когда нет?

классов дал на русском только для лучшего понимания (в реальности так делать НЕЛЬЗЯ)
Если писать для себя, то так делать всё-таки можно )))

Отредактировано Kyrym (Апрель 19, 2017 09:58:25)

Офлайн

#4 Апрель 19, 2017 11:01:26

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Kyrym
Строчка “ящики = None”, думаю, не нужна.
Давайте тогда на базе этого примера и продолжим.
Буду писать возможно сильно подробно, но это думаю будет плюсом.
Когда мы создаем экземпляр класса (объект) тумбочка_Ивана
 тумбочка_Ивана = Тумбочка(2)
то у нас сначала создается объект соответствующий классу (чертежу), т.е. у нас будет создан объект тумбочка_Ивана с атрибутом Ящики (это в моем случае), если же мы сделаем как написали Вы (уберем строчку “ящики = None”) то создается объект тумбочка_Ивана но без атрибута.
Дальше вызывается метод __init__ (так сказать конструктор класса) и в него передаются аргументы self и кол_ящ, так же у аргумента кол_ящ есть значение по умолчанию None. Теперь я постараюсь описать происходящее подробней.
Как я говорил ранее self - указывает на определенный объект и получается, что в метод (можно прочесть как функцию) передаются следующие аргументы self = тумбочка_Ивана, кол_ящ = 2, дальше у нас идет простое присвоение тумбочка_Ивана.ящики = 2 (опять же это в моем случае), в Вашем варианте будет создан атрибут ящики со значением 2. В данном примере нормально будут работать и Ваш и мой вариант, но как правило лучше сразу описать необходимые атрибуты, иначе при дальнейшей доработке могут пойти глюки. Для примера, доработаем наш класс
 class Тумбочка():
    ящики = None
    def __init__(self, кол_ящ = 2):
        if кол_ящ != 0:
            self.ящики = кол_ящ
Тогда мой вариант продолжит работать, а Ваш уже нет.

Kyrym
Типа:
“ящики = кол_ящ”, а программа бы сама сделала “self.ящики = кол_ящ”
Потому что, self.ящики = 2 если опять же перенести это в реальный мир, для человека сборщика будет звучать так: “Собрать тумбочку_Ивана по чертежу Тумбочка и сделать в ней два ящика”, а запись ящики = 2 для него будет звучать так “дочертить на чертеже Тумбочка два ящика” - тут мы услышим весь матерный запас сборщика (т.к. он не чертежник) Но это все конечно утрированно, но по сути верно.

Офлайн

#5 Апрель 19, 2017 11:51:14

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Kyrym
Здесь написано
self.grid = QtGui.QGridLayout()
Почему не написать
grid = QtGui.QGridLayout()
?
Ведь self должен подставится автоматом?
У-у-у как у вас все запущено…..
Вам пожалуй стоит начать с азов так сказать. В пайтоне есть так называемая область видимости переменных. Область видимости тесно связана с операциями присваивания.
Имена появляются в тот момент, когда им впервые присваиваются некоторые значения, и прежде чем имена смогут быть использованы, им необходимо присвоить значения. Поскольку имена не объявляются заранее, интерпретатор Python по местоположению операции присваивания связывает имя с конкретным пространством имен.
По умолчанию все имена, значения которым присваиваются внутри функции, ассоциируются с пространством имен этой функции.
Имена, определяемые внутри инструкции def, видны только программному коду внутри инструкции def. К этим именам нельзя обратиться за пределами функции.
В любом случае область видимости переменной (где она может использоваться) всегда определяется местом, где ей было присвоено значение, и никакого отношения не имеет к месту, откуда была вызвана функция или осуществлена операция изменения объекта.
Подробнее расписано тут например https://foxford.ru/wiki/informatika/oblasti-vidimosti-peremennyh-v-python
теперь давайте посмотрим что получиться если вы напишете
 grid = QtGui.QGridLayout()
вместо
 self.grid = QtGui.QGridLayout()
grid обьявляеться внутри def __init__ тоесть исходя из вышенаписаного переменная grid связана с областью видимости функции __init__ (локальная переменная), видна только внутри кода __init__ и к ней нельзя обратиться “извне”. А self.grid это уже атрибут инстанса класса GridLayout, и к нему вы можете обратиться из других методов класса, и даже извне класса(поробнее про классы и экземпляры ниже).
Вот дальше у нас есть
    def on_start(self):
        pole = self.sender()                #Лайн едид отправитель сигнала
        idx = self.grid.indexOf(pole)       # индекс отправителя сигнала
        location = self.grid.getItemPosition(idx) # положение в гриде
        poleX2 = self.grid.itemAtPosition(location[0],location[1]+1).widget() # соседнее поле
        poleX2.setText(pole.text()*2)
        print('старт', pole.text()*2)
Оно работает потому что в __init__ мы писали self.grid, тоесть обьявили grid аотрибутом экземпляра класса, и мы можем обратиться к нему как к атрибуту посредством self.grid. А self указывает на то что этот атрибут принадлежит тому же классу из которого мы его вызываем. А если бы указали просто grid то получили бы NameError поскольку метод on_start вообще не вкурсе что вы в __init__ обьявляли какуюто перменную grid.
А если бы вы хотели обратиться к нему извне класса то код выглядел бы вот так:
 qb = GridLayout()
location = qb.grid.getItemPosition(5)
Вместо self мы уже пишем перменную указывающую на экземпляр класса.
Определять что использовать self.grid или grid нужно по обстоятельствам. Если к атрибуту нужно обращаться “извне” или из других методов тогда пишем self, если переменная нужна только на время работы функции, то можно обойтись локальной переменной, котороая “исчезнет” после того как функция завершила работу.
Например в последнем варианте можно заменить self.grid на grid потому что grid за пределами __init__ не используеться.
 # Python 3. PyQt4
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
sss_vivod = ("background-color: #d0f0c0; font: 10pt 'Arial black'")
sss = ("background-color: #edecbe; font: 10pt")
class MyTextEdit(QtGui.QLineEdit): # создаем свой класс наследуя QLineEdit
    def __init__(self, *args, **kwargs):
        super().__init__()
        self.poles = [] # пустой список ссылок на поля вычислений
    def addPole(self, pole):
        self.poles.append(pole) # добавляем ссылку на поле в список
        print(self.poles)
    def valueChange(self,*args):
        s=0 # по умолчанию результат = 0
        for pole in self.poles:
            text = pole.text()
            if text:
                s+=int(text) # прошлый результат + новое значение
        self.setText(str(s))
        print(s)
        return s
    def valueCopy(self,*args):
        self.selectAll() # выделяем все
        self.copy() # копируем в буфер
class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Заголовок')
        grid = QtGui.QGridLayout()
        # ПОЛЯ
        n = 6 # строк
        m = 2 # столбцов
        for i in range(n):
            resultPole = MyTextEdit() # поле результата
            resultPole.textChanged.connect(self.gl)
            resultPole.setStyleSheet(sss_vivod)
            grid.addWidget(resultPole,i,m+2)
            butCopy = QtGui.QPushButton('Copy')
            butCopy.clicked.connect(resultPole.valueCopy)
            grid.addWidget(butCopy,i,m+1)
            for j in range(m):
                sourcePole = QtGui.QLineEdit() # поле данных
                sourcePole.setStyleSheet(sss)
                grid.addWidget(sourcePole,i,j)
                resultPole.addPole(sourcePole) # добавляем ссылку на поле в список
                sourcePole.textChanged.connect(resultPole.valueChange)
        self.pole_vivod = QtGui.QLineEdit()
        grid.addWidget(self.pole_vivod, n+1,m+2)
        self.setLayout(grid)
    def gl(self, s):
        print('приём s = ',s)
        self.pole_vivod.setText(str(s))
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.move(250,250)
qb.show()
sys.exit(app.exec_())
Видите, код как работал так и работает, потому что мы используем grid только для расположения виджетов во время __init__. Нам не нужно обращаться к grid из других методов или извне класса.

Теперь давайте посмотрим куда self должен поставляться “автоматом”
вот у нас есть банальный класс
 class A():   # Новый класс
    x=2      # атрибут x класса А
    y=4      # атрибут y класса А
    def __init__(self, x, z, n): #метод __init__ класса А
        self.x = x  # атрибут x экземпляра класса А
        self.z = z  # атрибут z экземпляра класса А
        w = n      # локальная переменная
    def print(self, num): #метод print класса А
        print('self.x + num =',self.x + num)

Для начала можно прочитать хотябы вот это http://ru.diveintopython.net/fileinfo_class.html
Метод __init__ вызывается сразу после создания экземпляра класса
Первым аргументом каждого метода класса, включая __init__, всегда является текущий экземпляр класса. Общепринято всегда называть этот аргумент self(Заметте, общепринято, в приницпе никто не мешает вам использовать любое другое слово). В методе __init__ self ссылается на только что созданный объект, в других методах — на экземпляр класса, для которого метод вызывается. Хотя и необходимо явно указывать self при определении метода, вы его не указываете, когда вызываете метод; Python добавит его автоматически.
Во как. давайте смотреть
 >>> 
print('A.x=',A.x)
A.x= 2
print('A.y=',A.y)
A.y= 4
print('A.z=',A.z)
Traceback (most recent call last):
  File "<модуль1>", line 15, in <module>
AttributeError: type object 'A' has no attribute 'z'
>>>
Как видим есть атрибуты класса, и атрибуты экземпляра класса. Атрибуты класса существуют всегда(без создания экземпляра). “x” и “y” это атрибуты класса. Атрибуты экземпляра существуют только в экземпляре. В нашем примере мы получаем исключение, так как экземпляр класса “А” не создан и атрибут “z” не существует пока.
давайте создадим экземпляр:
 a = A(x = 8, z = 22, n = 14) # создаем экземпляр класса А
print('A.x=',A.x)
print('A.y=',A.y)
print('a.x=',a.x)
print('a.y=',a.y)
print('a.z=',a.z)
>>> 
A.x= 2
A.y= 4
a.x= 8
a.y= 4
a.z= 22
>>> 
Как видим атрибуты A.x и A.y остальсь прежними, поскольку это атрибуты класса “А”, а вот a.x стал равен 8, потому что мы создали экземпляр класса и присвоили атрибуту “х” экземпляра “а” новое значение. Также у экземпляра появился новый атрибут “z”. А откуда взялся a.y, мы же ничего не присвавали? он взялся из атрибутов класса.
Не буду вдаваться в подробности, но когда вы обращаетесь к атрибуту экземпляра, сначала этот атрибут ищеться в экземпляре, и если находится то возвращаеться. Так произошло с нашим а.x. Интерпретатор нашел у экземпляра “а” атрибут “x” и вернул его значение: “8”. Если же найти не удаеться то ищеться в атрибутах класса, так произошло с a.y. Если и у класса нет такого атрибута то рекурсивно ищеться в родительких классов, если и там нет то бросается исключение AttributeError.
Напишем еще:
 print('a.w=',a.w)
>>> 
Traceback (most recent call last):
  File "<модуль1>", line 20, in <module>
AttributeError: 'A' object has no attribute 'w'
“w” локальная перпеменная, она существвовала только пока работал метод __init__. К ней нельзя обратиться “извне”. Мы это рассматривали ранее, когда изучали области видимости.
А вот теперь мы подходим к тому что “self должен подставится автоматом”
У нас есть метод класса print, у него есть два аргумента self и num
мы его можем вызвать вот так:
 a = A(x = 8, z = 22, n = 14) # создаем экземпляр класса А
A.print(a,2)
>>> 
self.x + num = 10
в качестве первого аргумента мы передаем экземпляр класса, а в качесвте второго число.
внутри мы видим вот такую кострукцию:
print('self.x + num =',self.x + num)
поскольку мы первым аргументом передали “а” то он подставляеться вместо self. В итоге мы получаем на выходе a.x+2( второй аргумент у нас 2), a.x у нас 8, результат = 10.
Но также мы может вызвать метод и вот так:
 a.print(2)
>>> 
self.x + num = 10
вот в этом случае “self должен подставится автоматом”. Интерпретатор всеравно сделает A.print(self,num) но вместо self “автоматом” подставит “а”, а вместо num двойку.
Надеюсь понятно?

Kyrym
Здесь есть такая строчка:
self.label = QtGui.QLabel('Knowledge only matters', self)
Здесь с селфом вообще не понятно.
еще раз повторюсь, self это “указатель” на экземпляр класса из которого вы вызываете метод.
в данном случае self.label переменная label, атрибут экземпляра класса FontDialog
мы создаем обьект типа QtGui.QLabel и присваиваем его с атрибуту label экземпляра класса FontDialog
теперь читаем документацию к QLabel http://doc.crossplatform.ru/qt/4.8.x/html-qt/qlabel.html#QLabel
и прозреваем
QLabel::QLabel ( const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0 )
Создаёт метку, которая отображает текст text.
The parent and widget flag f, arguments are passed to the QFrame constructor.
QLabel принимает в качестве первого аргумента текст самого лейбла, а вторым можно указать родительский виджет (не путать с родительским классом)
Соответвенно при таком вызове
self.label = QtGui.QLabel('Knowledge only matters', self)
текстом QLabel-а будет ‘Knowledge only matters’, а родительским виджетом - self: экземпляр класса FontDialog из которого вызвали этот самый QLabel



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Апрель 19, 2017 12:11:50)

Офлайн

#6 Апрель 19, 2017 12:32:33

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

PEHDOM
Ага, очень сильно запущено, но думаю он не безнадежен.

PEHDOM
grid обьявляеться внутри def __init__ тоесть исходя из вышенаписаного переменная grid связана с областью видимости функции __init__ (локальная переменная), видна только внутри кода __init__ и к ней нельзя обратиться “извне”. А self.grid это уже атрибут инстанса класса GridLayout, и к нему вы можете обратиться из других методов класса, и даже извне класса(поробнее про классы и экземпляры ниже).
Еще добавлю, любая переменная объявленная внутри функции, процедуры существует (живет), пока данная функция, процедура не завершит свою работу. Таким образом объявленная переменная grid внутри __init__ прекратит свое существование после завершения работы данного метода, а self.grid - это объявление атрибута объекта и она будет существовать пока существует этот объект.

Офлайн

#7 Апрель 19, 2017 12:49:46

vic57
Зарегистрирован: 2015-07-07
Сообщения: 908
Репутация: +  127  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Kyrym
Здесь с селфом вообще не понятно.
это Qt правило - при уничтожении родителя автоматом уничтожаются все дочерние элементы, поэтому и надо явно указывать родителя для освобождения памяти. в питоне это не так актуально, как в С++.

Офлайн

#8 Апрель 20, 2017 13:06:09

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

PEHDOM и MrViktor, спасибо вам большое, теперь я понял разницу в использовании self.

Офлайн

#9 Апрель 20, 2017 13:18:27

MrViktor
Зарегистрирован: 2017-03-09
Сообщения: 83
Репутация: +  8  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

Kyrym
PEHDOM и MrViktor, спасибо вам большое, теперь я понял разницу в использовании self.
Да всегда пожалуйста!
Поздравляю, надо бы еще экзамен провести

Офлайн

#10 Апрель 20, 2017 13:50:19

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a

MrViktor
Поздравляю, надо бы еще экзамен провести
А вот я как-раз и набросал сейчас программку с селфами. Программа ловит исключения: если может перевести значение поля в вещественное, то выводит это число, в противном случае выводит 0. И как раз две функции работают друг с другом.
 # Python 3. PyQt4
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ДАННЫЕ
        
# ГРАФИКА
class Window(QtGui.QWidget): # Класс Window  наследует класс QWidget
    def __init__(self, parent=None, *args, **kwargs): # Создаёт конструктор класса, parent - ссылка на родительский эл-т
        QtGui.QWidget.__init__(self, parent)
        
        self.setMinimumSize(200, 200) # Ширина и высота окна
        self.resize(200, 200) # шир / выс окна
        self.setWindowTitle('Исключения') # Заголовок
        self.setWindowIcon(QtGui.QIcon('icon.png')) # Иконка              
        
        # БЛОК РАЗМЕТКИ      
        self.vbox_os = QtGui.QVBoxLayout()
        # ---
        self.pole = QtGui.QLineEdit()
        self.pole.setStyleSheet(sss_vivod)
        self.vbox_os.addWidget(self.pole)
        # ---
        self.btn = QtGui.QPushButton('Выполнить')     
        self.btn.clicked.connect(self.on_start)
        self.vbox_os.addWidget(self.btn)
        # ---
        self.pole_vivod = QtGui.QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.vbox_os.addWidget(self.pole_vivod)
        # ---
        self.setLayout(self.vbox_os) # установка рабочей области
    # ЛОГИКА
    def on_start(self, x=None):
        a = self.pole.text()
        print('on_start до функции, a =',a)
        Window.in_ch_f(self,a)
        a = self.x
        print('on_start после функции, a =',a)
        self.pole_vivod.setText(str(a))
        print('-'*50)
    def in_ch_f(self,x):
        try:
            self.x = float(x)
            print('try, x =',x)
        except:
            self.x = 0
            print('except, x =',x)                  
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window() # создаёт экземпляр окна из класса
    window.show() # запускает окно
    sys.exit(app.exec_())
    

И второй вариант. Здесь 2 поля с данными.
 # Python 3. PyQt4
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 12pt 'Courier New'")
# ДАННЫЕ
        
# ГРАФИКА
class Window(QtGui.QWidget): # Класс Window  наследует класс QWidget
    def __init__(self, parent=None, *args, **kwargs): # Создаёт конструктор класса, parent - ссылка на родительский эл-т
        QtGui.QWidget.__init__(self, parent)
        
        self.setMinimumSize(200, 200) # Ширина и высота окна
        self.resize(200, 200) # шир / выс окна
        self.setWindowTitle('Исключения') # Заголовок
        self.setWindowIcon(QtGui.QIcon('icon.png')) # Иконка              
        
        # БЛОК РАЗМЕТКИ      
        self.vbox_os = QtGui.QVBoxLayout()
        # ---
        self.pole = QtGui.QLineEdit()
        self.pole.setStyleSheet(sss_vivod)
        self.vbox_os.addWidget(self.pole)
        # ---
        self.pole_2 = QtGui.QLineEdit()
        self.pole_2.setStyleSheet(sss_vivod)
        self.vbox_os.addWidget(self.pole_2)
        # ---
        self.btn = QtGui.QPushButton('Выполнить')     
        self.btn.clicked.connect(self.on_start)
        self.vbox_os.addWidget(self.btn)
        # ---
        self.pole_vivod = QtGui.QTextEdit('')
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.vbox_os.addWidget(self.pole_vivod)
        # ---
        self.setLayout(self.vbox_os) # установка рабочей области
    # ЛОГИКА
    def on_start(self, x=None):
        def ap(i):            
            data.append(i)
        data = []
        self.pole_vivod.setText('')
        
        a = self.pole.text()
        print('on_start до функции, a =',a)        
        Window.in_ch_f(self,a)
        a = self.x
        print('on_start после функции, a =',a)
        ap(a)
        print('-'*50)
        b = self.pole_2.text()
        print('on_start до функции, b =',b)
        Window.in_ch_f(self,b)
        b = self.x
        print('on_start после функции, b =',b)
        ap(b)
        print('='*50)
        for i in data:
            self.pole_vivod.append(str(i))
        
    def in_ch_f(self,x):
        try:
            self.x = float(x)
            print('try, x =',x)
        except:
            self.x = 0
            print('except, x =',x)                  
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window() # создаёт экземпляр окна из класса
    window.show() # запускает окно
    sys.exit(app.exec_())
    
Суть в том, что ссылаясь a = self.x и b = self.x, я получаю разные self.x

Отредактировано Kyrym (Апрель 20, 2017 15:16:38)

Офлайн

  • Начало
  • » GUI
  • » PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version