Найти - Пользователи
Полная версия: PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a
Начало » GUI » PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a
1 2 3 4 5
Kyrym
Данная программа создаёт поля и кнопки, но я не знаю, как мне ссылаться в функциях на эти элементы, которые ещё не существуют.
Функция старт должна умножать левое поле на два и выводить в правое поле своего ряда.
Функция клик выводит в консоль число из левого поля своего ряда.

 # 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_())
vic57
в параметрах
>>> def f(a,b):
return str(a*b)

>>> f(2,3)
'6'
>>>
Kyrym
Не понимаю, как это может помочь
PEHDOM
млин вы вообще понимаете что пишете? это же бред сивой кобылы.
увидев это
         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('ИмяОбьекта')
Kyrym
PEHDOM, насколько я понял, последний вариант лучше, чем предпоследний: покороче, и, вроде, попроще.
Функции enumerate и sender для меня новые.
Подскажите ещё, пожалуйста, что значит код: poleX1.poleX2 = poleX2 ? Не понимаю физического смысла. Типа поле poleX2 - становится атрибутом poleX1 и равно poleX2 ? Как это вообще так? Всё что я понял, это так мы создаём адрес поля, чтобы потом на него сослаться…
В общем пока пытаюсь разобраться, хочу связать более, чем 2 поля одной строки.
PEHDOM
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>

Kyrym
Последний пример я переписал для трёх связей. Получается лишний код, конечно…
 # 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_())
PEHDOM
будте проще, в таком случае вам нужно “плясать от обратного”
  # 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_())
PEHDOM
более общий случай, когда к-во полей неизвестно:
 # -*- 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_())
MrViktor
PEHDOM
более общий случай, когда к-во полей неизвестно:
Что-то мне подсказывает, что данный подход изначально относится к извращениям (поля я понимаю тоже динамически создаются в неизвестном колличестве). Разве TableWidget не лучше использовать?
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