Как поменять stylesheet у одной ячейки qt
Перейти к содержимому

Как поменять stylesheet у одной ячейки qt

  • автор:

Создаем стиль интерфейса Qt на примере таблицы

Как известно, Qt предлагает разработчикам практически неограниченные возможности для создания интерфейсов. В большинстве случаев, если вы используйте стандартные виджеты, внешний вид вашего приложения (и элементов его интерфейса) будет соответствовать внешнему виду вашей операционной системы. Для этого в Qt есть система так называемых стилей — классов, ответственных за отрисовку стандартных элементов интерфейса. В этой статье мы попробуем создать свой стиль и применить его к простейшему приложению для того, чтобы получить красивую таблицу на основе виджета QTableWidget.

Теоретическая часть

Итак, начнем с теории. В Qt существует абстрактный класс QStyle, ответственный, как не сложно догадаться, за стилизацию приложения. От него унаследовано некоторое количество классов (QWindowStyle, QMacStyle и т.д.), которые представляют собой стили, эмулирующие стандартный внешний вид операционной системы. Мы будем делать свой стиль для приложения по их образу и подобию. Qt требует, чтобы пользовательские стили были унаследованы не напрямую от QStyle, а от одного из его классов-наследников. Документация рекомендует выбрать наиболее близкий к желаемому системный стиль, и изменить его «под себя». Мы же будем наследовать наш класс от не менее абстрактного, чем QStyle, класса QCommonStyle.

Как же происходит рисование элементов внутри стиля? Класс QStyle имеет набор функций, названия которых начинаются со слова draw:

  • drawComplexControl()
  • drawControl()
  • drawItemPixmap()
  • drawItemText()
  • drawPrimitive()

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

drawComplexControl() используется для рисования составных виджетов, то есть таких, которые содержат в самих себе несколько других виджетов.
В качестве примера можно привести QSpinBox, который, как несложно догадаться, реализует обычный SpinBox и состоит из поля ввода и двух маленьких кнопок:

drawControl() рисует стандартные виджеты вроде кнопок и полей ввода.

drawPrimitive() рисует так называемые примитивные элементы, например, рамки.

drawItemPixmap() и drawItemText() имеют вполне говорящие названия и делают именно то, что вы могли бы от них ожидать. Детальные описание всех функций, а также их аргументов, можно очень легко найти в документации Qt, поэтому я на этом останавливаться не буду.

В нашем примере, мы будем делать стиль для элемента QTableWidget, который представляет собой обыкновенную таблицу. Стили для остальных элементов делаются абсолютно аналогично.

Начинаем

Первым делом, создадим новый класс С++. При создании класса, Qt услужливо предлагает нам написать его название, а так же название класса, от которого мы хотим наследовать. Назовем его для простоты myStyle, и укажем наследование от QCommonStyle. После этого, Qt создаст нам пару файлов (.h и .cpp), в которых, для начала, мы хотим получить примерно такую заготовку:

myStyle.h

#include class myStyle : public QCommonStyle < Q_OBJECT public: explicit myStyle(); signals: public slots: >; 

myStyle.cpp

#include "mystyle.h" myStyle::myStyle() : QCommonStyle()

Наша функция main() будет выглядеть следующим образом:

int main(int argc, char *argv[])

Как видите, все что мы делаем — это устанавливаем наш стиль, создаем виджет и отображаем его. На данном этапе у нас есть только пустой стиль, унаследованный от QCommonStyle, поэтому наша таблица будет выглядеть… ну, скажем, не очень привлекательно:

Рассмотрим подробнее из чего состоит таблица.

Структура, в общем, довольно простая и понятная. Стоит разве что остановиться на секунду на заголовках. В Qt разделяют два вида заголовков: горизонтальный (тот, который сверху), и вертикальный (тот, который слева). Под «Областью заголовка» я подразумеваю всю область, на которой впоследствии будет отображен заголовок. Секция — это каждая конкретная ячейка заголовка. Незанятая область — это та часть заголовка, на которой секций нет (это случается, когда суммарный размер всех секций меньше размера таблицы).

