Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > [QT4] переключить виджет в режим "на показ"


Автор: JackYF 11.10.2007, 23:27
Итак, дан виджет, например QTextEdit.

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

Документацию QT4 рыл, не нарыл.

Автор: archimed7592 12.10.2007, 08:45
Есть три идеи, работоспособность которых тебе придётся проверить самому(ибо у меня времени нет).

1. Унаследоваться от необходимого виджета и переопределить ф-цию event в которой и фильтровать все события, кроме отрисовки.
2. Возможно setFocusPolicy(Qt::NoFocus) сделает всё что тебе нужно.
3. Заменить нужный виджет пустым, но старый не удалять, а делать для него realWidget->render(dummyWidget/*, ... */), когда необходима перерисовка.

Автор: bsa 12.10.2007, 11:22
Интересно, а что если его просто выключить (setDisabled )?

Автор: archimed7592 12.10.2007, 11:25
Це иногда изменяет внешний вид(становится серым, к примеру)...

Автор: bsa 12.10.2007, 11:27
archimed7592, да. Но в т.з. не указано, что он должен отображаться, как обычно. smile

Автор: mes 12.10.2007, 11:44
Цитата(JackYF @ 11.10.2007,  23:27)
Итак, дан виджет, например QTextEdit.

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

Чтоб TextEdit не принимал изменения нужно  установить флаг ReadOnly 

Автор: archimed7592 12.10.2007, 12:40
mes, а если другой виджет smile?

Речь не о TextEdit конкретно:
Цитата(JackYF @  11.10.2007,  23:27 Найти цитируемый пост)
Итак, дан виджет, например QTextEdit.


Автор: JackYF 12.10.2007, 17:49
Цитата(archimed7592 @  12.10.2007,  08:45 Найти цитируемый пост)
1. Унаследоваться от необходимого виджета и переопределить ф-цию event в которой и фильтровать все события, кроме отрисовки.

попробую


Цитата(archimed7592 @  12.10.2007,  08:45 Найти цитируемый пост)
2. Возможно setFocusPolicy(Qt::NoFocus) сделает всё что тебе нужно.

пробовал - не помогает.


Цитата(archimed7592 @  12.10.2007,  08:45 Найти цитируемый пост)
3. Заменить нужный виджет пустым, но старый не удалять, а делать для него realWidget->render(dummyWidget/*, ... */), когда необходима перерисовка.

пока не очень понял, но пороюсь в документации

Цитата(archimed7592 @  12.10.2007,  11:25 Найти цитируемый пост)
Це иногда изменяет внешний вид(становится серым, к примеру)...

абсолютно верно, поэтому и не подходит

Цитата(mes @  12.10.2007,  11:44 Найти цитируемый пост)
Чтоб TextEdit не принимал изменения нужно  установить флаг ReadOnly  

это само собой. Этот флаг и так установлен в первую очередь. Но курсор при наведении на виджет меняется и можно выделять даже read-only текст. + контекстное меню, которого быть не должно.

Цитата(bsa @  12.10.2007,  11:27 Найти цитируемый пост)
Но в т.з. не указано, что он должен отображаться, как обычно. smile 

Исправляюсь. Виджет должен отображаться, как обычно smile  smile 

Автор: nickless 15.10.2007, 16:34
Вот еще вариант решения, возможно не самый красивый, но очень эффективный smile 

Поставить у нужного виджета focusPolicy = Qt::NoFocus, и положить сверху него QFrame того же размера, с frameShape = QFrame::NoFrame и autoFillBackground = false.
Будет всё видно, но до самого виджета юзер не доберётся.
Лучше это даже оформить в какой-нибудь контейнерный WidgetHider класс, который это всё делает (порядок создания виджетов похоже имеет значение, фрэйм надо позже создавать, по крайней мере в дизайнере).

