Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 21:03
Оценка:
Здравствуйте!

Хоткеи создаю так:
        QAction *pa = new QAction( QIcon(), "0", this );
        pa->setShortcut( QKeySequence( /* Qt::CTRL + */  Qt::Key_0) );
        connect( pa, &QAction::triggered, this, &MainWindow::slotShortcut0 ); // SLOT(slotShortcut0())
        this->addAction(pa);


Так работает. Но мне нужно динамически добавлять хоткей на один и тот же обработчик, при этом требуется их различать.
Обработчик выглядит так:
void slotShortcut( int id );


События я различаю по ID.

Докопался вроде, что следует использовать QSignalMapper. Но вот нихрена не понял, как это сделать
Маньяк Робокряк колесит по городу
Re: Нужно несколько горячих клавиш повесить на одну функцию
От: SaZ  
Дата: 29.09.19 21:21
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте!


M>...

M>Докопался вроде, что следует использовать QSignalMapper. Но вот нихрена не понял, как это сделать

Для начала нужно понять вашу логику, как вы планируете делать разные действия по одному и тому же хоткею?

А вообще вместо QSignalMapper проще заюзать лямбды с захватом в качестве слота.
Отредактировано 29.09.2019 21:25 SaZ . Предыдущая версия .
Re[2]: Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 21:25
Оценка:
Здравствуйте, SaZ, Вы писали:


M>>...

M>>Докопался вроде, что следует использовать QSignalMapper. Но вот нихрена не понял, как это сделать

SaZ>Для начала нужно понять вашу логику, как вы планируете делать разные действия по одному и тому же хоткею?


Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9

Похоже, через сигнал-слоты не получится нормально, придется ставить case в оконную процедурупереопределять функцию event
Маньяк Робокряк колесит по городу
Re[3]: Нужно несколько горячих клавиш повесить на одну функцию
От: SaZ  
Дата: 29.09.19 21:27
Оценка:
Здравствуйте, Marty, Вы писали:

M>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9


Так у вас на каждую кнопку будет свой хоткей тогда =). По тексту различайте. В документации по QSignalMapper есть практически ваш пример. Там хоть инт, хоть стринг принимаются.
P.S. я чуть обновил предыдущее сообщение.

M>Похоже, через сигнал-слоты не получится нормально, придется ставить case в оконную процедурупереопределять функцию event

Можно, но не нужно.
Re[3]: Нужно несколько горячих клавиш повесить на одну функцию
От: SaZ  
Дата: 29.09.19 21:31
Оценка: 6 (1)
Здравствуйте, Marty, Вы писали:

M>...

M>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9

Псевдокод:

for ( int i = 0; i <= 9; i++ )
{
  auto handler = [=]()
  {
    std::cout << "hotkey id = " << i;
  };
  
  const auto text = QString("%d").arg(i)
  QAction *pa = new QAction( QIcon(), text, this );
  pa->setShortcut( QKeySequence( /* Qt::CTRL + */  Qt::Key_0 + i) );
  connect( pa, &QAction::triggered, handler );
  this->addAction(pa);
}


Но если хотите, можно повозиться с QSignalMapper. Хотя я на практике ни разу его не использовал.
Re[4]: Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 21:34
Оценка:
Здравствуйте, SaZ, Вы писали:

M>>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9


SaZ>Так у вас на каждую кнопку будет свой хоткей тогда =). По тексту различайте. В документации по QSignalMapper есть практически ваш пример. Там хоть инт, хоть стринг принимаются.


  этот, что ли
class ButtonWidget : public QWidget
{
    Q_OBJECT

public:
    ButtonWidget(QStringList texts, QWidget *parent = 0);

signals:
    void clicked(const QString &text);

private:
    QSignalMapper *signalMapper;
};
The only function that we need to implement is the constructor:

ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
    : QWidget(parent)
{
    signalMapper = new QSignalMapper(this);

    QGridLayout *gridLayout = new QGridLayout;
    for (int i = 0; i < texts.size(); ++i) {
        QPushButton *button = new QPushButton(texts[i]);
        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        signalMapper->setMapping(button, texts[i]);
        gridLayout->addWidget(button, i / 3, i % 3);
    }

    connect(signalMapper, SIGNAL(mapped(const QString &)),
            this, SIGNAL(clicked(const QString &)));

    setLayout(gridLayout);
}