Итак, вооружившись этими знаниями, можно стилизовать каждый элемент. Начнем с добавления в наш класс функций

void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const; void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const; void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const; 

Начнем с функции drawControl(). Добавим в реализацию код:

switch(element)

Ключевой атрибут этой функции — это element, который указывает на тип того, что мы будем рисовать. Внутри switch‘a мы будем добавлять по case‘у для каждого из тех элементов, которые мы будем рисовать сами. Все остальные будут обрабатываться в default-секции с помощью аналогичной функции родительского класса.

Начнем с рамки, которая окружает нашу таблицу целиком. Я буду делать градиентную рамку. Верхняя и нижняя границы будут белыми, а вертикальные границы будут нарисованы градиентом: они будут белыми по краям и светло-серыми в середине.

Для этого добавим в функцию drawControl() следующий код:

case CE_ShapedFrame: < //создаем градиент QLinearGradient gradient(0, 0, 0, opt->rect.height()); gradient.setColorAt(0, QColor(255,255,255)); gradient.setColorAt(0.5, QColor(225,225,225)); gradient.setColorAt(1, QColor(255,255,255)); QPen pen; pen.setBrush( gradient ); p->setPen(pen); //рисуем рамку p->drawRect( 0,0,opt->rect.width()-1, opt->rect.height()-1); > break; 

комментарий

Итак, что же здесь происходит. Сначала мы создаем линейный градиент, направленный сверху вниз. Затем мы задаем цвета для ключевых точек, которых у нас три: начало, конец и середина. Как я уже говорил, начало и конец мы делаем белыми, а середину чуть сероватой.

После этого мы создаем перо и устанавливаем в него наш градиент. Перо в Qt рисует с помощью кисти (QBrush), в роли которой будет выступать градиент. Наконец, функцией drawRect() мы рисуем нашу рамку.

Теперь приступим к заголовкам. Саму область заголовка (CE_Header) нам обрабатывать не нужно. Мы займемся секциями и пустой областью. С пустой областью все очень просто, мы закрасим ее однотонным серым цветом:

case CE_HeaderEmptyArea: p->fillRect( opt->rect, QBrush( QColor( 233, 233, 233 ) ) ); break; 

С секциями же придется несколько сложнее. Как мы знаем, если на заголовок таблицы нажать, то выделится либо вся строка, либо весь столбец (в зависимости от того, куда мы нажали). При этом заголовок поменяет свой внешний вид, чтобы пользователь видел изменение его состояния. Обычно заголовок либо «вдавливается», либо подкрашивается. Мы хотим сохранить эту функциональность. Более того, хотелось бы, чтобы при выделении ячейки или ячеек, соответствующие заголовки также окрашивались.

Итак, добавим следующий код:

case CE_HeaderSection: < //Активная секция if( opt->state & State_Sunken || opt->state & State_On ) < //Закрашиваем секцию оранжевым цветом p->fillRect(opt->rect, QBrush( QColor(255,170,80) )); p->setPen( QPen( QColor( 170,170,170) ) ); //и обрисовываем рамкой p->drawRect(opt->rect.x(), opt->rect.y(),opt->rect.width()-1,opt->rect.height()-1); > else//неактивная секция < //Создаем градиент для фона QLinearGradient gradient(0, 0, 0, opt->rect.height()); gradient.setSpread(QGradient::PadSpread); gradient.setColorAt(0, QColor(255,255,255)); gradient.setColorAt(1, QColor(220,220,220)); //рисуем фон p->fillRect(opt->rect, QBrush( gradient )); //создаем градиент для границ секций gradient.setColorAt(0, QColor(230,230,230)); gradient.setColorAt(0.5, QColor(175,175,175)); gradient.setColorAt(1, QColor(230,230,230)); QPen pen; pen.setStyle(Qt::SolidLine); pen.setBrush(gradient); p->setPen(pen); //рисуем границы секций p->drawLine( opt->rect.width() + opt->rect.x() - 1, opt->rect.y() + 3, opt->rect.width() + opt->rect.x() - 1, opt->rect.height() + opt->rect.y() - 3 ); > > 

