Russian Qt Forum
Сентябрь 24, 2022, 19:17 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QActions  (Прочитано 1401 раз)
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« : Май 06, 2022, 14:31 »

Добрый день!
Только начинаю изучать Qt и столкнулся с тем, что не понимаю, как устанавливается доступность/недоступность для QAction.

Везде в сети я натыкаюсь на стандартный пример примерно такого содержания:
...
    // создается QAction для копирования в буфер обмена
    const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"));
    QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this);
    copyAct->setShortcuts(QKeySequence::Copy);
    copyAct->setStatusTip(tr("Copy the current selection's contents to the clipboard"));
    connect(copyAct, &QAction::triggered, textEdit, &QPlainTextEdit::copy);
    editMenu->addAction(copyAct);
    editToolBar->addAction(copyAct);
    copyAct->setEnabled(false);

    // созданный QAction связывается с редактором для определения доступности
    connect(textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
...

Да, я понимаю, что там написано, но... У меня возникают вопросы.

1) Если текстовое поле одно на форме, то типа будет работать, но если тестовых полей больше одного, то как будет определяться доступность Action?
2) Получается, что каждый виджет должен отправлять сигналы после каждого чиха? А если виджет не знает, что за действия с ним хотят произвести? Например, у меня есть Action, который меняет регистр символов в текстовом поле. Как мне получить указание на его доступность/недоступность?

Вероятно, мои вопросы кажутся странными, но я действительно не понимаю. В других средах, например в Delphi, есть ActionList, который вызывает событие, в обработчике которого и выставляется признак доступности для каждого Action. А как это делается в Qt?

Буду очень признателен за разъяснения.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 809


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #1 : Май 06, 2022, 16:41 »

А если виджет не знает, что за действия с ним хотят произвести? Например, у меня есть Action, который меняет регистр символов в текстовом поле. Как мне получить указание на его доступность/недоступность?
Для начала нужно самому себе сформулировать задачу, которую хотите решить Подмигивающий
К примеру, если у вас несколько источников событий (виджетов или других объектов), от которых зависит состояние QAction, то логично было бы создать слот, в котором эти события анализировались и устанавливалось состояние QAction. А соответствующие сигналы этих объектов соединить с этим слотом.

Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #2 : Май 06, 2022, 17:20 »

А если виджет не знает, что за действия с ним хотят произвести? Например, у меня есть Action, который меняет регистр символов в текстовом поле. Как мне получить указание на его доступность/недоступность?
Для начала нужно самому себе сформулировать задачу, которую хотите решить Подмигивающий
К примеру, если у вас несколько источников событий (виджетов или других объектов), от которых зависит состояние QAction, то логично было бы создать слот, в котором эти события анализировались и устанавливалось состояние QAction. А соответствующие сигналы этих объектов соединить с этим слотом.



Давайте для определенности сформулируем задачу и вы, если вам не сложно, дадите пояснения?

Есть QAction для изменения регистра всех символов на верхний. Действие может быть применено к узлу дерева, ячейке таблицы, тексту из TextEdit и к тексту из LineEdit. При этом, в Editors длина текста должна быть не менее 100 символов.

Если я правильно понимаю, то нужно создать слот, который будет принимать сигналы от всех перечисленных 4 виджетов, а также от qApp об изменении активного окна. (Поправьте, если я что-то пропустил)
От TextEditor и LineEditor: изменение текста
От TreeView: смена выбранного узла
От Table: смена выбранной ячейки

Функция-слот в зависимости от текущего активного виджета определяет доступность Action.
Так?
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 809


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #3 : Май 06, 2022, 18:21 »

Чувствую, что вы опять что-то скрываете В замешательстве К чему вы упомянули "qApp об изменении активного окна"? У вас MDI? Или нужно менять доступность меню от изменения фокуса виджета? Тогда слотом не обойтись - придется переопределять фильтр событий (installEventFilter, eventFilter). Но, возможно, достаточно просто проверить фокус виджета, который отправил сигнал.
А так все верно. Но, поскольку исходные события разные (изменение текущего узла, изменение текста и т.д.), делайте на каждое событие свой слот, чтобы не строить громоздкую логику. Потом, не исключено, что-то можно будет упростить и объединить.

Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #4 : Май 06, 2022, 18:40 »

Чувствую, что вы опять что-то скрываете В замешательстве К чему вы упомянули "qApp об изменении активного окна"? У вас MDI? Или нужно менять доступность меню от изменения фокуса виджета? Тогда слотом не обойтись - придется переопределять фильтр событий (installEventFilter, eventFilter). Но, возможно, достаточно просто проверить фокус виджета, который отправил сигнал.
А так все верно. Но, поскольку исходные события разные (изменение текущего узла, изменение текста и т.д.), делайте на каждое событие свой слот, чтобы не строить громоздкую логику. Потом, не исключено, что-то можно будет упростить и объединить.



Возможно, я что-то не то наговорил, потому что я пока не совсем понимаю, как все устроено.

Но примерно начинаю понимать. Получается, что для каждого QAction надо оформлять подписку от виджетов, на которые действие распространяется? На мой взгляд, это излишне сложно и громоздко... Хотя, видимо, все равно придется делать именно так, ведь в качестве альтернативы я пока вижу только повесить на таймер обработчик, в котором определять доступность Actions. Но очевидно, что это ужасное решение...
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 809


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #5 : Май 06, 2022, 19:33 »

