Уведомления

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

#1 Март 28, 2017 18:19:04

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

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

Данная программа создаёт поля и кнопки, но я не знаю, как мне ссылаться в функциях на эти элементы, которые ещё не существуют.
Функция старт должна умножать левое поле на два и выводить в правое поле своего ряда.
Функция клик выводит в консоль число из левого поля своего ряда.

 # Python 3. PyQt4
# -*- 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','']
        pos_pole = [(0, 0), (0, 1),
                    (1, 0), (1, 1),
                    (2, 0), (2, 1)]
        j = 0
        for i in names_pole:
            self.pole = QtGui.QLineEdit(i)
            self.grid.addWidget(self.pole, pos_pole[j][0], pos_pole[j][1])
            j = j + 1      
            self.pole.textChanged.connect(self.on_start) # сигнал изм текста
        
        # КНОПКИ
        names_button = ['Copy', 'Copy', 'Copy']      
        pos_button = [(0, 3), (1, 3), (2, 3)]
        j = 0
        for i in names_button:
            self.button = QtGui.QPushButton(i)
            self.grid.addWidget(self.button, pos_button[j][0], pos_button[j][1])
            j = j + 1
            self.button.clicked.connect(self.on_click)
        self.setLayout(self.grid)
    
    def on_start(self):
        a = self.pole.text()
        b = 2*a
        self.pole.setText(str(b)) 
        print('старт')
    
    def on_click(self):
        a = self.pole.text()
        print(a,'клик')
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.show()
sys.exit(app.exec_())

Отредактировано Kyrym (Апрель 19, 2017 13:15:11)

Офлайн

#2 Март 28, 2017 18:50:53

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

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

в параметрах

>>> def f(a,b):
return str(a*b)

>>> f(2,3)
'6'
>>>

Офлайн

#3 Март 28, 2017 19:04:23

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

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

Не понимаю, как это может помочь

Офлайн

#4 Март 28, 2017 22:29:37

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

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

млин вы вообще понимаете что пишете? это же бред сивой кобылы.
увидев это

         j = 0
        for i in names_pole:
            self.pole = QtGui.QLineEdit(i)
            self.grid.addWidget(self.pole, pos_pole[j][0], pos_pole[j][1])
            j = j + 1      
            self.pole.textChanged.connect(self.on_start) # сигнал изм текста
я впал в ступор минут на 10 пытаясь осознать что вы делаете. Вы вообще понимаете смысл выражения self.атрибут. Зачем вы в цикле 6 раз перназначаете self.pole? Вы думаете оно будет хранить ссылки на все 6 ЛайнЕдитов что вы создаете? Авотвамхрен, оно будет хранить ссылку только на последний созданый ЛайнЕдит. А про enumerate вы когданибудь слышали?
Если уж у вас заранее неизвестное колличество элементов на форме, можно воспользоваться словарем для хранения ссылок на элементы. Пример:
 self._widget ={}
for i in range(3):
    for j in range(2):
        self._widget[(i,j)] = QtGui.QLineEdit('pole {} ,{}'.format(i,j))
        self.grid.addWidget(self._widget[(i,j)],i,j)
names_pole = ['12','7','4']
for i,name in enumerate(names_pole):
    self._widget[(i,0)].setText(name)
    self._widget[(i,0)].textChanged.connect(self.on_start)
замените этот кусок
         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)
тогда вы сможете обратиться к виджету просто зная его положение простым
 self._widget[(row,column)]

но если уж вам так захотелось извращений, то в принципе можно найти виджет по его позиции в QgridLayout, :
 # -*- 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_())
Но это как рвать гланды через жопу
ЗЫ немного поправил ваш пример.