Автор: JackYF 15.10.2007, 18:51
Цитата(nickless @  15.10.2007,  16:34 Найти цитируемый пост)
Поставить у нужного виджета focusPolicy = Qt::NoFocus, и положить сверху него QFrame того же размера, с frameShape = QFrame::NoFrame и autoFillBackground = false.
Будет всё видно, но до самого виджета юзер не доберётся.
Лучше это даже оформить в какой-нибудь контейнерный WidgetHider класс

Очень неплохая идея, обязательно в скором времени попробую. Как только разгребусь с остальным...

Никто не забыт, ничто не забыто (с) smile

Автор: JackYF 19.10.2007, 00:21
Цитата(archimed7592 @  12.10.2007,  08:45 Найти цитируемый пост)
1. Унаследоваться от необходимого виджета и переопределить ф-цию event в которой и фильтровать все события, кроме отрисовки.

Начал пробовать эту идею, однако эффект не тот немного...

Код

bool RichBoxWidget::event(QEvent* event)
{
    if (event->type() == QEvent::Paint)
    {
        QWidget::paintEvent((QPaintEvent*)event);
        return true;
    }
    else
    {
        return false;
    }
}

Следующий код оставляет изменение мышиного курсора и возможность выделения текста, при этом рамочки фрейма перестают почему-то рисоваться... Наверное, не подойдёт.

Автор: archimed7592 19.10.2007, 04:43
Гхм... Что это ещё за c-style касты? 0_о
А если так:
Код

bool RichBoxWidget::event(QEvent* e)
{
    if (e->type() == QEvent::Paint)
    {
        return Base::event(e); // Base - класс от которого унаследовался...
    }
    else
    {
        return true;
    }
}

Автор: JackYF 19.10.2007, 14:10
Цитата(archimed7592 @  19.10.2007,  04:43 Найти цитируемый пост)
Base - класс от которого унаследовался...

QWidget и есть....

попробуем-с...


Цитата(archimed7592 @  19.10.2007,  04:43 Найти цитируемый пост)
Гхм... Что это ещё за c-style касты? 0_о

гм... static_cast<QPaintEvent*>(event) и иже с ним это правильно, но длинно, поэтому данные штуки я обычно пишу только в библиотечках...
В обычном юзеркоде (как здесь) жалею символы... Возможно, я поменяю данное мнение.

Автор: archimed7592 19.10.2007, 14:18
Цитата(JackYF @  19.10.2007,  14:10 Найти цитируемый пост)
гм... static_cast<QPaintEvent*>(event) и иже с ним это правильно, но длинно, поэтому данные штуки я обычно пишу только в библиотечках...
В обычном юзеркоде (как здесь) жалею символы... Возможно, я поменяю данное мнени

Всю конструкцию можно заменить этим:
Код

if (QPaintEvent *casted = qobject_cast< QPaintEvent * >(event))
{
  // ...
}

Два в одном smile.

Автор: JackYF 19.10.2007, 14:29
Цитата(archimed7592 @  19.10.2007,  14:18 Найти цитируемый пост)
Два в одном smile. 

тоже вариант (в данном случае).

Автор: JackYF 19.10.2007, 22:28
Цитата(JackYF @  19.10.2007,  14:10 Найти цитируемый пост)
QWidget и есть....

тьфу, не QWidget, а тот самый QTextEdit.

Цитата(archimed7592 @  19.10.2007,  04:43 Найти цитируемый пост)
А если так

уже лучше. Остался курсор, осталось выделение, остальное ушло.

Исследую дальше. При выделении текста и изменении курсора виджету, как было выяснено при дебаговом выводе, не посылаются сообщения. Следовательно, через виджет я заблокировать их я не могу.

Автор: JackYF 19.10.2007, 22:46
Плюнул на всё, создал прозрачный фрейм по совету nickless, с помощью QGridLayout добавил эти два виджета в одну ячейку.
Требуемая функциональность достигнута.  smile 

Всем еще раз большое спасибо за участие, тему закрываю smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)