Но примерно начинаю понимать. Получается, что для каждого QAction надо оформлять подписку от виджетов, на которые действие распространяется?
У вас в голове каша, уж извините)) Совсем наоборот, сигналы виджетов надо соединить со слотами, к примеру (я использую сигнал из вашего примера):
Код
C++ (Qt)
MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent)
{
 
   connect(textEdit1, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
   connect(textEdit2, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
   connect(textEdit3, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
}
 
void MainWindow::actionSlot()
{
   QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(sender());
   bool len = edit->toPlainText().size();
   copyAct->setEnabled(len > 100);
}
 
Для другого типа виджета создаете другой слот, где анализируется другое условие. Ну и т.д.
В чем громоздкость?
« Последнее редактирование: Май 06, 2022, 19:37 от sergek » Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #6 : Май 06, 2022, 20:22 »

Но примерно начинаю понимать. Получается, что для каждого QAction надо оформлять подписку от виджетов, на которые действие распространяется?
У вас в голове каша, уж извините)) Совсем наоборот, сигналы виджетов надо соединить со слотами, к примеру (я использую сигнал из вашего примера):
Код
C++ (Qt)
MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent)
{
 
   connect(textEdit1, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
   connect(textEdit2, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
   connect(textEdit3, &QPlainTextEdit::copyAvailable, this, &MainWindow::actionSlot);
}
 
void MainWindow::actionSlot()
{
   QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(sender());
   bool len = edit->toPlainText().size();
   copyAct->setEnabled(len > 100);
}
 
Для другого типа виджета создаете другой слот, где анализируется другое условие. Ну и т.д.
В чем громоздкость?

Да, у меня в голове пока каша - очень уж все непривычное)) Надеюсь, все у меня уложится со временем.

Спасибо за пример!
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 809


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #7 : Май 06, 2022, 20:36 »

Впредь не нужно цитировать каждое сообщение, тем более, что вы не используете его для ответа.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Май 07, 2022, 11:10 »

Для начала нужно самому себе сформулировать задачу, которую хотите решить Подмигивающий
Желание поучать - свойство человеческой натуры Улыбающийся
А соответствующие сигналы этих объектов соединить с этим слотом.
При разрастании кода это становится неудачным/неудобным, приходится втыкать много сигналов там и сям. Др подход - дизаблить "динамически", т.е вычислять доступность айтема при открытии меню или при нажатии hotkey. Хотя и здесь свои минусы  
Записан
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #9 : Май 07, 2022, 12:14 »

Цитировать
При разрастании кода это становится неудачным/неудобным, приходится втыкать много сигналов там и сям. Др подход - дизаблить "динамически", т.е вычислять доступность айтема при открытии меню или при нажатии hotkey. Хотя и здесь свои минусы 

Согласен, что будет неудобно. Удобнее было бы написать одну процедуру, которая вызывалась бы автоматически и в ней бы определялась доступность Actions. Но, судя по всему, в Qt нет такой возможности (кроме пресловутого таймера)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Май 08, 2022, 08:26 »

Согласен, что будет неудобно. Удобнее было бы написать одну процедуру, которая вызывалась бы автоматически и в ней бы определялась доступность Actions. Но, судя по всему, в Qt нет такой возможности (кроме пресловутого таймера)
Почему нет? Потому что не хочется искать? Улыбающийся Для hotkeys есть QEvent::ShortcutOverride, момент открытия меню тоже можно поймать (здесь правда на OSX нужен нативный код)
Записан
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #11 : Май 08, 2022, 15:38 »

Почему нет? Потому что не хочется искать? Улыбающийся Для hotkeys есть QEvent::ShortcutOverride, момент открытия меню тоже можно поймать (здесь правда на OSX нужен нативный код)

Послушайте, я написал в первом сообщении: "Только начинаю изучать Qt", сообщение находится в разделе "Вопросы новичков". Неужели нельзя просто ответить на вопрос без этого трагичного наморщивания лба и пафосного "Потому что не хочется искать?"...

Почему нельзя просто дать ссылку на статью или сообщение? Повторюсь: я новичок в Qt, я пока не могу даже толком понять, что надо искать, как запрос сформулировать. Неужели это не понятно? Или вы забыли, что вы тоже когда-то были новичком?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Май 09, 2022, 11:29 »

Почему нельзя просто ...
Потому что Вам уже хочется быть экспертом Улыбающийся
Но, судя по всему, в Qt нет такой возможности (кроме пресловутого таймера)
А это не так, возможность есть
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 809


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #13 : Май 10, 2022, 23:28 »

Почему нельзя просто дать ссылку на статью или сообщение?
Добро пожаловать на форум, самый беспощадный форум в мире Улыбающийся
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
spinmozg
Новичок

Offline Offline

Сообщений: 7


Просмотр профиля
« Ответ #14 : Май 11, 2022, 08:02 »

Добро пожаловать на форум, самый беспощадный форум в мире Улыбающийся

Спасибо. Я уже все понял))
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.101 секунд. Запросов: 23.