Online video hd

Смотреть мама и сын видео

Официальный сайт bok-o-bok 24/7/365

Смотреть видео бесплатно

Shihad 20.11.2010 12:59

Есть вопрос!Как правильно связать сигналы и слоты? (Python/Qt) {Решено}

В процессе написания программы управления моторчиками через Ардуино возникла следующая проблема:
Функции, управляющие моторчиками имеют от двух (номер сервопривода, значение) до трех ( + направление вращения) параметров.
Сигнал же идет от ползунка и у него только один параметр - значение.

Есть способ решить эту проблему поизящнее, чем написав отдельную функцию для каждого параметра моторчика?


Покурил Саммерфилда - "Быстрое программирование GUI", но толком не понял, можно ли это сделать с помощью partial. В источниках по Си++ утверждается, что число параметров слота должно быть равно или меньше, чем число параметров сигнала, но верно ли это для Питона?

Собственно функции.
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def Servo(self, servo=1, angle):
'''Moves the specified servo to the supplied angle.

Arguments:
servo
the servo number to command, an integer from 1-4
angle
the desired servo angle, an integer from 0 to 180

(e.g.) >>> Zeppelin.MoveServo(2, 90)
... # "move servo #2 to 90 degrees"'''
if (0 <= angle <= 180):
self.ser.write(str(255))
self.ser.write(str(servo))
self.ser.write(str(angle))
else:
print "Servo angle must be an integer between 0 and 180.\n"

def Motor(self, motor, speed, direction):
'''Moves the specified motor to the supplied speed and direction.

Arguments:
motor
the motor number to command, an integer from 1-4
speed
the desired motor speed, an integer from 0 to 254
direction (1/0)
motor direction

(e.g.) >>> Zeppelin.Motor(2, 90)
... # "move servo #2 to 90 degrees"'''
if (0 <= angle <= 254):
ser.write(chr(255))
ser.write(chr(motor))
ser.write(chr(speed))
ser.write(chr(direction))
else:
print "Motor must be an integer between 0 and 254.\n"



Вызов их из основной программы
1
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int)"), Zeppelin.Servo)




Правильным красивым ответом будет использовать функцию partial из модуля functools.
Примерно следующим образом.
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int)"), functools.partial(Zeppelin.Servo, 1))

Всем спасибо за интересную дискуссию, побудившую меня покопаться в Гугле поглубже и вдумчиво покурить Саммерфилда.


Тэги:
+ 2 -
Похожие Поделиться

f_evgeny 20.11.2010 14:04 #
+ 1 -
Думаю, что то, что верно для Qt верно и для PyQt.
Не силен в PyQT, но навскидку, что бы попробовал. Передал бы один аргумент, словарь.
Пардон, если неправильно понял задачу.
f_evgeny 20.11.2010 14:08 #
+ 0 -
Вопрос, а что нужно-то? Не очень понял задачу. Поставить механизм в определенное положение? Тогда датчик положения должен быть.
Shihad 20.11.2010 14:44 #
+ 0 -
Вообще - это дирижаблик. У него есть один сервопривод и два моторчика. Все это управляется через Ардуино, сервопривод - непосредственно с выхода, моторы подключены через драйвер.
Задача - сделать управление всем хозяйством через ком-порт.
Главное окно нарисовал. В качестве элементов управления использую ползунки (слайдеры).
Слайдер передает только один параметр - значение. Слот требует два или три параметра.
Как сделать сигнал с несколькими параметрами?

Я вижу два пути - либо переделать класс ползунка так, чтобы он еще номер мотора посылал- похоже, это то, что предлагаете Вы - либо сделать по функции на каждый параметр - отдельно направление, отдельно скорость, отдельно номер.

Оба решения мне кажутся несимпатичными. Можно ли сделать так, чтоб сигнал со значением от ползунка не просто пошел в слот, а пошел в один из несколькиз параметров слота?

