Qt. Как использовать сигналы-слоты?

Вот что получилось:
Теперь нужно сам алгоритм писать. Но как слоты-сигналы реализовать? Я понял, что через connect, но как не доходит.
Сделать бесконечный цикл? Как я понял, нужно при нажатии кнопки «ВЫЧИСЛИТЬ», подать сигнал в 3 слота: в 2 ComboBox’а и в редактируемый LineEdit. Тогда я получу строку из LineEdit, переведу ее в число, и потом if-else-if’ами вычислю и во второй LineEdit выведу после преобразования в строку.
- Вопрос задан более трёх лет назад
- 1706 просмотров
Комментировать
Решения вопроса 2
Программист на «си с крестами» и не только
Нет, мы заводим где-то новый слот и подаём сигнал в него.
Есть два способа завести новый слот: либо унаследоваться от QObject или его наследника (удобно унаследовать главную форму), либо воспользоваться лямбда-функцией C++11. Поскольку все наши формы на стеке, проще всего написать лямбду.
connect(&Button, &QPushButton::clicked, &Base, [&]() < // тут код >);
В реальных проектах каждая форма является наследником от QWidget (или чего-то подобного) и хранит свои компоненты. А слоты — это функции в форме.
Ответ написан более трёх лет назад
Нравится 1 7 комментариев

megorit @EgoRusMarch Автор вопроса
Делать производные классы я пока не готов, у меня мозги перегреются)
Можно ведь базовыми сигналами-слотами обойтись:
От QComboBox нужны currentIndex и activated
От QLineEdit нужны text и setText
От QPushButon нужен pressed
От QString нужны setNum и toDouble
Только как сделать не могу разобраться:
* нужно ли для этого делать цикл бесконечный
* как соединить эти элементы сигналами-слотами
Цикл бесконечный делать не надо. Он уже есть где-то в коде QApplication.
Вот перед нами один слот, который и будет выполнять нашу задачу.
Штатными не обойдёшься — ибо это не просто соединить проводом нажатие OK и QDialog::accept(), а собственная логика.
QLineEdit with Custom QComboBox
Hi guys i am pretty new to Qt and now trying to make a simple dictionary application and i wanted to customize the QLineEdit with QComboBox inside like u get a search box with magnifier icon and down arrow right next to it and u can choose from the options right inside the QLineEdit. The idea seems easy to realize as i inherited QLineEdit and used a new QComboBox inside and i managed to get QComboBox inside the QLine edit with magnifier or any icons but the problem is the down arrow of QComboBox cant be set closer to the icons like almost overlaps little bit from left small down arrow i tries different styleSheet stuffs but still the distance between down arrow and the icon is not changed. Any suggestions will be appreciated..
goetz отредактировано
I don’t know exactly what you want, but could a editable QComboBox be a solution for you? Another guess might be to use the input widget in the locator of Qt Creator. I don’t know if it is available as a more or less standalone widget.
mohsen отредактировано
@Volker: I guess he needs an autofill textbox. you could use same combobox and make it appear like textbox using style http://developer.qt.nokia.com/forums/viewthread/3150 then you can design a combo box with your theme by placing a button to expand combo box where ever you want.
bahonurn отредактировано
thanks for the replies but the thing is i want like a input box with icon and down arrow before the input itself where one can click the arrow next to the icon and choose different options to search like hmm english or other alternative languages
giesbert отредактировано
Can you show us a picture, of what you want to achieve? that would make it clearer.
Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)
bahonurn отредактировано
Here i am attaching the link where it shows a simple iTunes search box. As u see it has magnifier glass with drop down options to search. So that is almost what i want to do if that is realizable in Qt. Thanks Guys :)!http://lifehacker.com/246006/add-search-keyboard-shortcut-to-itunes-on-your-mac()!
goetz отредактировано
This is what Qt Creator uses in its locator on the bottom. Maybe it’s not too hard to extract it from its sources.
Использую две модели, как заполнить QComboBox одной моделью
У меня две модели, Users (Имя, Фамилия, Страна) и Countries(Наименование). Я сделал делегат для комбобокса в поле Страна таблицы Пользователи. Как мне его заполнить данными из таблицы Страны? Country.cpp
#include "Country.h" Country::Country() < >void Country::setName(const QString name) < m_name = name; >QString Country::getName() const
CountryTable.cpp
#include "CountryTable.h" CountryTable::CountryTable(QObject *parent) : QAbstractTableModel (parent) < listOfCountries = new QList (); > int CountryTable::columnCount(const QModelIndex & parent) const < return 1; >int CountryTable::rowCount(const QModelIndex & parent) const < return listOfCountries->size(); > QVariant CountryTable::data(const QModelIndex & index, int role) const < if (index.isValid() && role == Qt ::DisplayRole) return getData(index.row(), index.column()); return QVariant (); >QVariant CountryTable::getData(int num, int position) const < switch (position) < case 0: return QVariant (listOfCountries->at(num).getName()); default: return QVariant (); > > bool CountryTable::setData(const QModelIndex &index, const QVariant &value, int role) < if (!index.isValid()) < return false; >Country &country = this->getCountry(index); switch (index.column()) < case 0: country.setName(value.toString()); break; default: return false; >emit dataChanged(index, index); return true; > QVariant CountryTable::headerData(int section, Qt ::Orientation orientation, int role) const < if (role != Qt ::DisplayRole) return QVariant (); if (orientation == Qt ::Vertical) return QVariant (section + 1); else switch (section) < case 0: return QVariant ("Name"); default: return QVariant (); >> Qt ::ItemFlags CountryTable::flags(const QModelIndex & index) const < return Qt ::ItemIsSelectable | Qt ::ItemIsEnabled | Qt ::ItemIsEditable; >Country& CountryTable::getCountry(const QModelIndex & index) const < return (*listOfCountries)[index.row()]; >void CountryTable::addCountry(Country& newCountry) < beginInsertRows(QModelIndex (), listOfCountries->size(), listOfCountries->size()); listOfCountries->append(newCountry); endInsertRows(); > void CountryTable::delCountry(const QModelIndex &index) < beginRemoveRows(QModelIndex (), index.row(), index.row()); listOfCountries->removeAt(index.row()); endRemoveRows(); >
#include "User.h" QVector User::usersList; User::User() < usersList.push_back(this); >User::~User() < >void User::setName(const QString name) < m_name = name; >void User::setSurname(const QString surname) < m_surname = surname; >void User::setCountry(const QString country) < m_country = country; >QString User::getName() const < return m_name; >QString User::getSurname() const < return m_surname; >QString User::getCountry() const < return m_country; >QVector User::getAllUsers()
UsersTable.cpp
#include "UsersTable.h" #include UsersTable::UsersTable(QObject *parent) : QAbstractTableModel (parent) < listOfUsers = new QList (); > int UsersTable::columnCount(const QModelIndex & parent) const < return 3; >int UsersTable::rowCount(const QModelIndex & parent) const < return listOfUsers->size(); > QVariant UsersTable::data(const QModelIndex & index, int role) const < if (index.isValid() && role == Qt ::DisplayRole) return getData(index.row(), index.column()); return QVariant (); >QVariant UsersTable::getData(int num, int position) const < switch (position) < case 0: return QVariant (listOfUsers->at(num).getName()); case 1: return QVariant (listOfUsers->at(num).getSurname()); case 2: return QVariant (listOfUsers->at(num).getCountry()); default: return QVariant (); > > bool UsersTable::setData(const QModelIndex &index, const QVariant &value, int role) < if (!index.isValid()) < return false; >User &user = this->getUser(index); switch (index.column()) < case 0: user.setName(value.toString()); break; case 1: user.setSurname(value.toString()); break; case 2: user.setCountry(value.toString()); break; default: return false; >emit dataChanged(index, index); return true; > QVariant UsersTable::headerData(int section, Qt ::Orientation orientation, int role) const < if (role != Qt ::DisplayRole) return QVariant (); if (orientation == Qt ::Vertical) return QVariant (section + 1); else switch (section) < case 0: return QVariant ("Name"); case 1: return QVariant ("Surname"); case 2: return QVariant ("Country"); default: return QVariant (); >> Qt ::ItemFlags UsersTable::flags(const QModelIndex & index) const < return Qt ::ItemIsSelectable | Qt ::ItemIsEnabled | Qt ::ItemIsEditable; >User& UsersTable::getUser(const QModelIndex & index) const < return (*listOfUsers)[index.row()]; >void UsersTable::addUser(User& newUser) < beginInsertRows(QModelIndex (), listOfUsers->size(), listOfUsers->size()); listOfUsers->append(newUser); endInsertRows(); > void UsersTable::delUser(const QModelIndex & index) < beginRemoveRows(QModelIndex (), index.row(), index.row()); listOfUsers->removeAt(index.row()); endRemoveRows(); >
DelegateComboBox.cpp
#include "DelegateComboBox.h" #include #include #include DelegateComboBox::DelegateComboBox(const QStringList &country, QObject *parent) :QStyledItemDelegate(parent), countryList(country) < >QWidget* DelegateComboBox::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const < QComboBox *comboBox = new QComboBox(parent); comboBox->addItems(countryList); comboBox->setCurrentIndex(-1); return comboBox; > void DelegateComboBox::setEditorData(QWidget *editor, const QModelIndex &index) const < QString text = index.model()->data(index, Qt::EditRole).toString(); QComboBox *comboBox = static_cast(editor); if(text.isEmpty())< QLineEdit *edit=new QLineEdit; QFont font=edit->font(); font.setBold(true); font.setItalic(true); edit->setFont(font); edit->setPlaceholderText("Select country"); comboBox->setLineEdit(edit); comboBox->lineEdit()->setReadOnly(true); return; > int idx=comboBox->findText(text); comboBox->setCurrentIndex(idx); > void DelegateComboBox::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const < QComboBox *comboBox = static_cast(editor); QString text = comboBox->currentText(); model->setData(index, text, Qt::EditRole); > void DelegateComboBox::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const < editor->setGeometry(option.rect); >
MainWindow.cpp
dataTable = new UsersTable(this); view = new QTableView (this); view->setModel(dataTable); view->resizeColumnsToContents(); add = new QPushButton ("Add new User"); del = new QPushButton ("Delete selected User"); showQDebug = new QPushButton ("Show"); QWidget *box = new QWidget (); QVBoxLayout *layout = new QVBoxLayout (); layout->addWidget(view); QHBoxLayout *buttonLayout = new QHBoxLayout (); layout->addLayout(buttonLayout); buttonLayout->addWidget(add); buttonLayout->addWidget(del); buttonLayout->addWidget(showQDebug); box->setLayout(layout); setCentralWidget(box); setWindowTitle("Table of Users"); QStringList country; countrysetItemDelegateForColumn(2, delegate); connect(add, SIGNAL(clicked()), this, SLOT(addButtonClicked())); connect(del, SIGNAL(clicked()), this, SLOT(delButtonClicked())); connect(showQDebug, SIGNAL(clicked()), this, SLOT(showUsersData()));
Как видно, в файле MainWindow, сейчас я просто записываю данные в ручную в QStringList. Подскажите, как взять данные из модели Country?
Как связать qcombobox с qlineedit
Здорово работать с QTableView при помощи делегатов, но вот такая незадача, например, я могу установить делегат для столбца или строки таблицы, а как присвить его конкретному индексу.
В MS Access это делается очень легко и непринужденно, а здесь я так понял можно только через setIndexWidget и созданный Widget подцеплять к четырем слотам, вместо простоейшего использования ItemDelegate.
В справке нашел:
Note: If a delegate has been assigned to both a row and a column, the row delegate (i.e., this delegate) will take presedence and manage the intersecting cell index.
т.е. как бы если назначить делегат для строки и столбца, будет работать в ячейки пересечения, но почему то он работает и по гориз и по верт.
Спасибо заранее за помощь !
P.S.
Any existing row delegate for row will be removed, but not deleted. QAbstractItemView does not take ownership of delegate.
т.е. опять memory leaks ?
igor_bogomolov
21.1.2011, 8:53
Цитата(JuryS1806 @ 21.1.2011, 2:09)
Note: If a delegate has been assigned to both a row and a column, the row delegate (i.e., this delegate) will take presedence and manage the intersecting cell index.
Тут опечатка в документации. Должно быть pre c edence. Т.е. если делегат был назначен как для строки так и для колонки, то приоритет будет иметь делегат строки, который будет управлять пересекающейся ячейкой.
Для конкретной ячейки делегат установить нельзя. У меня на такой случай есть «обобщенный делегат». Т.е. делегат который имеет множество представлений по редактированию. Я в Qt::UserRole выставляю тип делегата, и зависимости от этого типа, делегат ведет себя по разному, тем самым имитируя «делегат для яцейки»
21.1.2011, 23:44
Спасибо за ответ. Я вот вчера к утру додумал к следующему:
нужно создавать делегат для конкретного колумна, например:
IntDelegate *IntVal = new IntDelegate(5);
и переписываю createEditor
if (index.column() == 5)
//создаю нужный делегат
>
else
//стандартный делегат
>
//также переписываю все остальные свойства делегата
я так понимаю, стандартным является QLineEdit.
Вообще, если честно я собрал для себя коллекцию разных делегатов, искал через инет, изобретал и как результат, имею все элементы управления MS Access 2007, календарики, чекбоксы, выпадающие таблицы, списки и т.д. и т.п.
И теперь работать одно удовольствие со своей моделью и делегатами!
Qt очень крутая система!
igor_bogomolov
22.1.2011, 0:10
Можно конечно и так, каждый сам для себя решает, вот только это не универсально, т.к. к другой таблице ты этот делегат не применишь.
А вот если ты сделаешь примерно так
QWidget *StdDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &,
const QModelIndex & index) const
QWidget *editor = 0;
typeeditor = index.data(Qt::UserRole).toInt();
switch(typeeditor)
case K095::TQComboBox:
QComboBox *cmbox = new QComboBox(parent);
editor = cmbox;
break;
>
case K095::TQSpinBox:
QSpinBox *spbox = new QSpinBox(parent);
editor = spbox;
break;
>
.
default:
QLineEdit *ledit = new QLineEdit(parent);
editor = ledit;
>
>
return editor;
>
получишь делигат применимый к любой таблице, всё что надо будет сделать, проинициализировать UserRole
22.1.2011, 0:11
Нет, тоже не вариант. Если до этого какой-нибудь ячейке был назначен делегат, он перепишется новым.
Игорь, я так понял что нужно создать универсальный делегат для строки со всеми необходимыми вариантами.
Это очень много кода. А может быть все таки более простые и красивые решения ?
Прикрепил скриншот того что хочу воспроизвести, т.е. в каждой строки таблицы в зависимости от выбранного типа (столбец «Тип») меняются делегаты для «Умолч»,»Мин»,»Макс».
Спасибо за любое участие в решении проблемы
igor_bogomolov
22.1.2011, 0:22
Цитата(JuryS1806 @ 22.1.2011, 0:11)
Нет, тоже не вариант. Если до этого какой-нибудь ячейке был назначен делегат, он перепишется новым.
Это ограничение легко обходится. Не нужно относиться к коду так буквально, я всего лишь хотел продемонстрировать идею.
Цитата(JuryS1806 @ 22.1.2011, 0:11)
я так понял что нужно создать универсальный делегат для строки со всеми необходимыми вариантами.
Как ты его будешь использовать, это не важно. Хочешь для строки выставляй, хочешь для столбца, да хоть для всей таблици целиком. Способ редактирования будет такой как ты укажешь в UserRole. Главное не забывать его задавать для каждой ячейки.
Цитата(JuryS1806 @ 22.1.2011, 0:11)
Это очень много кода. А может быть все таки более простые и красивые решения ?
Да, что поделаешь, кода действительно чуть больше чем для обычного делегата. Зависит от того, сколько способов для редактирования ты хочешь иметь. Другого способа задавать делегаты для отдельной ячейки я не знаю.
22.1.2011, 0:29
И на том спасибо. Просто боюсь костыли приделывать в своей программе. Сейчас покопаю QAbstractItemView исходники, может унаследоваться от него или Qt пересоберу с изменениями какими. Уж больно не нравится мне использовать Qt::UserRole.
Ведь все равно при использовании setItemDelegateForColumn(), setItemDelegateForRow() назначаются на самом деле делегаты для конкретных ячеек, просто это сокращенное решение от тролей, такая юзерфильная хрень
igor_bogomolov
22.1.2011, 0:36
Цитата(JuryS1806 @ 22.1.2011, 0:29)
Просто боюсь костыли приделывать в своей программе.
Лично я это костылем не считаю. На мой взгляд — это нормальное, грамотное решение.
Цитата(JuryS1806 @ 22.1.2011, 0:29)
Qt пересоберу с изменениями какими
Вот это еще больший костыль будет, намучаетесь. К тому же эти изменения придётся открыть.
Цитата(JuryS1806 @ 22.1.2011, 0:29)
Сейчас покопаю QAbstractItemView исходники
Ну удачи, если что получится отпишись. Я, правда, в своё время, там решения не углядел (правда и не старался так уж сильно)
22.1.2011, 1:04
Да. это и вправду лучшее решение сейчас. только до меня дошло.
т.е. я могу например сделать следующее:
1. для каждой строки таблицы назначать всегда делегат.
2. далее считывать data(index,Qt::UserRole)
3. если будет 0, тогда QLineEdit
4. если будте 1, тогда IntDelegate
RealDelegate
MoneyDelegate
и т.д.
Я правильно понял мысль, т.е. до меня это так дошло ? И все таки как выглядит дефолтный делегат. Это есть обычный QLineEdit ?
igor_bogomolov
22.1.2011, 1:11
Цитата(JuryS1806 @ 22.1.2011, 1:04)
Я правильно понял мысль
Цитата(JuryS1806 @ 22.1.2011, 1:04)
И все таки как выглядит дефолтный делегат. Это есть обычный QLineEdit
Ну я по крайней мере так делал, см. код выше, в default.
22.1.2011, 1:21
вот и простейший делегат от тролей: QSqlRelationalDelegate
можно назначить делегат не для каждой строки, а для все таблицы.
Только вот когда вызывается CreateEditor?
Каждый раз при вхождении в ячейку?
Соответственно делегат нужно запихнуть в приватную секцию и добавить на него несколько Update’ов.
Вообщем, все делегаты нужно объединить в один и ПОЛОВИНУ ПРОГРАММЫ переписывать заново !
Пойду застрелюсь БЛИН!
igor_bogomolov
22.1.2011, 1:33
Цитата(JuryS1806 @ 22.1.2011, 1:21)
Вообщем, все делегаты нужно объединить в один и ПОЛОВИНУ ПРОГРАММЫ переписывать заново !
Пойду застрелюсь БЛИН!
Не нужно так сгущать краски. Нет там ничего сложного, тем более что отдельные делегаты уже есть. В остальном коде изменений будет самый минимум.
Цитата(JuryS1806 @ 22.1.2011, 1:21)
Только вот когда вызывается CreateEditor?
Это устанавливает void QAbstractItemView:setEditTriggers ( EditTriggers triggers ). Если писали другие делегаты, то должны бы это знать.
Цитата(JuryS1806 @ 22.1.2011, 1:21)
Соответственно делегат нужно запихнуть в приватную секцию и добавить на него несколько Update’ов.
Не понятная какая то фраза. Каких еще update, зачем?
30.1.2011, 17:07
Вообщем, приблизительно сделал так:
Раскрывающийся текст
#ifndef DELEGATE_H
#define DELEGATE_H
#include
//! Универсальный делегат для ввода любых значний в зависимости от UserRole
// 0 - строка ввода
// 1 - чекбокс
// 2 - спинбокс
// 3 - комбобокс
// 4 - ввод денег
// 5 - ввод дробных и целых чисел
// 6 - ввод целых чисел
// 7 - пустрой делегат, нередактируемый
class UniversalDelegate : public QItemDelegate Q_OBJECT
public:
UniversalDelegate(QObject *parent = 0);
QWidget *createEditor(
QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor,
const QModelIndex &index) const;
void setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const;
void updateEditorGeometry(
QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
void setComboValuesForCell(const QModelIndex index,const QList < QPair> aValues);
void setComboValuesForColumn(const int aColumn,const QList < QPair> aValues);
void setColumnDelegate(const int aColumn,const int aDelegate)
void setCellDelegate(const QModelIndex index,const int aDelegate)
QList < QPair> getComboValuesForCell(const QModelIndex index) const;
int getCurrentDelegate(const QModelIndex index) const;
void Clear();
private slots:
void ChangeComboBoxText(int);
private:
QMap > aValuesOfComboForCell;
QMap > aIndexesOfComboForCell;
QMap > aValuesOfComboForColumn;
QMap > aIndexesOfComboForColumn;
QMap aColumnDelegate;
QMap aCellDelegate;
>;
#endif
Раскрывающийся текст
#include "delegate.h"
//! Универсальный делегат для ввода любых значний в зависимости от UserRole
UniversalDelegate::UniversalDelegate(QObject *parent)
: QItemDelegate(parent)
>
QWidget *UniversalDelegate::createEditor(
QWidget *parent,
const QStyleOptionViewItem& /* option */,
const QModelIndex& index) const //Для начала построю делегат для всего столбца
int aCurUserRole;
aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
aCurUserRole = aCellDelegate.value(index,0);
if (aCurUserRole==1) //чекбокс
QCheckBox *editor = new QCheckBox(parent);
connect(editor,SIGNAL(stateChanged(int)),this,SLOT(ChangeComboBoxText(int)));
return editor;
>
if (aCurUserRole==2) //спинбокс
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
>
if (aCurUserRole==3) //комбобокс
QComboBox *editor = new QComboBox(parent);
QList < QPair> aValues;
if (aColumnDelegate.contains(index.column()))
aValues = aValuesOfComboForColumn.value(index.column());
else
aValues = aValuesOfComboForCell.value(index);
QList < QPair>::const_iterator it=aValues.begin();
while (it != aValues.end())
const QPair aPair = *it;
editor->addItem(aPair.second);
++it;
>
return editor;
>
if (aCurUserRole==4) //ввод денег
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
editor->setMinimum(0.00);
editor->setMaximum(999999999);
editor->setDecimals(2);
editor->setSingleStep(0.1);
return editor;
>
if (aCurUserRole==5) //ввод дробных и целых чисел
QLineEdit *editor = new QLineEdit(parent);
return editor;
>
if (aCurUserRole==6) //ввод целых чисел
QLineEdit *editor = new QLineEdit(parent);
return editor;
>
if (aCurUserRole==7) //пустрой делегат, нередактируемый
QLineEdit *editor = new QLineEdit(parent);
editor->setReadOnly(true);
return editor;
>
//строка ввода
QLineEdit *editor = new QLineEdit(parent);
return editor;
>
void UniversalDelegate::setEditorData(
QWidget *editor,
const QModelIndex &index) const
//Для начала построю делегат для всего столбца
int aCurUserRole;
aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
aCurUserRole = aCellDelegate.value(index,0);
if (aCurUserRole==0) //строка ввода
if (index.model()->data(index, Qt::EditRole).isNull()) return;
const QString value = index.model()->data(
index, Qt::EditRole).toString();
QLineEdit *lineEdit = static_cast(editor);
lineEdit->setText(value);
>
if (aCurUserRole==1) //чекбокс
QCheckBox *checkBox = static_cast(editor);
if (index.model()->data(index, Qt::EditRole).toInt()!=1)
checkBox->setChecked(false);
checkBox->setText(QString::fromUtf8("Нет"));
>
else
checkBox->setChecked(true);
checkBox->setText(QString::fromUtf8("Да"));
>
>
if (aCurUserRole==2) //спинбокс
const int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast(editor);
spinBox->setValue(value);
>
if (aCurUserRole==3) //комбобокс
QComboBox *comboBox = static_cast(editor);
const int value = index.model()->data(index, Qt::EditRole).toInt();
QVector aIndexes;
if (aColumnDelegate.contains(index.column()))
aIndexes = aIndexesOfComboForColumn.value(index.column());
else
aIndexes = aIndexesOfComboForCell.value(index);
comboBox->setCurrentIndex(aIndexes.indexOf(value));
>
if (aCurUserRole==4) //ввод денег
const double value = index.model()->data(
index, Qt::EditRole).toDouble();
QDoubleSpinBox *doubleSpinBox = static_cast(editor);
doubleSpinBox->setValue(value);
>
if (aCurUserRole==5) //ввод дробных и целых чисел
if (index.model()->data(index, Qt::EditRole).isNull()) return;
const QString value = index.model()->data(
index, Qt::EditRole).toString();
QLineEdit *lineEdit = static_cast(editor);
lineEdit->setText(value);
>
if (aCurUserRole==6) //ввод целых чисел
if (index.model()->data(index, Qt::EditRole).isNull()) return;
const QString value = index.model()->data(
index, Qt::EditRole).toString();
QLineEdit *lineEdit = static_cast(editor);
lineEdit->setText(value);
>
if (aCurUserRole==7) //пустрой делегат, нередактируемый
return;
>
>
void UniversalDelegate::setModelData(
QWidget *editor,
QAbstractItemModel *model,
const QModelIndex& index) const
//Для начала построю делегат для всего столбца
int aCurUserRole;
aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
aCurUserRole = aCellDelegate.value(index,0);
if (aCurUserRole==0) //строка ввода
QLineEdit *lineEdit = static_cast(editor);
model->setData(index, lineEdit->text());
>
if (aCurUserRole==1) //чекбокс
QCheckBox *checkBox = static_cast(editor);
if (checkBox->isChecked())
model->setData(index, "1");
else
model->setData(index, "0");
>
if (aCurUserRole==2) //спинбокс
QSpinBox *spinBox = static_cast(editor);
spinBox->interpretText();
const int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
>
if (aCurUserRole==3) //комбобокс
QComboBox *comboBox = static_cast(editor);
QVector aIndexes;
if (aColumnDelegate.contains(index.column()))
aIndexes = aIndexesOfComboForColumn.value(index.column());
else
aIndexes = aIndexesOfComboForCell.value(index);
model->setData(index, aIndexes.at(comboBox->currentIndex()), Qt::EditRole);
>
if (aCurUserRole==4) //ввод денег
QDoubleSpinBox *doubleSpinBox = static_cast(editor);
doubleSpinBox->interpretText();
model->setData(index, doubleSpinBox->text());
>
if (aCurUserRole==5) //ввод дробных и целых чисел
QLineEdit *lineEdit = static_cast(editor);
if (lineEdit->text().isEmpty())
model->setData(index, QVariant(QString::null));
return;
>
const QString aValue = QString::number(lineEdit->text().toDouble());
model->setData(index, aValue);
>
if (aCurUserRole==6) //ввод целых чисел
QLineEdit *lineEdit = static_cast(editor);
if (lineEdit->text().isEmpty())
model->setData(index, QVariant(QString::null));
return;
>
const QString aValue = QString::number(lineEdit->text().toInt());
model->setData(index, aValue);
>
if (aCurUserRole==7) //пустрой делегат, нередактируемый
return;
>
>
void UniversalDelegate::updateEditorGeometry(
QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex& /* index */) const editor->setGeometry(option.rect);
>
void UniversalDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
int aCurUserRole;
aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
aCurUserRole = aCellDelegate.value(index,0);
if (aCurUserRole==0 || aCurUserRole==2 || aCurUserRole==4 || aCurUserRole==5 || aCurUserRole==6) //строка ввода
if (option.state & QStyle::State_Editing)
return; //Передаю управление QLineEdit
if (index.data(Qt::EditRole).isNull())
return; //Пустая ячейка
//Прорисовываю текст редактируемой ячейки
const QString aText = index.data(Qt::EditRole).toString();
painter->drawText(
QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
Qt::AlignLeft | Qt::AlignVCenter,
aText
);
>
if (aCurUserRole==1) //чекбокс
if (option.state & QStyle::State_Selected)
return; //Передаю управление QCheckBox
>
QString aText;
if (index.model()->data(index, Qt::EditRole).toInt()!=1)
aText = QString::fromUtf8("Нет");
else
aText = QString::fromUtf8("Да");
painter->drawText(
QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
Qt::AlignLeft | Qt::AlignVCenter,
aText
);
>
if (aCurUserRole==3) //комбобокс
if (option.state & QStyle::State_Editing)
return; //Передаю управление QComboBox
if (index.data(Qt::EditRole).isNull())
return; //Пустая ячейка
QString aText;
const int aIntValue = index.data(Qt::EditRole).toInt();
QList < QPair> aValues;
if (aColumnDelegate.contains(index.column()))
aValues = aValuesOfComboForColumn.value(index.column());
else
aValues = aValuesOfComboForCell.value(index);
QList < QPair>::const_iterator it=aValues.begin();
while (it != aValues.end())
const QPair aPair = *it;
if (aPair.first == aIntValue)
aText = aPair.second;
break;
>
++it;
>
painter->drawText(
QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
Qt::AlignLeft | Qt::AlignVCenter,
aText
);
>
if (aCurUserRole==7) //пустрой делегат, нередактируемый
return;
>
>
void UniversalDelegate::setComboValuesForCell(const QModelIndex index,const QList < QPair> aValues)
aValuesOfComboForCell[index] = aValues;
QVector aIndexes;
QList < QPair>::const_iterator it=aValues.begin();
while (it != aValues.end())
const QPair aPair = *it;
aIndexes.append(aPair.first);
++it;
>
aIndexesOfComboForCell[index] = aIndexes;
>
void UniversalDelegate::setComboValuesForColumn(const int aColumn,const QList < QPair> aValues)
aValuesOfComboForColumn[aColumn] = aValues;
QVector aIndexes;
QList < QPair>::const_iterator it=aValues.begin();
while (it != aValues.end())
const QPair aPair = *it;
aIndexes.append(aPair.first);
++it;
>
aIndexesOfComboForColumn[aColumn] = aIndexes;
>
QList < QPair> UniversalDelegate::getComboValuesForCell(const QModelIndex index) const
QList < QPair> aValues;
return aValuesOfComboForCell.value(index,aValues);
>
int UniversalDelegate::getCurrentDelegate(const QModelIndex index) const
return aCellDelegate.value(index,0);
>
void UniversalDelegate::Clear()
aValuesOfComboForCell.clear();
aIndexesOfComboForCell.clear();
aValuesOfComboForColumn.clear();
aIndexesOfComboForColumn.clear();
aCellDelegate.clear();
aColumnDelegate.clear();
>
void UniversalDelegate::ChangeComboBoxText(int aValue)
QCheckBox* aCheckBox = qobject_cast(sender());
if (aValue != 0)
aCheckBox->setText(QString::fromUtf8("Да"));
>
else
aCheckBox->setText(QString::fromUtf8("Нет"));
>
Работает неплохо, при этом можно назначить делегат для ячейки или целого столбца.
Один минус — не могу прорисовать делегат в неактивном состоянии.
Вылетает программа, try . catch не спасает.
Поэтому например при прорисовке чекбокса в неактивном состоянии получаю просто текст Да или Нет, а сам флажок можно установить при редакции ячейки. В целом нормально.