Я в сигналах и слотах разбираюсь, как свинья в апельсинах. Так и не понял, как это к QAction прикрутить


SaZ>P.S. я чуть обновил предыдущее сообщение.


А вот с лямбдой — идея неплохая



M>>Похоже, через сигнал-слоты не получится нормально, придется ставить case в оконную процедурупереопределять функцию event

SaZ>Можно, но не нужно.

Без лямбды — был бы самый нормальный вариант
Маньяк Робокряк колесит по городу
Re[5]: Нужно несколько горячих клавиш повесить на одну функц
От: SaZ  
Дата: 29.09.19 21:39
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, SaZ, Вы писали:


M>>>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9


SaZ>>Так у вас на каждую кнопку будет свой хоткей тогда =). По тексту различайте. В документации по QSignalMapper есть практически ваш пример. Там хоть инт, хоть стринг принимаются.


M>
  этот, что ли
M>class ButtonWidget : public QWidget
M>{
M>    Q_OBJECT

M>public:
M>    ButtonWidget(QStringList texts, QWidget *parent = 0);

M>signals:
M>    void clicked(const QString &text);

M>private:
M>    QSignalMapper *signalMapper;
M>};
M>The only function that we need to implement is the constructor:

M>ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
M>    : QWidget(parent)
M>{
M>    signalMapper = new QSignalMapper(this);

M>    QGridLayout *gridLayout = new QGridLayout;
M>    for (int i = 0; i < texts.size(); ++i) {
M>        QPushButton *button = new QPushButton(texts[i]);
M>        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
M>        signalMapper->setMapping(button, texts[i]);
M>        gridLayout->addWidget(button, i / 3, i % 3);
M>    }

M>    connect(signalMapper, SIGNAL(mapped(const QString &)),
M>            this, SIGNAL(clicked(const QString &)));

M>    setLayout(gridLayout);
M>}


Он самый. Суть маппера в том, что он ловит сигнал без параметра, потом по отправителю смотрит, что нужно в качестве параметра использовать, потом бросает свой сигнал, но уже с параметром. Такой вот прокси класс, паттерн "посредник". В примере вместо button будет ваш QAction.

M>Я в сигналах и слотах разбираюсь, как свинья в апельсинах. Так и не понял, как это к QAction прикрутить


Стоит разобраться, причём хорошо, без этого Qt практически бесполезен. Потому что на Qt-шном эвент лупе и сигналах-слотах строится достаточно удобная событийная модель программирования.

M>Без лямбды — был бы самый нормальный вариант


Есть на то реальные причины?
Отредактировано 29.09.2019 21:40 SaZ . Предыдущая версия .
Re[4]: Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 21:48
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Псевдокод:


Да, так работает, спасибо


SaZ>Но если хотите, можно повозиться с QSignalMapper. Хотя я на практике ни разу его не использовал.


Ну, так-то да
Маньяк Робокряк колесит по городу
Re[6]: Нужно несколько горячих клавиш повесить на одну функц
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 21:55
Оценка:
Здравствуйте, SaZ, Вы писали:


M>>>>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9


SaZ>>>Так у вас на каждую кнопку будет свой хоткей тогда =). По тексту различайте. В документации по QSignalMapper есть практически ваш пример. Там хоть инт, хоть стринг принимаются.



SaZ>Он самый. Суть маппера в том, что он ловит сигнал без параметра, потом по отправителю смотрит, что нужно в качестве параметра использовать, потом бросает свой сигнал, но уже с параметром. Такой вот прокси класс, паттерн "посредник". В примере вместо button будет ваш QAction.


Суть я понимаю. Я не понимаю, почему оно не работает


M>>Я в сигналах и слотах разбираюсь, как свинья в апельсинах. Так и не понял, как это к QAction прикрутить


SaZ>Стоит разобраться, причём хорошо, без этого Qt практически бесполезен. Потому что на Qt-шном эвент лупе и сигналах-слотах строится достаточно удобная событийная модель программирования.