комментарий

Итак, секция может быть в двух состояниях: активном и неактивном. Для того, чтобы определить это, мы проверяем ее флаги. Флаг State_Sunken показывает, что секция нажата, а флаг State_On показывает, что выбрана ячейка, принадлежащая столбцу (или строке) этой секции. Если хотя бы один из них установлен, мы закрашиваем секцию ровным оранжевым цветом, а также рисуем для нее целиковую границу для того, чтобы оранжевая секция не смотрелась грубо на фоне других (не выделенных) светло-серых частей заголовка.

Если секция неактивна, мы закрашиваем ее градиентом от белого до светло-серого цвета и рисуем границу. Я решил рисовать только вертикальные границы секций, поэтому все что мне нужно — это изобразить вертикальную полоску справа от каждой секции. Чтобы полоски не смотрелись грубо, мы нарисуем их градиентом почти так же, как и рамку всей таблицы: концы полосок будут более светлыми, а середина — более темной. Для этого мы перенастраиваем градиент и устанавливаем его в перо, которым будет рисоваться полоса.

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

За отрисовку ячеек отвечает атрибут CE_ItemViewItem. Добавим в него следующий код:

case CE_ItemViewItem: < //Вызываем отрисовку приметива, который отвечает за подсветку выделенных ячеек drawPrimitive(PE_PanelItemViewItem, opt, p, w); //Преобразовываем опции из указателя на базовый класс //в указатель на тот класс, которым они на самом деле являются. const QStyleOptionViewItemV4 * option = qstyleoption_cast(opt); if( !option ) < //Если по каким-то причинам не получилось преобразовать, рисуем элемент по умолчанию QCommonStyle::drawControl(element, opt, p, w); return; >//Рисуем фокусную рамку в виде обычной серой рамки. if (option->state & QStyle::State_HasFocus) < QPen pen(QColor( 170,170,170 )); p->save(); p->setPen(pen); p->drawRect(opt->rect.x(), opt->rect.y(), opt->rect.width()-1, opt->rect.height()-1); p->restore(); > //Получаем размер области, на которой будет отображаться текст QRect textRect = subElementRect(SE_ItemViewItemText, option, w); //Сдвигаем немного, чтобы текст не "прилипал" к краям ячейки textRect.setX( textRect.x() + 5 ); textRect.setY( textRect.y() + 5 ); if( !option->text.isEmpty() ) < //Рисуем текст. p->drawText(textRect, option->text); > > 

комментарий

Здесь нам пришлось сделать гораздо больше. Во-первых, за раскраску выделенных ячеек другим цветом отвечает элемент PE_PanelItemViewItem, который рисуется в функции drawPrimitive(). Поэтому мы должны вызвать эту функцию, передав туда имеющиеся у нас параметры. После этого мы преобразовываем указатель на опции с базового класса QStyleOption в нужный нам класс QStyleOptionViewItemV4. Это нужно, помимо прочего, для получения текста и области рисования этого текста.

Если ячейка, которую мы рисуем, является выделенной

if (option->state & QStyle::State_HasFocus)

то мы рисуем небольшую серую рамку вокруг всей ячейки.

После этого мы получаем размер области, на которой должен бын выведен текст, и делаем небольшой отступ, чтобы текст не появился вплотную к левому верхнему краю. Наконец, мы рисуем текст функцией drawText().

Поскольку при обработки ячеек мы вызываем функцию drawPrimitive для элемента PE_PanelItemViewItem, реализуем отрисовку этого элмента, чтобы выделенные ячейки раскрашивались в какой-нибудь более приятный цвет.

По аналогии с drawControl(), добавим в drawPrimitive() точно такой же switch, и сразу реализуем нужную нам подсветку ячеек:

