C++ QT6 Получение переменной из обьекта кастомного класса в dropEvent
Имеется столбец кнопок в QGridlayout row n, column 0. Кнопки - обьекты кастомного класса ButtonDrag, наследника QPushbutton. В классе есть некая переменная int row, в которую сохраняется значение номера строки из QGridLayout. Надо переопределить dropEvent окна так, чтобы при срабатывании считывалась значение переменной row из ButtonDrag для дальнейшего использования (в качестве индекса в векторе)
Есть вот такой код на питоне. Он прекрасно работает:
def dropEvent(self, e):
pos = e.position()
target = e.source()
for d in range(len(self.cat_btn_ls)): # Список всех кнопок созданных в цикле.
if pos.y() in range(self.cat_btn_ls[d].y(),
self.cat_btn_ls[d].y() + 30): # Высота кнопки 30px
targ_str = self.file.categories[target.row] # Список порядок которого надо изменить в соответствии с новым порядком кнопок после перетаскивания
self.file.categories.pop(target.row)
self.file.categories.insert(d, targ_str)
break
self.write_categories()
self.reload_categories()
e.accept()
Потому как питону не надо указывать к какому классу будет принадлежать обьект захваченный ивентом... Как сделать тоже самое на плюсах?
void BoxCategories::dropEvent(QDropEvent *e){
auto pos = e->position();
auto target = e->source();
for (auto d=0; d<cat_btn_ls.size(); d++){
if (cat_btn_ls[d]->y() < pos.y() < cat_btn_ls[d]->y() - 30){
auto targ_str = file.categories[target->row];
file.categories.erase(std::next(file.categories.begin(), target->row));
break;
}
}
write_categories();
reload_categories();
e->accept();
}
По очевидным причинам тут это не работает, т.к e->source() это QObject у которого нет переменной row... (Да, если на питоне теперь захватить обьект в котором нет этой переменной то будет краш) Но уменя нет в этом окне других обьектов, к тому же можно сделать if else на наличие переменной)
Ответы (1 шт):
Питон вроде как использует метаданные объекта. Что придется явно использовать в С++. Каждый QObject сдержит в себе QMetaObject, который хранит информацию о классе и имени объекта.
Кроме того, если заранее известен тип объекта и ваш проект поддерживает RTTI, можно обойтись банальным кастом dynamic_cast. В Qt предусмотрена функция qobject_cast не зависящая от RTTI:
auto *button = qobject_cast<ButtonDrag*>(e->source()); // вернет nullptr если тип не совпадает
if(button) {
// свершить деяние
}
qobject_cast также возвращает nullptr если класс был описан без публичного мета-интерфейса ( без макроса Q_OBJECT), что исключает возможную проблему в том случае если такой случайно или намеренно был опущен, а мы использовали (dynamic\static)_cast.
Если "деяние" - вызов слота в классе ButtonDrag, можно обойтись и без каста, а использовать QMetaMethod::invoke, вопрос в производительности. Но тогда тип вообще не важен, будет работать для всех типов с одноимённым и однотипным слотом.