Уведомления

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

#1 Апрель 11, 2017 16:23:37

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

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

PEHDOM
в смысле? какой “этот метод”
я имею ввиду предложенный Вами код стр.2 пост 4

PEHDOM
super().__init__(*args, **kwargs)
получилось )))

Отредактировано Kyrym (Апрель 11, 2017 16:27:01)

Офлайн

#2 Апрель 11, 2017 16:49:21

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

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

enumerate работает везде где работает in. только in перебирает элементы последовательности, а enumerate еще и выводит… порядковый номер элемента чтоле, позволяя избавиться от необходимости инициализировать и обновлять отдельную переменную-счётчик.



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

Офлайн

#3 Апрель 11, 2017 18:30:49

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

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

Kyrym
И эти имена объектов “<PyQt4.QtGui.QLineEdit object at 0x00000000038A0C18>” постоянные?
да, пока они храняться в памяти
Kyrym
Можно ли на них ссылаться?
По моему нет, это всего лишь текстовое представление, генерируемое встроеным методом __str__
в пайтоне есть “идентификатор” обьекта, число, гарантированно являющееся уникальным и постоянным для объекта на время его существования. узнать его мжно при помощи функции id(obj). НО вам стоит существенно пересмотреть алгоритм работы вашей программы если вы вдруг решите использовать id.
Kyrym
Можно ли по названию удалить некоторые поля из общей сетки
У всех виджетов PyQt есть атрибут objectName, устанавливвется методом .setObjectName(name), и возвращаеться .objectName()
Соответенно если назначить виджету уникальное имя, то потом его можно найти методами родителя
findChildren() и findChild()
http://doc.crossplatform.ru/qt/4.8.x/html-qt/qobject.html#findChild
Kyrym
и вставить (вставить, понятное дело, можно) на их позиции другие элементы?
чтобы удалить а потом вставить на его место другой виджет вам нужно запомнить его местоположение в сетке. Я уже приводил вам несколько вариантов решения ранее http://python.su/forum/topic/32446/?page=1#post-177512, Сходу могу еще пару тройку придумать.
Kyrym
Или по имени для одной ячейки (из всей сетки) сделать проверку вводимых значений? Вопрос в том, реально ли такое?
реально, в любом табличном процессоре это реализовано.
Kyrym
И ещё меня интересует вопрос. Вообще я хочу сделать сетку (30х7, где 30 - это строки), столбцы которой будут лайнэдитами, кнопками, раскрывающимися списками. Отдельные ячейки с проверкой вводимых значений. Как думаете, стоит ли мне пытаться решить такую задачу последней методикой?
все завивит от того насколько однотипными будут ваши элементы в сетке.
Kyrym
Может лучше вернуться к начальному варианту с индексами из стр. 1 поста 4, или вообще всё руками прописать? Руками бы я уже сделал, но хотелось сделать правильно - технологично! ))
при таком колличетсве возможно вам действительно стоит помотреть в сторону TableWidget как советовал MrViktor, или mvc? Например вот тут https://habrahabr.ru/post/139454/ как раз пример паттерна mvc очень похожий на ваш только упрощен до минимума, одна строка три поля.




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

Отредактировано PEHDOM (Апрель 11, 2017 18:32:15)

Офлайн

#4 Апрель 14, 2017 09:31:29

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

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

Ох… что-то не понятное создает автор.
Можно еще рассмотреть создание своего виджета с использованием QScrollArea, где можно будет создавать/удалять QLineEdit, но тут надо хорошо продумать реализацию.

Kyrym
Может на словах опишете задачу (общую картину работы). Возможно вы выбрали изначально не правильный путь решения (реализации).

Офлайн

#5 Апрель 17, 2017 15:23:02

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

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

MrViktor
QScrollArea
Не понял при чём тут QScrollArea.

MrViktor
Kyrym
Может на словах опишете задачу (общую картину работы). Возможно вы выбрали изначально не правильный путь решения (реализации).
Ой, описывать я долго буду, да и думаю, это не сильно интересно. Я пока заморозил этот проект. Зато делаю другой, и успешно внедрил метод PEHDOM'a.