switch( pe ) < case PE_PanelItemViewItem: //Просто преобразовываем указатель, и если ячейка выделена, закрашиваем ее серым. if (const QStyleOptionViewItemV4 *option = qstyleoption_cast(opt)) if (option->state & QStyle::State_Selected) < p->fillRect(option->rect, QBrush( QColor( 220,220,220,100 ))); > break; default: QCommonStyle::drawPrimitive( pe, opt, p, w); break; > 

Наконец, изменим шрифт, которым будет выводиться текст. Добавим в функцию drawItemText() следующий код:

painter->setPen( QPen( QColor( 30, 30, 30 ))); painter->setFont(QFont("Consolas")); painter->drawText(rect, text); 

Итак, мы преобразили невзрачную табличку, и теперь она выглядит так:

что на мой взгляд гораздо лучше того, что было изначально.

Преимущества данного подхода

Конечно, создавать стили для всего приложения таким образом — весьма трудоемкая задача. Стиль для одного элемента (как в этой статье) можно сделать очень быстро, но если вы хотите позаботится о всех виджетах (например если вы хотите распространять свой стиль, чтобы другие люди могли им воспользоваться), это может отнять достаточно много времени. Описание элементов, которые должны быть нарисованы для каждого отдельно взятого виджета, я, к примеру, не нашел, и мне пришлось определять их методом «научного тыка». Однако у стилизации таким образом есть ряд существенных преимуществ.

Во-первых, эти стили применяются ко всем элементам. Если у вас есть 300таблиц, то вам не нужно настраивать каждую вручную, стиль к приложению применяется в одну строку.

Во-вторых, стили, созданные таким образом, удобно менять. Это, пожалуй, лучший способ предоставить пользователю возможность изменить стиль приложения через настройки. К тому же, вы можете быть точно уверены, что созданный вами стиль будет каждый раз выглядеть одинаково.

myStyle.h

#ifndef MYSTYLE_H #define MYSTYLE_H #include #include class myStyle : public QCommonStyle < Q_OBJECT public: explicit myStyle(); void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const; void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const; void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const; signals: public slots: >; #endif // MYSTYLE_H 

myStyle.cpp

#include "mystyle.h" myStyle::myStyle() : QCommonStyle() < >void myStyle::drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const < switch( element ) < case CE_ShapedFrame: < QLinearGradient gradient(0, 0, 0, opt->rect.height()); gradient.setColorAt(0, QColor(255,255,255)); gradient.setColorAt(0.5, QColor(225,225,225)); gradient.setColorAt(1, QColor(255,255,255)); QPen pen; pen.setBrush( gradient ); p->setPen(pen); p->drawRect( 0,0,opt->rect.width()-1, opt->rect.height()-1); > break; case CE_ItemViewItem: < drawPrimitive(PE_PanelItemViewItem, opt, p, w); const QStyleOptionViewItemV4 * option = qstyleoption_cast(opt); if( !option ) < QCommonStyle::drawControl(element, opt, p, w); return; >if (option->state & QStyle::State_HasFocus) < QPen pen(QColor( 170,170,170 )); p->save(); p->setPen(pen); p->drawRect(opt->rect.x(), opt->rect.y(), opt->rect.width()-1, opt->rect.height()-1); p->restore(); > QRect textRect = subElementRect(SE_ItemViewItemText, option, w); textRect.setX( textRect.x() + 5 ); textRect.setY( textRect.y() + 5 ); if( !option->text.isEmpty() ) < p->drawText(textRect, option->text); > > break; case CE_Header: QCommonStyle::drawControl(element, opt, p, w); break; case CE_HeaderEmptyArea: p->fillRect( opt->rect, QBrush( QColor( 233, 233, 233 ) ) ); break; case CE_HeaderSection: < if( opt->state & State_Sunken || opt->state & State_On ) < p->fillRect(opt->rect, QBrush( QColor(255,170,80) )); p->save(); p->setPen( QPen( QColor( 170,170,170) ) ); p->drawRect(opt->rect.x(), opt->rect.y(),opt->rect.width()-1,opt->rect.height()-1); p->restore(); > else < QLinearGradient gradient(0, 0, 0, opt->rect.height()); gradient.setSpread(QGradient::PadSpread); gradient.setColorAt(0, QColor(255,255,255)); gradient.setColorAt(1, QColor(220,220,220)); p->fillRect(opt->rect, QBrush( gradient )); gradient.setColorAt(0, QColor(230,230,230)); gradient.setColorAt(0.5, QColor(175,175,175)); gradient.setColorAt(1, QColor(230,230,230)); QPen pen; pen.setStyle(Qt::SolidLine); pen.setBrush(gradient); p->setPen(pen); p->drawLine( opt->rect.width() + opt->rect.x() - 1, opt->rect.y() + 3, opt->rect.width() + opt->rect.x() - 1, opt->rect.height() + opt->rect.y() - 3 ); > > break; default: QCommonStyle::drawControl(element, opt, p, w); break; > > void myStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const < painter->setPen( QPen( QColor( 30, 30, 30 ))); painter->setFont(QFont("Consolas")); painter->drawText(rect, text); > void myStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const < switch( pe ) < case PE_PanelItemViewItem: if (const QStyleOptionViewItemV4 *option = qstyleoption_cast(opt)) if ((option->state & QStyle::State_Selected)) p->fillRect(option->rect, QBrush( QColor( 220,220,220,100 ))); break; default: QCommonStyle::drawPrimitive( pe, opt, p, w); break; > > 