можно хранить ссылки на обьекты прямо в самих обьектах:
   # -*- 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']
        self._widget ={}
        for i in range(3):
            for j in range(2):
                self._widget[(i,j)] = QtGui.QLineEdit('pole {} ,{}'.format(i,j))
                self.grid.addWidget(self._widget[(i,j)],i,j)
        for i,name in enumerate(names_pole):
            self._widget[(i,0)].setText(name)
            self._widget[(i,0)].textChanged.connect(self.on_start)
            self._widget[(i,0)].x2widget = (i,1)
       # КНОПКИ
        names_button = ['Copy', 'Copy', 'Copy']
        for i, name  in enumerate(names_button):
            self._widget[(i,2)] = QtGui.QPushButton(name+str(i))
            self.grid.addWidget(self._widget[(i,2)], i,2)
            self._widget[(i,2)].clicked.connect(self.on_click)
            self._widget[(i,2)].source = (i,1)
        self.setLayout(self.grid)
    def on_start(self):
        pole = self.sender()                #Лайн едид отправитель сигнала
        self._widget[pole.x2widget].setText(pole.text()*2)
        print('старт', pole.text()*2)
    def on_click(self):
        button = self.sender()
        print(self._widget[button.source].text(),'клик')
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.show()
sys.exit(app.exec_())
или даже так:
  # -*- 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']
        names_button = ['Copy', 'Copy', 'Copy']
        for i in range(3):
                poleX1 = QtGui.QLineEdit(names_pole[i])
                self.grid.addWidget(poleX1,i,0)
                poleX2 = QtGui.QLineEdit('pole {} ,{}'.format(i,1))
                self.grid.addWidget(poleX2,i,1)
                poleX1.textChanged.connect(self.on_start)
                poleX1.poleX2 = poleX2
                button = QtGui.QPushButton(names_button[i]+str(i))
                self.grid.addWidget(button,i,2)
                button.clicked.connect(self.on_click)
                button.poleX2 = poleX2
        self.setLayout(self.grid)
    def on_start(self):
        pole = self.sender()                #Лайн едид отправитель сигнала
        pole.poleX2.setText(pole.text()*2)
        print('старт', pole.text()*2)
    def on_click(self):
        button = self.sender()
        print(button.poleX2.text(),'клик')
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.show()
sys.exit(app.exec_())
А можно банально давать имена всем обьектам по типу obj.setObjectName('ИмяОбьекта')
а потом искать их по имени через метод родителя parent.findChild('ИмяОбьекта')



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

Отредактировано PEHDOM (Март 29, 2017 00:00:25)

Офлайн

#5 Март 30, 2017 08:45:16

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

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

PEHDOM, насколько я понял, последний вариант лучше, чем предпоследний: покороче, и, вроде, попроще.
Функции enumerate и sender для меня новые.
Подскажите ещё, пожалуйста, что значит код: poleX1.poleX2 = poleX2 ? Не понимаю физического смысла. Типа поле poleX2 - становится атрибутом poleX1 и равно poleX2 ? Как это вообще так? Всё что я понял, это так мы создаём адрес поля, чтобы потом на него сослаться…
В общем пока пытаюсь разобраться, хочу связать более, чем 2 поля одной строки.

Офлайн

#6 Март 30, 2017 09:44:33

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

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

Kyrym
насколько я понял, последний вариант лучше, чем предпоследний: покороче, и, вроде, попроще.
все зависит от задачи,в данном случае когда вам нужно “связать” два соседних виджета, он выглядит поэстетичнее. А если вам надо, допустим, получать данные сразу со всех полей, то первый вариант проще, вы тогда просто проходитесь по массиву собираете данные и заносите их в список.
Kyrym
что значит код: poleX1.poleX2 = poleX2 ? Не понимаю физического смысла. Типа поле poleX2 - становится атрибутом poleX1 и равно poleX2 ? Как это вообще так?
физический смысл в том что у вас в памяти создаеться два обькта , и первый хранит адрес второго, по которому он может к нему обратиться.

Смотрите, мы создали
 poleX1 = QtGui.QLineEdit()
тоесть в памяти создался инстанс(экземпляр) класса QtGui.QLineEdit, надо понимать что poleX1 это не сам обьект, это просто пременная которая содержит ссылку на этот обьект, грубо говоря.
если вставить print(poleX1) то оно выведет чтото типа такого
 <PyQt4.QtGui.QLineEdit object at 0x02F17660>
Пишем
 poleX2 = QtGui.QLineEdit()
Теперь у вас в памяти есть еще один инстанс класса QLineEdit, доступ к которому мы имеем через перемнную poleX2. принт нам покажет чтото типа такого
 <PyQt4.QtGui.QLineEdit object at 0x02F17738>
.
Теперь
 poleX1.poleX2 = poleX2 
это создает у инстанса на котороый ссылаеться poleX1 еще один атрибут: “poleX2” который одержит адрес того же обькта что и локальная переменная poleX2. если вы вставите
 print(poleX1.poleX2)
то увидите все тоже
 <PyQt4.QtGui.QLineEdit object at 0x02F17738>



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

Офлайн

#7 Март 30, 2017 11:58:26

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

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

Последний пример я переписал для трёх связей. Получается лишний код, конечно…

 # Python 3. PyQt4
