Найти - Пользователи
Полная версия: PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a
Начало » GUI » PyQt4 | Как в функциях ссылаться на несуществующие элементы? + Разбор self'a
1 2 3 4 5
MrViktor
Kyrym
Window.in_ch_f(self,a)
self применяется и к методам, то есть если метод а экземпляра класса вызывает метод в этого же экземпляра то нужно писать так
self.in_ch_f(self,a)
Возможно еще что-то упустил (бегло код посмотрел), со временем проблема.
Kyrym
Хм… вместо Window.in_ch_f(self,a) пишу self.in_ch_f(self,a) и вижу:
TypeError: in_ch_f() takes 2 positional arguments but 3 were given
Видимо, надо ещё что-то менять.
PEHDOM
Kyrym
Хм… вместо Window.in_ch_f(self,a) пишу self.in_ch_f(self,a) и вижу:
вы можете вместо Window.in_ch_f(self,a) писать self.in_ch_f(a)
Вообще вы вроде начали понимать, но надобы еще потренироваться.
Например у вас есть метод def in_ch_f(self,x):, если вам self.x нужен исключительно для проверки\преобразования то можно сделать чтобы функция сразу возвращала нужное значение, без присваивания времменой переменной:
 # -*- 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)
        a = self.in_ch_f(a)  # Да, можно вот так
        print('on_start после функции, a =',a)
        ap(a)
        print('-'*50)
        b = self.pole_2.text()  # Да, можно вот так
        print('on_start до функции, b =',b)
        b = self.in_ch_f(b)
        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:
            x = float(x)
            print('try, x =',x)
        except (TypeError, ValueError):
            print('except, x =',x)
            x = 0
        return x
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window() # создаёт экземпляр окна из класса
    window.show() # запускает окно
    sys.exit(app.exec_())
или даже так:
 # -*- 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)
        a = Window.in_ch_f(a)  # вызываем  in_ch_f через класс 
        print('on_start после функции, a =',a)
        ap(a)
        print('-'*50)
        b = self.pole_2.text()
        print('on_start до функции, b =',b)
        b = self.in_ch_f(b)   # вызываем  in_ch_f через экземпляр
        print('on_start после функции, b =',b)
        ap(b)
        print('='*50)
        for i in data:
            self.pole_vivod.append(str(i))
    @staticmethod    #декоратор указывающий на то  что  in_ch_f статический метод
    def in_ch_f(x):   # Обратите внимание self отсутвует как аргумент
        try:
            x = float(x)
            print('try, x =',x)
        except (TypeError, ValueError):
            print('except, x =',x)
            x = 0
        return x    # возвращаем значение
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window() # создаёт экземпляр окна из класса
    window.show() # запускает окно
    sys.exit(app.exec_())

во втором случае у нас появился декоратор @staticmethod , это означает сто следующая за декоратором функция статичный метод.
В статичные методы, в отличие, скажем, от обычных или от classmethod(), не передаётся первый аргумент неявным образом. Тоесть по сути это простая функция внутри класса. Вызывается как через класс: a = Window.in_ch_f(a) , так и через экземпляр: b = self.in_ch_f(b), при этом данные экземпляра игнорируются, а принимаются во внимание только данные его класса.
Статические методы можно вызывать не создавая экземпляр классса.

Kyrym
Суть в том, что ссылаясь a = self.x и b = self.x, я получаю разные self.x
не совсем просто перед тем как получить self.x вы в методе in_ch_f меняете его значение.
ну и в except: надо бы указывать тип исключения
Kyrym
Получилось компактнее, что радует.
Kyrym
Решил писать в свою тему.
Есть код:
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                         QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                         QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,                         
                          QBrush, QColor)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(300, 100) # шир / выс окна
        self.setWindowTitle('несущ') # Заголовок
        grid = QGridLayout()
        grid.setSpacing(5)
        # --- ---
        self.columnCount = 4
        self.lines = [None for i in range(self.columnCount)]
        #lst_on_start = ['self.on_start'+str(i) for i in range(columnCount)]
        #print('lst_on_start =',lst_on_start)
        for col in range(self.columnCount):
            line = QLineEdit()
            self.lines[col] = line
            grid.addWidget(line,0,col+1)
            self.lines[col].textChanged.connect(self.on_start)
            #self.lines[col].textChanged.connect(lst_on_start[col])
        # --- ---
        self.setLayout(grid)
    def on_start(self):
        print('1')
        lst_data = []
        for i in range(self.columnCount):
            lst_data.append(self.lines[i].text())
        print('lst_data =',lst_data)
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.move(40, 20) # сдвиг окна от верхнего левого угла экрана    
    window.show()
    sys.exit(app.exec_())