Единственное, вопрос возник. Спрошу на примере предыдущего кода.
В классе GridLayout создали обычным образом текстовое поле:
 self.edit = QtGui.QLineEdit()
В фунции valueChange класса MyTextEdit получили сумму ‘s’, и теперь нужно эту сумму вставить в поле self.edit.
Ни к чему не приводят попытки сделать вот так:
 class MyTextEdit
...
s = ...
GridLayout.self.edit.setText(str(s))
GridLayout.__init__.self.edit.setText(str(s))
...
class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None, *args, **kwargs):
...


Отредактировано Kyrym (Апрель 17, 2017 16:27:00)

Офлайн

#6 Апрель 17, 2017 16:46:09

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

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

Kyrym
В фунции valueChange класса MyTextEdit получили сумму ‘s’, и теперь нужно эту сумму вставить в поле self.edit.
Ни к чему не приводят попытки сделать вот так:
чето я нихрена не понял.. словами вы пишеете одно а в коде у вас другое.
Kyrym
В классе GridLayout создали обычным образом текстовое поле:
а коде у вас
  class MyTextEdit
...
s = ...
GridLayout.self.edit.setText(str(s))
GridLayout.__init__.self.edit.setText(str(s))
во первых, класс MyTextEdit не знает о существовании класса GridLayout
во вторых, self это прсто признак того что атрибут принадлежит классу в котором мы это пишем. Поэтому конструкция self.edit.setText(str(s)) снаружы должна выгладеть вот так GridLayout.edit.setText(str(s))
в третих GridLayout это название класса, а не экземпляр класса, поэтому написав GridLayout.edit.setText(…)
вы установите текст атрибуту класса а не атрибуту инстанса, учитывая что это QLineEdit то у вас мало что получится.
если вы хотите этот текст вставить в другой QLineEdit то вам нужно свзать его какимто иным способом
например в том же GridLayout написать чтото типа такго MyTextEditInstanse.textChanged.connect(self.edit.setText) где MyTextEditInstanse переменная связаная с MyTextEdit -ом из которого хотите вставить текст.
или передать както ссылку на QLineEdit в MyTextEdit какимто образом, это уже зависит от конкретной реализации…



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

Отредактировано PEHDOM (Апрель 17, 2017 17:00:56)

Офлайн

#7 Апрель 17, 2017 19:57:28

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

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

PEHDOM
чето я нихрена не понял.. словами вы пишеете одно а в коде у вас другое.
Надо было мне полный код выложить.

