Название: Выравнивание виджета в ячейке таблицы Отправлено: dolphinik от Ноябрь 04, 2008, 18:46 Добрый день.
Подскажите как можно выровнять по-центру QCheckBox в ячейке QTableWidget? Или как сделать то же самое с обычным QTableWidgetItem с установленной опцией setCheckState ? Опция setTextAlignment не помагает. Вот краткие примеры одного и другого случаев 1 Код:
2 Код: item = QtGui.QCheckBox() Измучился уже вконец... Название: Re: Выравнивание виджета в ячейке таблицы Отправлено: EhTemka от Ноябрь 13, 2008, 13:37 Как выровнить QCheckBoxы не знаю, но я как то писал таблицу с большим количеством ячеек, где должны были эти чекбоксы рисоваться. Причем они должны были срабатывать сразу, то бишь по одному клику на ячейку(без предварительного клика для открытия редактирования). Там у меня все рисовалось по центру, причем не сами QCheckBoxы (так как это тормозило), а их изображение.
Если тебя это устроит могу дать код. Там всего то надо переопределить паинт в делегате и событие клика в таблице. Название: Re: Выравнивание виджета в ячейке таблицы Отправлено: kirill от Январь 13, 2010, 09:52 Добавлять не QCheckBox а Виджет с Лэйаутом в который помещен КуЧекБокс
Код
Название: Re: Выравнивание виджета в ячейке таблицы Отправлено: sibmail от Февраль 08, 2011, 11:39 а как потом проверить состояние чекбокса?
Название: Re: Выравнивание виджета в ячейке таблицы Отправлено: vfilatov от Февраль 09, 2011, 16:15 По поводу выравнивания чекбоксов есть вариант решения в факе (http://developer.qt.nokia.com/faq/answer/how_can_i_align_the_checkboxes_in_a_view), но он кривоватый (попробуйте - увидите сами), поэтому хочу предложить свой, модифицированный.
Итак, нам необходимо определить свой класс делегата: Код: class ItemDelegate : public QItemDelegate Отрисовка Чтобы нарисовать чекбокс по центру ячейки достаточно переопределить метод drawCheck. В него передаётся параметр rect, мы его модифицируем, сместив в центр и вызовем метод базового класса: Код: void ItemDelegate::drawCheck(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, Qt::CheckState state) const { Если сейчас сделать и запустить тестовый проект с таким кодом, то мы увидим, что чекбокс рисуется по центру, как мы и хотели... до тех пор, пока мы не выделим ячейку. А при выделении ячейки цвет выделения полностью закрашивает наш чекбокс. Происходит это потому, что переместив чекбокс в центр ячейки, мы теперь его рисуем в области, где Qt рисует текст. Рисование текста происходит это в функции drawDisplay, которая вызывается после drawCheck. В ней Qt заливает область цветом выделения, затем рисует текст. Текст у нас пустой (иначе зачем бы мы стали выравнивать чекбокс по центру), однако заливка цветом выделения всё равно происходит. Зачем Qt так делает, я не понял, ведь при отрисовке ячейки первым делом вызывается функция drawBackground, которая заливает всю ячейку нужным цветом, поэтому в drawDisplay происходит повторная заливка части уже залитой области. Проще всего избавиться от этого поведения - переопределить функцию drawDisplay просто оставив её пустой: Код: void ItemDelegate::drawDisplay(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& text) const { Теперь можно видеть, что чекбоксы у нас рисуются по центру как в выделенных, так и в не выделенных ячейках. Если вы устанавливаете делегат только на столбцы с чекбоксами, то можно сразу переходить к части Редактирование. Однако я, как правило, устанавливаю один делегат на всю таблицу и предоставляю ему самому разбираться, где чекбоксы, где нет и правильно отрисовывать любые ячейки. Для этого придётся ещё немного поработать. Главное что нам нужно знать - рисуем ли мы сейчас ячейку с чекбоксом или ячейку другого типа, а точнее, нам достаточно знать, присутствует ли в отрисовываемой ячейке текст или нет. Ячейки с текстом, даже чекбоксы, нам надо рисовать как обычно. К сожалению, в методе drawCheck узнать это, похоже, нельзя (или я не знаю как), поэтому необходимо переопределить функцию paint: Код: void ItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { Последовательность вызовов здесть такая: при отрисовке ячейки сначала вызывается функция paint, в которой мы устанавливаем флажок наличия в ячейке текста. Потом мы вызываем функцию базового класса из которой вызовутся наши переопределённые drawCheck и drawDisplay. Переменная _draw_display должна иметь тип mutable bool, потому что нам приходится модифицировать её в константной функции paint. Теперь drawCheck будет выглядить таким образом: Код: void ItemDelegate::drawCheck(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, Qt::CheckState state) const { А drawDisplay таким: Код: void ItemDelegate::drawDisplay(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& text) const { Т.е. логика простейшая: если текст в ячейке есть, то мы ничего не трогаем, всю работу делают базовые функции (чекбоксы с текстом мы не выравниваем, я думаю, это логично). Если текста нет, вмешиваемся в процесс отрисовки, пытаясь выровнять чекбокс по центру. Причём здесь даже не важно, является ли отрисовываемая ячейка чекбоксом, всё будет работать правильно в любом случае. Ну вот с отрисовкой и всё, букв много, но на самом деле всё просто, всю работу выполняют три последних фрагмента кода (переопределённые paint, drawCheck и drawDisplay). Редактирование Если мы оставим всё как есть, то состояние чекбокса будет меняться при клике не в то место, где мы его отрисовали теперь (по центру), а в то, где Qt думает, что он до сих пор находится (слева). Обработку пользовательского ввода Qt осуществляет в функции editorEvent, которую можно (и нужно) переопределить. К сожалению, область, где находится чекбокс, в эту функцию не передаётся, поэтому нет возможности модифицировать входные параметры и вызвать базовую функцию. Нам ничего не остаётся, кроме как скопипастить код библиотеки, закомментировать строки, где определяется положение чекбокса и вставить туда свои. Получается так: Код: bool ItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { Теперь мы можем безопасно устанавливать такой делегат на всю таблицу и наслаждаться выровненными по центру чекбоксами. Ну, по крайней мере у меня всё работает как часики :) Название: Re: Выравнивание виджета в ячейке таблицы Отправлено: blood_shadow от Март 30, 2011, 15:30 По поводу выравнивания чекбоксов есть вариант решения в факе (http://developer.qt.nokia.com/faq/answer/how_can_i_align_the_checkboxes_in_a_view), но он кривоватый (попробуйте - увидите сами), поэтому хочу предложить свой, модифицированный сам долго долбался решение по проще, может кому-то пригодится:Код
QStyle::PM_IndicatorWidth это ширина в пикселях нашего чекбокса(без текста), который нужно перевести с пикселей с помощью pixelMetric() результат - идеальное выравнивание даже при растяжении |