Нечто вроде этого
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int)"), Zeppelin.Servo(1,value)
f_evgeny 20.11.2010 16:21 #
+ 1 -
Мне кажется, так как Вы хотите, нельзя. Т.е. указать в методе connect значение параметра для слота не получится.
Shihad 20.11.2010 16:36 #
+ 0 -
Спасибо. Отрицательный результат - тоже результат.
А никаких функций типа partial или lambda нельзя задействовать? У Саммерфилда они есть, но объяснены не слишком просто.
f_evgeny 20.11.2010 17:01 #
+ 1 -
Не думаю насчет лямбда. А может сделать так?:
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int, int)"), Zeppelin.Servo(num,value)
dront78 20.11.2010 18:20 #
+ 1 -
> Можно ли сделать так, чтоб сигнал со значением от ползунка не просто пошел в слот, а пошел в один из несколькиз параметров слота?

как ярый c++, хочу спросить - что пойдет в остальные параметры слота?
Shihad 20.11.2010 20:07 #
+ 0 -
Константа, к примеру.
f_evgeny 20.11.2010 20:42 #
+ 1 -
Поскольку у аргументов у сигнала по документации должно быть больше или равно количеству аргументов слота, константу некуда вставлять.

И в прототипе метода connect тоже не видно, как бы можно бы было подключить константу.

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection )
Shihad 20.11.2010 21:02 #
+ 0 -
А так, как вы предложили?
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int, int)"), Zeppelin.Servo(num,value)

Компилятор ругается на несоответствие типов. Возможно, просто неправильно форматирую строку.
dront78 20.11.2010 22:09 #
+ 1 -
совсем не очевидно. если уж хочется велосипед - я бы сделал что-то типа на C