Я тут ещё немного пошаманил (но пока не работает):
 # 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)
        self.textChanged.connect(GridLayout.gl(self,s))
        #self.textChanged.connect(GridLayout.gl)
        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('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        n = 6 # строк
        m = 2 # столбцов
        for i in range(n):
            resultPole = MyTextEdit() # поле результата
            resultPole.setStyleSheet(sss_vivod)
            self.grid.addWidget(resultPole,i,m+2)
            butCopy = QtGui.QPushButton('Copy')
            butCopy.clicked.connect(resultPole.valueCopy)
            self.grid.addWidget(butCopy,i,m+1)
            
            for j in range(m):
                sourcePole = QtGui.QLineEdit() # поле данных
                sourcePole.setStyleSheet(sss)
                self.grid.addWidget(sourcePole,i,j)
                resultPole.addPole(sourcePole) # добавляем ссылку на поле в список
                sourcePole.textChanged.connect(resultPole.valueChange)
        self.pole_vivod = QtGui.QLineEdit()
        self.grid.addWidget(self.pole_vivod, n+1,m+2)            
        self.setLayout(self.grid)
    def gl(self,s):
        s = MyTextEdit.valueChange(self,s)
        #s = MyTextEdit.valueChange(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_())
Я понимаю, что self показывает принадлежность к экземпляру класса, но когда надо прописывать self, а когда не надо, мне не понятно, поэтому стараюсь писать везде, где это относится к конструктивным элементам.

Механика
Когда в sourcePole мы вводим значения, срабатывает функция valueChange. Она считает нам сумму s, запускает сигнал self.textChanged.connect(GridLayout.gl(self,s)), который должен передать аргумент s в функцию gl класса GridLayout, а там значение s должно приниматься s = MyTextEdit.valueChange.
Если я пишу так: s = MyTextEdit.valueChange(self,s), то программа уходит в бесконечный цикл.

Отредактировано Kyrym (Апрель 17, 2017 20:00:27)

Офлайн

#8 Апрель 17, 2017 22:47:50

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

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

Kyrym
Я понимаю, что self показывает принадлежность к экземпляру класса, но когда надо прописывать self, а когда не надо, мне не понятно, поэтому стараюсь писать везде, где это относится к конструктивным элементам.
да вы шутите… как вы вообще чтото пишете не понимая таких элементарных вещей?
self пишеться только когда вы описываете класс, оно означает собственно сам себя. Я не знаю как еще это обьяснить. “Снаружи” класса вы должны указать инстанс класса.


Kyrym
Механика
Когда в sourcePole мы вводим значения, срабатывает функция valueChange. Она считает нам сумму s, запускает сигнал self.textChanged.connect(GridLayout.gl(self,s)), который должен передать аргумент s в функцию gl класса GridLayout, а там значение s должно приниматься s = MyTextEdit.valueChange.
Если я пишу так: s = MyTextEdit.valueChange(self,s), то программа уходит в бесконечный цикл.
Честно говоря нихрена всеравно непонятно, вы просто хотите чтобы когда менялось значение в любом MyTextEdit-е оно передавалось в pole_vivod?
  
 # 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('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        n = 6 # строк
        m = 2 # столбцов
        for i in range(n):
            resultPole = MyTextEdit() # поле результата
            resultPole.textChanged.connect(self.gl)
            resultPole.setStyleSheet(sss_vivod)
            self.grid.addWidget(resultPole,i,m+2)
            butCopy = QtGui.QPushButton('Copy')
            butCopy.clicked.connect(resultPole.valueCopy)
            self.grid.addWidget(butCopy,i,m+1)
            for j in range(m):
                sourcePole = QtGui.QLineEdit() # поле данных
                sourcePole.setStyleSheet(sss)
                self.grid.addWidget(sourcePole,i,j)
                resultPole.addPole(sourcePole) # добавляем ссылку на поле в список
                sourcePole.textChanged.connect(resultPole.valueChange)
        self.pole_vivod = QtGui.QLineEdit()
        self.grid.addWidget(self.pole_vivod, n+1,m+2)
        self.setLayout(self.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_())
хотя такой подход несколько странный, можно вообще обойтись без def gl, а resultPole.textChanged.connect(self.gl) заменить на resultPole.textChanged.connect(self.pole_vivod.setText)
Только self.pole_vivod нужно обьявить до цикла.



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

Отредактировано PEHDOM (Апрель 17, 2017 22:51:21)

Офлайн

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

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

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

PEHDOM
resultPole.textChanged.connect(self.gl)
Как оказывается, всё просто.

PEHDOM
вы просто хотите чтобы когда менялось значение в любом MyTextEdit-е оно передавалось в pole_vivod?
Именно так. Суть в том, что pole_vivod не принадлежит классу MyTextEdit, в котором происходят расчёты, а результаты из MyTextEdit получает. Для меня это было важно.

PEHDOM
self пишется только когда вы описываете класс, оно означает собственно сам себя
Это я знаю. Вопрос в том, как это применять на практике. Я читал, про self, но пока так и не понял.
Например, это на тостере.
Ладно, думаю, со временем до меня дойдёт.

PEHDOM
можно вообще обойтись без def gl, а resultPole.textChanged.connect(self.gl) заменить на resultPole.textChanged.connect(self.pole_vivod.setText)
Только self.pole_vivod нужно обьявить до цикла.
Этого мало, программа не понимает, что нужно вставить, нет никаких ссылок на ‘s’ как было в функции:
 def gl(self,s):
Вот код, правленный, как Вы сказали - без функции:
 # Python 3. PyQt4
# -*- coding: utf-8 -*-
# подвариант 2 без доп функции gl
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))
        return s
        print(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('Заголовок')
        self.grid = QtGui.QGridLayout()
        # ПОЛЯ
        n = 6 # строк
        m = 2 # столбцов
        for i in range(n):
            resultPole = MyTextEdit() # поле результата
            resultPole.setStyleSheet(sss_vivod)
            self.grid.addWidget(resultPole,i,m+2)
            butCopy = QtGui.QPushButton('Copy')
            butCopy.clicked.connect(resultPole.valueCopy)
            self.grid.addWidget(butCopy,i,m+1)
            self.pole_vivod = QtGui.QLineEdit()
            resultPole.textChanged.connect(self.pole_vivod.setText)
            self.grid.addWidget(self.pole_vivod, n+1,m+2)
            for j in range(m):
                sourcePole = QtGui.QLineEdit() # поле данных
                sourcePole.setStyleSheet(sss)
                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_())