Как поменять stylesheet у одной ячейки qt

Просмотр профиля

14.10.2009, 14:08

Группа: Новичок
Сообщений: 12
Регистрация: 13.7.2009
Пользователь №: 903

Репутация: 0

Приветствую!
Итак, понадобилось мне изменить цвет фона QTableview при выделении. С этим проблем не возникло:

MyTable->setStyleSheet("QTableView");

Все это стало выглядеть так:
Раскрывающийся текст

Понятно, что цвет инвертированного текста, с этим цветом фона, мягко говоря, не сочетаются. На ум пришло, через все тот же Style Sheet, жестко задать цвет текста в выделенный итемах:

MyTable->setStyleSheet("QTableView");

Как изменить стиль столбца/строки с помощью Qt Style Sheets?

введите сюда описание изображения

1)Подскажите, каким образом можно установить фон для 1 столбца/строки?
Есть ли возможность не создавать QFrame для каждой ячейки столбца/строки? 2)Каким образом можно установить только вертикальные границы столбцов в таблице? UPD: С кодом в общем то проблем нет, так как его нет 🙁 Я не могу найти в документации каким образом с помощью таблицы стилей или каких-либо методов можно реализовать заливку одного столбца/строки и как можно разделить только по вертикали. Таким образом выглядит моя таблица: Для левых двух столбцов создавался QFrame, в правом ничего. Можно заметить небольшие пробелы между ячейками, поэтому заливка QFrame не подходит

