Название: Передача параметра в слот
Отправлено: kemosab от Октябрь 20, 2017, 20:42
Столкнулся с проблемой. У меня есть 50+ объектов типа QFrame, которым я сделал всплывающее меню по правому клику, так вот теперь нужно сделать обработчик нажатия. При нажатии должен меняться цвет у выбранного фрейма. Проблема в том, что все QFrame, а точнее указатели на них у меня хранятся в QList, и при инициализации окна я добавляю им в цикле всплывающее окно и связываю нажатия с обработчиком, но не могу сделать так, чтобы обработчик был один на каждый цвет. Думаю с кодом будет понятнее. C++ (Qt) for (int i = 0; i < 6; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { allAct[0][countAct] = new QAction("Белый", mainFrames[i][j][k]); allAct[1][countAct] = new QAction("Оранжевый", mainFrames[i][j][k]); allAct[2][countAct] = new QAction("Зеленый", mainFrames[i][j][k]); allAct[3][countAct] = new QAction("Красный", mainFrames[i][j][k]); allAct[4][countAct] = new QAction("Синий", mainFrames[i][j][k]); allAct[5][countAct] = new QAction("Желтый", mainFrames[i][j][k]); mainFrames[i][j][k]->addAction(allAct[0][countAct]); mainFrames[i][j][k]->addAction(allAct[1][countAct]); mainFrames[i][j][k]->addAction(allAct[2][countAct]); mainFrames[i][j][k]->addAction(allAct[3][countAct]); mainFrames[i][j][k]->addAction(allAct[4][countAct]); mainFrames[i][j][k]->addAction(allAct[5][countAct]); mainFrames[i][j][k]->setContextMenuPolicy(Qt::ActionsContextMenu); mainFrames[i][j][k]->connect(allAct[0][countAct], SIGNAL(triggered), mainFrames[i][j][k], SLOT(mainFrames[i][j][k])); connect(allAct[0][countAct], SIGNAL(triggered), this, SLOT(changeWhite(mainFrames[i][j][k]))); connect(allAct[1][countAct], SIGNAL(triggered()), this, SLOT(changeOrange())); connect(allAct[2][countAct], SIGNAL(triggered()), this, SLOT(changeGreen())); connect(allAct[3][countAct], SIGNAL(triggered()), this, SLOT(changeRed())); connect(allAct[4][countAct], SIGNAL(triggered()), this, SLOT(changeBlue())); connect(allAct[5][countAct], SIGNAL(triggered()), this, SLOT(changeYellow())); } } } } // слот для обработки нажатия на пункт меню void MainWindow::changeWhite(QFrame *frame1) { frame1->setStyleSheet("background-color: white"); }
выглядит крайне массивно и некрасиво, есть ли более изящное решение и как вообще передать параметр в слот, если при connect это нельзя сделать. А использовать QSignalMapper для массива таких объектов не понимаю как.
Название: Re: Передача параметра в слот
Отправлено: Swa от Октябрь 20, 2017, 22:22
Можно сделать через setData примерно так. Компилятора под рукой нет, так что возможны ошибки. { QAction* act1 = new QAction("Белый", mainFrames[i][j][k]); act1->setData( "white" ); connect(act1 , SIGNAL(triggered()), this, SLOT(changeColor()));
QAction* act2 = new QAction("Оранжевый", mainFrames[i][j][k]); act2->setData( "orange" ); connect(act2 , SIGNAL(triggered()), this, SLOT(changeColor()));
QAction* act3 = new QAction("Зеленый", mainFrames[i][j][k]); act3->setData( "green" ); connect(act3 , SIGNAL(triggered()), this, SLOT(changeColor()));
QAction* act4 = new QAction("Красный", mainFrames[i][j][k]); act4->setData( "red" ); connect(act4 , SIGNAL(triggered()), this, SLOT(changeColor()));
QAction* act5 = new QAction("Синий", mainFrames[i][j][k]); act5->setData( "blue" ); connect(act5 , SIGNAL(triggered()), this, SLOT(changeColor()));
QAction* act6 = new QAction("Желтый", mainFrames[i][j][k]); act6->setData( "yellow" ); connect(act6 , SIGNAL(triggered()), this, SLOT(changeColor()));
mainFrames[i][j][k]->addAction(act1); mainFrames[i][j][k]->addAction(act2); mainFrames[i][j][k]->addAction(act3); mainFrames[i][j][k]->addAction(act4); mainFrames[i][j][k]->addAction(act5); mainFrames[i][j][k]->addAction(act6); mainFrames[i][j][k]->setContextMenuPolicy(Qt::ActionsContextMenu); }
void MainWindow::changeColor() { // Находим action, который отправил сигнал QAction* action = qobject_cast<QAction*>(QObject::sender()); // Находим заложенный в него цвет QString color = action->data().toString(); // Находим виджет-родитель QFrame* frame = qobject_cast<QFrame*>(action->parent()); // Устанавливаем стиль color = color.prepend("background-color: "); frame ->setStyleSheet(color); }
Название: Re: Передача параметра в слот
Отправлено: deMax от Октябрь 21, 2017, 15:25
allAct[0][countAct] = new QAction("Белый", mainFrames[j][k]); allAct[1][countAct] = new QAction("Оранжевый", mainFrames[j][k]);
можно заменить на int n=0; for(auto& str: {"белый","синий","зеленый","...","..."}) { auto &mainFrame = mainFrames[j][k]; mainFrame->addAction(allAct[n][countAct] = new QAction("Белый", mainFrame)); ++n; } // mainframe имхо тут 2 раза не нужен
слоты тоже можно засунуть в список auto f = {&Test::a1, &Test::a2, &Test::a3}; только пока не смотрел как в коннекте получить конкретный?
Название: Re: Передача параметра в слот
Отправлено: MrDron от Октябрь 23, 2017, 12:32
mainwindow.h C++ (Qt) QList<QFrame*> listFrames; QMenu popupMenu; QFrame *activeFrame;
mainwindow.cpp C++ (Qt) MainWindow::MainWindow() { auto listColors = QList<QPair<QString, QString> >() << qMakePair(QString("white"), QString("Белый")) << qMakePair(QString("orange"), QString("Оранжевый")) << qMakePair(QString("green"), QString("Зеленый")) << qMakePair(QString("red"), QString("Красный")) << qMakePair(QString("blue"), QString("Синий")) << qMakePair(QString("yellow"), QString("Желтый")); QList<QAction*> listActions; for (auto color : listColors) { QPixmap pixmap(16, 16); pixmap.fill(QColor(color.first)); auto action = new QAction(QIcon(pixmap), color.second, this); action->setData(color.first); listActions << action; connect(action, &QAction::triggered, this, &MainWindow::changeColor); } this->popupMenu.addActions(listActions); for (auto frame : this->listFrames) frame->installEventFilter(this); } bool MainWindow::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::ContextMenu) { this->activeFrame = static_cast<QFrame*>(object); this->popupMenu.exec(QCursor::pos()); } return QObject::eventFilter(object, event); } void MainWindow::changeColor() { activeFrame->setStyleSheet(QString("background-color: %1").arg(static_cast<QAction*>(sender())->data().toString())); }
|