Отредактировано Kyrym (Апрель 18, 2017 20:14:03)

Офлайн

#10 Апрель 18, 2017 21:57:12

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

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

Kyrym
Вот код, правленный, как Вы сказали - без функции:
переместите self.pole_vivod = QtGui.QLineEdit() и self.grid.addWidget(self.pole_vivod, n+1,m+2) сразу после m = 2 # столбцов и будет вам щастье, а у вас оно создает 6 лайн едитов, и помещает их один над одним, потому у вас ничего и не получаеться.
 class GridLayout(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Заголовок')
        self.grid = QtGui.QGridLayout()
        self.pole_vivod = QtGui.QLineEdit()
        # ПОЛЯ
        n = 6 # строк
        m = 2 # столбцов
        self.grid.addWidget(self.pole_vivod, n+1,m+2)
        for i in range(n):
            resultPole = MyTextEdit() # поле результата
            resultPole.setStyleSheet(sss_vivod)
            self.grid.addWidget(resultPole,i,m+2)
            butCopy = QtGui.QPushButton('Copy')
            butCopy.clicked.connect(resultPole.valueCopy)
            self.grid.addWidget(butCopy,i,m+1)
            resultPole.textChanged.connect(self.pole_vivod.setText)
            for j in range(m):
                sourcePole = QtGui.QLineEdit() # поле данных
                sourcePole.setStyleSheet(sss)
                self.grid.addWidget(sourcePole,i,j)
                resultPole.addPole(sourcePole) # добавляем ссылку на поле в список
                sourcePole.textChanged.connect(resultPole.valueChange)
        self.setLayout(self.grid)

Kyrym
Этого мало, программа не понимает, что нужно вставить, нет никаких ссылок на ‘s’ как было в функции:
этого более чем достаточно, читаем документацию
http://doc.crossplatform.ru/qt/4.8.x/html-qt/qlineedit.html#textChanged
This signal is emitted whenever the text is edited. The text argument is the new text.
тоесть сигнал генерируеться когда текст меняется, и текст в аргументе это новый текст в лайн едите
читаем дальше http://doc.crossplatform.ru/qt/4.8.x/html-qt/qlineedit.html#text-prop
setText аргументом содержит новый текст
Тогда вы пишете resultPole.textChanged.connect(self.pole_vivod.setText)
вы по сути передаете текст котороый генерирует resultPole.textChanged в слот self.pole_vivod.setText.
Обратите внимание что вы не указываете что именно вы пердаете, это кагбе остаеться за скобками(вернее вы передаете автоматически все что генерирует сигнал), но при этом вы должны учитывать что вы передаете в сигнале, и что может принимат слот. Тоесть аргументы сигнала передаються в слот автоматически, их не нужно специально указывать если вы делаете connect.

Kyrym
Это я знаю. Вопрос в том, как это применять на практике. Я читал, про self, но пока так и не понял.
что конкретно непонятно? По помему на тостере по вашей сссылке вполне доступно обьяснено.



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

Отредактировано PEHDOM (Апрель 18, 2017 22:18:14)

Офлайн

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

Board footer

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

Powered by DjangoBB

Lo-Fi Version