Russian Qt Forum

Qt => Вопросы новичков => Тема начата: spinmozg от Май 06, 2022, 14:31



Название: QActions
Отправлено: spinmozg от Май 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?

Буду очень признателен за разъяснения.


Название: Re: QActions
Отправлено: sergek от Май 06, 2022, 16:41
А если виджет не знает, что за действия с ним хотят произвести? Например, у меня есть Action, который меняет регистр символов в текстовом поле. Как мне получить указание на его доступность/недоступность?
Для начала нужно самому себе сформулировать задачу, которую хотите решить ;)
К примеру, если у вас несколько источников событий (виджетов или других объектов), от которых зависит состояние QAction, то логично было бы создать слот, в котором эти события анализировались и устанавливалось состояние QAction. А соответствующие сигналы этих объектов соединить с этим слотом.



Название: Re: QActions
Отправлено: spinmozg от Май 06, 2022, 17:20
А если виджет не знает, что за действия с ним хотят произвести? Например, у меня есть Action, который меняет регистр символов в текстовом поле. Как мне получить указание на его доступность/недоступность?
Для начала нужно самому себе сформулировать задачу, которую хотите решить ;)
К примеру, если у вас несколько источников событий (виджетов или других объектов), от которых зависит состояние QAction, то логично было бы создать слот, в котором эти события анализировались и устанавливалось состояние QAction. А соответствующие сигналы этих объектов соединить с этим слотом.



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

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

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

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


Название: Re: QActions
Отправлено: sergek от Май 06, 2022, 18:21
Чувствую, что вы опять что-то скрываете :-\ К чему вы упомянули "qApp об изменении активного окна"? У вас MDI? Или нужно менять доступность меню от изменения фокуса виджета? Тогда слотом не обойтись - придется переопределять фильтр событий (installEventFilter, eventFilter). Но, возможно, достаточно просто проверить фокус виджета, который отправил сигнал.
А так все верно. Но, поскольку исходные события разные (изменение текущего узла, изменение текста и т.д.), делайте на каждое событие свой слот, чтобы не строить громоздкую логику. Потом, не исключено, что-то можно будет упростить и объединить.



Название: Re: QActions
Отправлено: spinmozg от Май 06, 2022, 18:40
Чувствую, что вы опять что-то скрываете :-\ К чему вы упомянули "qApp об изменении активного окна"? У вас MDI? Или нужно менять доступность меню от изменения фокуса виджета? Тогда слотом не обойтись - придется переопределять фильтр событий (installEventFilter, eventFilter). Но, возможно, достаточно просто проверить фокус виджета, который отправил сигнал.
А так все верно. Но, поскольку исходные события разные (изменение текущего узла, изменение текста и т.д.), делайте на каждое событие свой слот, чтобы не строить громоздкую логику. Потом, не исключено, что-то можно будет упростить и объединить.



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

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


Название: Re: QActions
Отправлено: sergek от Май 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);
}
 
Для другого типа виджета создаете другой слот, где анализируется другое условие. Ну и т.д.
В чем громоздкость?


Название: Re: QActions
Отправлено: spinmozg от Май 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);
}
 
Для другого типа виджета создаете другой слот, где анализируется другое условие. Ну и т.д.
В чем громоздкость?

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

Спасибо за пример!


Название: Re: QActions
Отправлено: sergek от Май 06, 2022, 20:36
Впредь не нужно цитировать каждое сообщение, тем более, что вы не используете его для ответа.


Название: Re: QActions
Отправлено: Igors от Май 07, 2022, 11:10
Для начала нужно самому себе сформулировать задачу, которую хотите решить ;)
Желание поучать - свойство человеческой натуры :)
А соответствующие сигналы этих объектов соединить с этим слотом.
При разрастании кода это становится неудачным/неудобным, приходится втыкать много сигналов там и сям. Др подход - дизаблить "динамически", т.е вычислять доступность айтема при открытии меню или при нажатии hotkey. Хотя и здесь свои минусы  


Название: Re: QActions
Отправлено: spinmozg от Май 07, 2022, 12:14
Цитировать
При разрастании кода это становится неудачным/неудобным, приходится втыкать много сигналов там и сям. Др подход - дизаблить "динамически", т.е вычислять доступность айтема при открытии меню или при нажатии hotkey. Хотя и здесь свои минусы 

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


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


Название: Re: QActions
Отправлено: spinmozg от Май 08, 2022, 15:38
Почему нет? Потому что не хочется искать? :) Для hotkeys есть QEvent::ShortcutOverride, момент открытия меню тоже можно поймать (здесь правда на OSX нужен нативный код)

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

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


Название: Re: QActions
Отправлено: Igors от Май 09, 2022, 11:29
Почему нельзя просто ...
Потому что Вам уже хочется быть экспертом :)
Но, судя по всему, в Qt нет такой возможности (кроме пресловутого таймера)
А это не так, возможность есть


Название: Re: QActions
Отправлено: sergek от Май 10, 2022, 23:28
Почему нельзя просто дать ссылку на статью или сообщение?
Добро пожаловать на форум, самый беспощадный форум в мире :)


Название: Re: QActions
Отправлено: spinmozg от Май 11, 2022, 08:02
Добро пожаловать на форум, самый беспощадный форум в мире :)

Спасибо. Я уже все понял))