# -*- 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_X1 = ['4','2','3']
        for i in range(3):
                poleX1 = QtGui.QLineEdit(names_X1[i])
                poleX1.textChanged.connect(self.on_start1)
                self.grid.addWidget(poleX1,i,0)
                print('poleX1 = ',poleX1)
                poleX2 = QtGui.QLineEdit('1')
                poleX2.textChanged.connect(self.on_start2)
                self.grid.addWidget(poleX2,i,1)
                print('poleX2 = ',poleX2)
                poleX3 = QtGui.QLineEdit('')
                self.grid.addWidget(poleX3,i,2)
                print('poleX3 = ',poleX3)
                
                poleX1.poleX3 = poleX3
                poleX1.poleX2 = poleX2
                poleX2.poleX3 = poleX3
                poleX2.poleX1 = poleX1
                
        self.setLayout(self.grid)        
        
        
    def on_start1(self):
        sbor = self.sender()   #Лайн едид отправитель сигнала (1 стлб)
        x1 = int(sbor.text())
        x2 = int(sbor.poleX2.text())
        sbor.poleX3.setText(str(x1+x2))
        print('sbor = ',sbor)
        print('sbor.poleX2 = ',sbor.poleX2)
        print('sbor.poleX3 = ',sbor.poleX3)
    def on_start2(self):
        sbor = self.sender()   #Лайн едид отправитель сигнала (2 стлб)
        x1 = int(sbor.poleX1.text())
        x2 = int(sbor.text())
        sbor.poleX3.setText(str(x1+x2))
        print('sbor = ',sbor)
        print('sbor.poleX1 = ',sbor.poleX1)
        print('sbor.poleX3 = ',sbor.poleX3)
        
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.move(250,250)
qb.show()
sys.exit(app.exec_())

Отредактировано Kyrym (Март 30, 2017 12:56:59)

Офлайн

#8 Март 30, 2017 17:38:52

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

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

будте проще, в таком случае вам нужно “плясать от обратного”

  # Python 3. PyQt4
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
#вап = 4
class MyTextEdit(QtGui.QLineEdit): # создаем свой класс наследуя QLineEdit
    poleX1 = None                         # атрибуты класса 
    poleX2 = None
    def valueChange(self,*args):# функция суммы, сюда еще можно добавить проврку что self.poleXn != None например
        self.setText(str(int(self.poleX1.text())+ int(self.poleX2.text())))
class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        names_X1 = ['4','2','3']
        for i in range(3):
                poleX1 = QtGui.QLineEdit(names_X1[i])
                
                self.grid.addWidget(poleX1,i,0)
                print('poleX1 = ',poleX1)
                poleX2 = QtGui.QLineEdit('1')
                self.grid.addWidget(poleX2,i,1)
                print('poleX2 = ',poleX2)
                poleX3 = MyTextEdit('')  # poleX3 уже не QLineEdit а MyLineEdit
                self.grid.addWidget(poleX3,i,2)
                print('poleX3 = ',poleX3)
                poleX3.poleX1 = poleX1
                poleX3.poleX2 = poleX2
                poleX1.textChanged.connect(poleX3.valueChange) # соединяем сигнал  textChanged с методом valueChanged обьекта poleX3
                poleX2.textChanged.connect(poleX3.valueChange)
        self.setLayout(self.grid)
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.move(250,250)
qb.show()
sys.exit(app.exec_())



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

Отредактировано PEHDOM (Март 30, 2017 17:56:48)

Офлайн

#9 Март 30, 2017 19:48:46

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

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

более общий случай, когда к-во полей неизвестно:

 # -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
#вап = 4
class MyTextEdit(QtGui.QLineEdit): # создаем свой класс наследуя QLineEdit
                                  
    def __init__(self, *args, **kwargs):
        super().__init__()
        self.poles = list()
    def addPole(self, pole):
        self.poles.append(pole)
    def valueChange(self,*args):
        s=0
        for pole in self.poles:
            text = pole.text()
            if text:
                s+=int(text)
        self.setText(str(s))
class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        n=10
        for i in range(n):
            resultPole = MyTextEdit()
            self.grid.addWidget(resultPole,i,n+1)
            for j in range(i+1):
                sourcePole = QtGui.QLineEdit()
                self.grid.addWidget(sourcePole,i,j)
                resultPole.addPole(sourcePole)
                sourcePole.textChanged.connect(resultPole.valueChange) 
        self.setLayout(self.grid)
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.move(250,250)
qb.show()
sys.exit(app.exec_())



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

Офлайн

#10 Март 31, 2017 06:00:24

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

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

PEHDOM
более общий случай, когда к-во полей неизвестно:
Что-то мне подсказывает, что данный подход изначально относится к извращениям (поля я понимаю тоже динамически создаются в неизвестном колличестве). Разве TableWidget не лучше использовать?

Офлайн

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

Board footer

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

Powered by DjangoBB

Lo-Fi Version