void slotOnUpdate(int param1, int param2, int param3) {

static int _p1(0); static int _p2(0); static int p3(0);

if (_p1 != param1) updateParam1Func(param1);
if (_p2 != param2) updateParam2Func(param2);
if (_p3 != param3) updateParam3Func(param3);

_p1 = param1; _p2 = param2; _p3 = param3;

}
Shihad 20.11.2010 22:19 #
+ 0 -
Я питон-то только начал изучать, а вы си предлагаете. Не, си - это хорошо. Но для меня рано.
dront78 20.11.2010 22:22 #
+ 1 -
это не важно - суть просто в локальном кешировании старых значений в одном месте - мультиплексор типа ;) а он дергает 3 разных функции в зависимости от того, какое значение изменилось. в результате имеем скрытый от посторонних глаз интерфейс управления супердирижаблем, который втихую можно изменять не затрагивая другую часть программы. внутрь можно добавить обработку еще всех трех значений сразу, если надо.
Shihad 20.11.2010 22:27 #
+ 0 -
Интересно. Посмотрю, как у меня получится с драйвером двигателей - сумею ли я поменять направление и скорость? Если уже имеющийся метод не прокатит, с удовольствием воспользуюсь вашим советом.
f_evgeny 20.11.2010 22:08 #
+ 0 -
То, что я написал, явно неправильно, просто хотел передать идею, сделать сигнал с двумя параметрами и слот с двумя параметрами. Но этот сигнал с двумя параметрами тоже нужно дергать откуда-то.
Какое решение получилось?
Shihad 20.11.2010 22:20 #
+ 1 -
Воспользоваться функцией partial из functools. Примерно она делает следующее
def partial(func, arg):
def callme():
return func(arg)
return callme
Shihad 20.11.2010 22:23 #
+ 1 -
Вызвав ее так, получаю то, что требовалось.
Qt.QObject.connect(form.spinBoxAngle, Qt.SIGNAL("valueChanged(int)"), functools.partial(Zeppelin.Servo, 1))
f_evgeny 20.11.2010 22:37 #
+ 0 -
Заборол значит по питоновски! Поздравляю. А я узнал про functools. Спасибо, буду иметь в виду.
time2die 20.11.2010 23:16 #
+ 1 -
если я правильно понял, то вам подойдет паттерн адпатер
f_evgeny 21.11.2010 12:27 #
+ 1 -
Я как-то пробовал применять паттерны при программировании на Python. ИМХО это неоправданно. Ну или нужны совсем другие паттерны. Для себя я сделал следующий вывод. То, что обычно называется паттернами, придумано для C++/Java, при переносе их в том же самом виде на Python получается слишком все громоздко. На Python, когда пишешь, используя питоновский подход, получается гораздо проще/лучше. На C++/Java просто деваться некуда. А в Python есть много встроенных (или в прилагаемых "батарейках" - библиотеках) средств, которые решают многие, решаемые в паттернах задачи.
К примеру, автор вопроса использовал одну функцию из functools и все заработало. С предлагаемыми паттернами, нужно бы было определить еще один класс.
dront78 22.11.2010 14:39 #
+ 0 -
Зависит от того, какие и для чего эти паттерны применялись. То, что "точечная" задача может быть реализована с помощью syntactic sugar или стандартной либы, не отменяет паттернов в разработке ПО. Но и "в лоб" все подряд переносить не стоит конечно. Я привел лишь пример. Как и кто его реализует - не мое дело, но знание паттерна Proxy в данном случае избавило бы от длиннющих вопросов.
f_evgeny 22.11.2010 15:16 #
+ 0 -
Я не спорю, только ИМХО, паттерны (стандартные решения) в Python должны быть другие.
dront78 23.11.2010 20:23 #
+ 1 -
не хочу флудить, но питон судя по описанию - это мультипарадигменный язык общего назначения, как и c++. на вскидку нашлось Design Patterns in Python ;) просто реализовано python-based способами. некоторые отличаются от c++, но возможности предоставляются те же. повторюсь - в этом и суть паттернов IMHO - решать абстракции высокого уровня вне зависимости от языка.
f_evgeny 23.11.2010 21:27 #
+ 1 -
Почему бы доброжелательно не обсудить? При чем тут флуд. Я смотрел и пробовал применять Design Patterns in Python , если мы про одно и то же. Начинал с мнения похожего на Ваше. Но в результате пришел к своей позиции.
Если понимать Design Patterns как стандартные инженерные решения типовых задач, то я за. Но на сегодня есть нюанс. То, что обычно понимают под Design Patterns заточено в первую очередь под C++ и Java. И многие проблемы, которые в них решаются, в Python просто не возникают или лучше их решать "по питоновски". То, что я видел в сети, и что называется Design Patterns in Python - скорее перенос C++ паттернов в питон. Многие вопросы, для которых применяются паттерны в C++, в питоне решаются в одну строчку или библиотечную функцию. А многие вообще не возникают.
Вот такое вот мнение.
С уважением
Евгений
Shihad 23.11.2010 21:54 #
+ 0 -
Спасибо всем за обсуждение.
В настоящий момент я действительно воспользовался готовым враппером из functools. Вообще, по моему скромному, дао питона - "все уже написано до тебя". Это "все" надо собрать и заставить работать вместе.
Но, поскольку мне нужно было не просто решение, а решение красивое (так бы я написал костыль - несколько функций, различающихся только названиями), я благодарен dront78 за указание точки дальнейшего погружения в теорию. Применю сразу, как только смогу.
dront78 24.11.2010 10:17 #
+ 1 -
я имелл виду флуд - тема не об этом - давайте в другую ;) А то что Desing Patterns уже реализованы в питоне по питоновски - это ж круто и я только за. Единственное, с чем я не согласен, что Design patterns это для C++/Java, даже если люди хотят их так понимать.

В хорошем качестве hd видео

Онлайн видео бесплатно


Смотреть русское с разговорами видео

Online video HD

Видео скачать на телефон

Русские фильмы бесплатно

Full HD video online

Смотреть видео онлайн

Смотреть HD видео бесплатно

School смотреть онлайн