def _createtable(self): table = QTableWidget(43,5) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalPolicy(0) sizePolicy.setHeightForWidth(table.sizePolicy().hasHeightForWidth()) table.setSizePolicy(sizePolicy) table.setMinimumSize(QSize(400,0)) table.setMaximumSize(QSize(2000,2000)) table.setSizeIncrement(QSize(0,0)) table.setLayoutDirection(Qt.LeftToRight) table.setFrameShadow(QtWidgets.QFrame.Raised) table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.setShowGrid(False) table.setGridStyle(Qt.SolidLine) table.verticalHeader().setVisible(False) table.setObjectName("Table") table.setHorizontalHeaderLabels([ 'Product','Base output','Base\nconsumption', 'Productivity','Buildings\nRequired' ]) table.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) for row in range(table.rowCount()): gbox = QGridLayout() framebox = QFrame() framebox.setLayout(gbox) table.setCellWidget(row,2,framebox) hbox8 = QHBoxLayout() hbox8.setAlignment(Qt.AlignCenter) framebox2 = QFrame() framebox2.setLayout(hbox8) table.setCellWidget(row,3,framebox2) hbox9 = QHBoxLayout() framebox3 = QFrame() framebox3.setLayout(hbox9) table.setCellWidget(row,0,framebox3) farmer = QLabel() farmer.setPixmap(QPixmap(':Portrait_Farmer').scaled(25,25)) worker = QLabel() worker.setPixmap(QPixmap(':Portrait_Worker').scaled(25,25)) artisan = QLabel() artisan.setPixmap(QPixmap(':Portrait_Artisan').scaled(25,25)) engineer = QLabel() engineer.setPixmap(QPixmap(':Portrait_Engineer').scaled(25,25)) investor = QLabel() investor.setPixmap(QPixmap(':Portrait_Investor').scaled(25,25)) tourist = QLabel() tourist.setPixmap(QPixmap(':Portrait_Tourist').scaled(25,25)) scholar = QLabel() scholar.setPixmap(QPixmap(':Portrait_Scholar').scaled(25,25)) for pics in (farmer,worker,artisan,engineer,investor,tourist,scholar): pics.setStyleSheet("background-color: ") column_pop = column1.pop(0) pb = QPushButton(QIcon(":"+ column_pop),'') pb.setMinimumSize(35,35) pb.setMaximumSize(35,35) pb.setStyleSheet("background-color: brown") hbox9.addWidget(pb) widget = QTableWidgetItem(column2.pop(0)) widget.setTextAlignment(Qt.AlignCenter) table.setItem(row%60,1,widget) a = column3.pop(0) 

А это часть кода для таблицы стилей:

.QFrame < background-color: #664127; border-radius: ; >QTableView < column3-background-color: qlineargradient(x1: 0, y1: 0, x2: 0.5, y2: 0.5, stop: 0 #FF92BB, stop: 1 white); >#Table < background-color: #805130; font-size: 20px; >QHeaderView::section

Как поменять stylesheet у одной ячейки qt

Если таблица пустая, то у нее белый фон.
А можно ли как сделать немный фон там, где нет строк, а где они есть — белый.

Эту возможность я вроде видел у .net компонента таблицы.

Сообщ. #2 , 09.04.12, 11:27
Unregistered

Наследоваться от QTableWidgetItem, переопределить у нее setData.

if( text.isEmpty() )
setBackground(Qt::white);
else
setBackground(Qt::black);
>

Сообщение отредактировано: jobdead — 09.04.12, 11:29
Сообщ. #3 , 09.04.12, 11:33
Full Member
Рейтинг (т): нет

jobdead, не совсем то. Менять нужно Background не у item-a, а у самого QTableWidget.
То есть если строк — 5, то они на белом фоне. А остальная область ниже этих строк — например серая.
А QTableWidgetItem может не быть вообще, если вообще нет строк.

Сообщ. #4 , 09.04.12, 16:01
Unregistered

Задать таблице stylesheet c нужным цветом фона, и «Наследоваться от QTableWidgetItem»
а можно и не наследоваться:

Прикреплённая картинка

Прикреплённая картинка

Сообщ. #5 , 09.04.12, 16:09
Full Member
Рейтинг (т): нет
Adil, спасибо — то, что нужно
Сообщ. #6 , 10.04.12, 06:47
Full Member
Рейтинг (т): нет

Adil, а не знаешь как можно реализовать пустую запись в таблице.
Если ее изменить, то она просит заполнить все поля, а при этом появляется еще одна пустая строка.

Или это нужно руками делать ?

P.S. И еще — хотелось бы для каждого поля задать тип вводимых значений. Например, цело число, строка.

Сообщение отредактировано: gpepsi — 10.04.12, 06:51
Сообщ. #7 , 10.04.12, 06:50
Unregistered
Цитата gpepsi @ 10.04.12, 06:47
Если ее изменить, то она просит заполнить все поля
Сообщ. #8 , 10.04.12, 06:51
Full Member
Рейтинг (т): нет
Цитата _lcf_ @ 10.04.12, 06:50