1 строка, 4 столбца. 1 функция ловит изменения текста в 4х ЛайнЭдитах.
В результате получим список вида:
 lst_data = ['4', '', '16', '']
Таки образом я могу собрать с полей весь текст , который там есть и обработать его. Однако меня интересует такой вопрос: как понять, какое поле заполнялось последним?
Может ли сигнал textChanged передавать информацию об имени текстового поля (либо его индексе) в функцию on_start?
Если заполнять одно поле, то его “индекс” находится просто, а если появляется второе заполненое поле, то всё… не знаю.
vic57
qlineedit.textChanged передает текст в аргументах
RTFM
https://pythonworld.ru/gui/pyqt5-widgets2.html
Kyrym
Да, таким образмо я смогу узнать последний переданный текст, найду его в своём списке lst_data, а значит, выясню через поиск номер столбца.

А сам сигнал textChanged не может передать некую заданную информацию, номер колонки в данном случае?

Пока так:
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                         QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                         QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,                         
                          QBrush, QColor)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(300, 100) # шир / выс окна
        self.setWindowTitle('несущ') # Заголовок
        grid = QGridLayout()
        grid.setSpacing(5)
        # --- ---
        self.columnCount = 4
        self.lines = [None for i in range(self.columnCount)]
        #lst_on_start = ['self.on_start'+str(i) for i in range(columnCount)]
        #print('lst_on_start =',lst_on_start)
        for col in range(self.columnCount):
            line = QLineEdit()
            self.lines[col] = line
            grid.addWidget(line,0,col+1)
            self.lines[col].textChanged.connect(self.on_start)
            #self.lines[col].textChanged.connect(lst_on_start[col])
        # --- ---
        self.setLayout(grid)
    def on_start(self, text):
        print('1')
        lst_data = []
        for i in range(self.columnCount):
            lst_data.append(self.lines[i].text())
        col_index = lst_data.index(text)
        print('lst_data =',lst_data)
        print('Столбец №',col_index)
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.move(40, 20) # сдвиг окна от верхнего левого угла экрана    
    window.show()
    sys.exit(app.exec_())
PEHDOM
Kyrym
А сам сигнал textChanged не может передать некую заданную информацию, номер колонки в данном случае?
можно создать свой сигнал, котороый будет передавать все что угодно, хоть номкр колонки, хоть черта лысого..
Kyrym
PEHDOM
можно создать свой сигнал
Свои элементы создавать сложно (для меня), потом оказывается, что нужно многое предусмотреть.

Мне понравился вариант vic57. Переделал его код под свою программу:
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                         QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                         QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,                         
                          QBrush, QColor)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(300, 100) # шир / выс окна
        self.setWindowTitle('несущ') # Заголовок
        grid = QGridLayout()
        grid.setSpacing(5)
        # --- ---
        self.columnCount = 4
        self.lst_obj_name = ['line' + str(i) for i in range(self.columnCount)]
        self.lines = [None for i in range(self.columnCount)]
        for col in range(self.columnCount):
            line = QLineEdit()
            line.setObjectName('line' + str(col))
            self.lines[col] = line
            self.lines[col].textChanged.connect(self.on_start)
            grid.addWidget(line,0,col)
        # --- ---
        self.setLayout(grid)
    def on_start(self):
        print('press',self.sender().objectName(),self.sender().text())
        col_index = self.lst_obj_name.index(self.sender().objectName())
        print('Столбец №',col_index)
        
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.move(40, 20) # сдвиг окна от верхнего левого угла экрана    
    window.show()
    sys.exit(app.exec_())
У меня было плохо то, что если в столбцы вводить одинаковый текст, то программа будет выдавать неверный результат.
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