Да в обще вроде разобрался, непонятны только два момента какого чорта оно иногда не собирается, выдавая не слишком понятное сообщение, и второй момент — это почему оно собирается, но не работает


M>>Без лямбды — был бы самый нормальный вариант


SaZ>Есть на то реальные причины?


Я имел в виду, что если бы лямбд не было бы, то через переопределение event имхо было бы проще всего. Ну, а так — с лямбдой да, вообще элементарно. Я что-то не подумал, что тут лямбды поддерживаются
Маньяк Робокряк колесит по городу
Re[4]: Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.19 22:00
Оценка:
Здравствуйте, SaZ, Вы писали:

M>>...

M>>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9

SaZ>Псевдокод:


Кстати, а как потом расконнектить такое?
Маньяк Робокряк колесит по городу
Re[5]: Нужно несколько горячих клавиш повесить на одну функц
От: SaZ  
Дата: 30.09.19 08:38
Оценка: 4 (1)
Здравствуйте, Marty, Вы писали:

M>Кстати, а как потом расконнектить такое?


Запоминайте куда-нибудь то, что вам вернул connect, а когда надо отконнектить, то просто QObject::disconnect.
Отредактировано 30.09.2019 8:40 SaZ . Предыдущая версия . Еще …
Отредактировано 30.09.2019 8:39 SaZ . Предыдущая версия .
Re: Нужно несколько горячих клавиш повесить на одну функцию
От: Denwer Россия  
Дата: 30.09.19 14:05
Оценка: 6 (2)
Здравствуйте, Marty, Вы писали:

M>Здравствуйте!


M>Хоткеи создаю так:

M>
M>        QAction *pa = new QAction( QIcon(), "0", this );
        pa->>setShortcut( QKeySequence( /* Qt::CTRL + */  Qt::Key_0) );
M>        connect( pa, &QAction::triggered, this, &MainWindow::slotShortcut0 ); // SLOT(slotShortcut0())
        this->>addAction(pa);
M>


M>Так работает. Но мне нужно динамически добавлять хоткей на один и тот же обработчик, при этом требуется их различать.

M>Обработчик выглядит так:
M>
void slotShortcut( int id );


M>События я различаю по ID.


M>Докопался вроде, что следует использовать QSignalMapper. Но вот нихрена не понял, как это сделать


Можно использовать функцию sender внутри обработчика MainWindow::slotShortcut0, что бы понять кто кинул сигнал.

UPD: А когда получил QAction через sender , то можно взять юзерские данные через data(), куда заранее положишь цифры от 1 до 9, как в твоем примере выше.
Отредактировано 30.09.2019 14:08 Denwer . Предыдущая версия .
Re[2]: Нужно несколько горячих клавиш повесить на одну функцию
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.09.19 16:31
Оценка:
Здравствуйте, Denwer, Вы писали:


D>Можно использовать функцию sender внутри обработчика MainWindow::slotShortcut0, что бы понять кто кинул сигнал.


Об этом я позже узнал, но спс.


D>UPD: А когда получил QAction через sender , то можно взять юзерские данные через data(), куда заранее положишь цифры от 1 до 9, как в твоем примере выше.


Тоже интересно.

Но пока лямбдами обошелся
Маньяк Робокряк колесит по городу
Re[5]: Нужно несколько горячих клавиш повесить на одну функцию
От: Igore Россия  
Дата: 01.10.19 08:11
Оценка: 7 (2)
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, SaZ, Вы писали:


M>>>...

M>>>Чего тут понимать — хоткеи разные, например, кнопки 1, 2, 3, ... 9, 0 — вызывается один обработчик с параметром int, который может принимать значения 0 — 9

SaZ>>Псевдокод:


M>Кстати, а как потом расконнектить такое?


QAction *pa = new QAction( QIcon(), text, this );
pa->setShortcut( QKeySequence( /* Qt::CTRL + */  Qt::Key_0 + i) );
connect( pa, &QAction::triggered, handler );
pa->disconnect();//Удалить все коннекты данного QAction
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.