ну есть 5 столбцов. Начал менять первое. Если не задал все и нажал enter — начинает ругаться.
Сообщ. #9 , 10.04.12, 07:03
Unregistered
Цитата gpepsi @ 10.04.12, 06:51
ну есть 5 столбцов. Начал менять первое. Если не задал все и нажал enter — начинает ругаться.

ничего не понимаю, если честно редактирование ячеек никак не связано друг с другом.
Цитата gpepsi @ 10.04.12, 06:47

P.S. И еще — хотелось бы для каждого поля задать тип вводимых значений. Например, цело число, строка.

всё-таки стоит посмотреть в сторону своей реализации кутейблвиджет ибо ни масок, ни валидаторов ячейкам задать нельзя, да и сортировать можно только текст.

Сообщ. #10 , 10.04.12, 07:04
Full Member
Рейтинг (т): нет
Цитата _lcf_ @ 10.04.12, 07:03
всё-таки стоит посмотреть в сторону своей реализации кутейблвиджет

QTableView ?
Сообщ. #11 , 10.04.12, 07:06
Unregistered

ну или вообще к моделям перейти — qtableview

Добавлено 10.04.12, 07:08

вариантов несколько. либо используй model-based виджеты, либо делай свой класс, наследованный от qtablewidgetitem где и реализуй всё что хошь.

Добавлено 10.04.12, 07:09

Цитата gpepsi @ 10.04.12, 07:04

всё-таки стоит посмотреть в сторону своей реализации кутейблвиджет

да, имелось ввиду кутейблвиджетИТЕМ, очепятался
Сообщ. #12 , 10.04.12, 11:53
Full Member
Рейтинг (т): нет
Цитата _lcf_ @ 10.04.12, 07:06
ну или вообще к моделям перейти — qtableview

попробовал реализовать модель. Засунул ее в QTableView.
Вроде таблица строится.

Но никак не могу понять как приляпить контекстное меню, которое показвалось бы при щелчке правой кнопкой мыши на QTableView.
Или и от него еще наследоваться и садиться на mouseReleaseEvent ? Что-то много руками приходится делать.

Сообщ. #13 , 10.04.12, 12:18
Unregistered
да нет. есть сигнал customContextMenuRequested, не забудь про setContextMenuPolicy
Сообщ. #14 , 11.04.12, 11:05
Full Member
Рейтинг (т): нет
Цитата _lcf_ @ 10.04.12, 12:18
да нет. есть сигнал customContextMenuRequested, не забудь про setContextMenuPolicy

_lcf_, спасибо — вроде заработало.

Нужно отлавливать выделение строки в таблице. Причем если выделение снимается (например при reset модели), то это тоже нужно отлавливать.
Иде я том, что структура данных иерархическая. И если в одной таблице выделить строку, то в другой нужно отобразить данные нижнего уровня для выделенной записи.
Первый уровень лежит с первой таблице (вернее все данные), а второй — во второй таблице.

Я что-то ник не соображу где и как это сделать. В самой модели (QAbstractListModel) нет возможности отследить выделение.
А в QTableView сигнал currentChange закрытый.

Как тогда правильно отловить выделение и передать данные во вторую таблицу для отрисовки ?

P.S. Да и вообще хотелось бы понять как это правильно делать. То есть где хранить сами данные (в модели или нет), как их передать в модель.

Сообщ. #15 , 11.04.12, 11:31
Unregistered
Цитата gpepsi @ 11.04.12, 11:05

Нужно отлавливать выделение строки в таблице. Причем если выделение снимается (например при reset модели), то это тоже нужно отлавливать.

копайте сигналы от QAbstractItemView. В качестве извращУнства могу предложить mousemovevent и иже с ним

Цитата gpepsi @ 11.04.12, 11:05
То есть где хранить сами данные (в модели или нет), как их передать в модель.

ну вообще данные хранятся в модели, а на вьюшке отображаются. синхронизация между изменениями регулируется всякими едитстратегиями и субмитами. например, у мускульной модели есть — QSqlTableModel::setEditStrategy

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *