Russian Qt Forum
Сентябрь 30, 2024, 10:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Контекстное меню на QTableWidgetItem  (Прочитано 6144 раз)
arhiv6
Гость
« : Март 27, 2014, 07:04 »

Добрый день.
На форме есть таблица (QTableWidget). Хочу иметь контекстное меню на элементах QTableWidgetItem этой таблицы + при выборе action из этого контекстного меню что-нибудь делать с этим QTableWidgetItem, но не знаю, как это сделать правильно.

1) Первый вариант - контекстное меню работает на всей таблице, даже где нет  ячеек + при вызове actionSlot1() или actionSlot1() я не знаю, на какой ячейке было вызвано контекстное меню:
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // создаю 4 ячейки
    ui->tableWidget->setColumnCount(4);
    ui->tableWidget->setRowCount(1);
    for (int i  = 0; i < 4; ++i)
        ui->tableWidget->setItem( 0, i, new QTableWidgetItem("Element"+QString::number(i)));

    ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
    ui->tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);

    QAction *action1 = new QAction("action1",this);
    QAction *action2 = new QAction("action2",this);

    ui->tableWidget->addAction(action1);
    ui->tableWidget->addAction(action2);

    ui->tableWidget->connect(action1, SIGNAL(triggered()), this, SLOT(actionSlot1()));
    ui->tableWidget->connect(action2, SIGNAL(triggered()), this, SLOT(actionSlot2()));
}

void MainWindow::actionSlot1()
{
    qDebug() << "set action1";
}

void MainWindow::actionSlot2()
{
    qDebug() << "set action2";
}

2) Второй вариант - контекстное меню работает только на ячейках таблицы, я знаю на какой ячейке вызвано контекстное меню, но при выборе из этого меню action - как правильно перейти в обработчик для этого action+передать туда указатель на QTableWidgetItem?
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),  ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->tableWidget->setColumnCount(4);
    ui->tableWidget->setRowCount(1);
    for (int i  = 0; i < 4; ++i)
        ui->tableWidget->setItem( 0, i, new QTableWidgetItem("Element"+QString::number(i)));

    ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
    ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    QAction *action1 = new QAction("action1",this);
    QAction *action2 = new QAction("action2",this);

    contextMenu=new QMenu();
    contextMenu->addAction(action1);
    contextMenu->addAction(action2);

    connect(ui->tableWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotShowContextMenu(const QPoint &)));
}

void MainWindow::slotShowContextMenu(const QPoint &pos)
{
    QTableWidgetItem *item;
    item = ui->tableWidget->itemAt(pos);

    if(!item)
        return;
   
    contextMenu->exec(QCursor::pos());
    qDebug() << "item text" << item->text();

}
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Март 27, 2014, 08:59 »

При вызове контекстного меню проверяйте текущий элемент таблицы ( currentItem() вернет или указатель на выделенную ячейку, или 0 ), если он равен 0, то нет выделенной ячейки, если есть, то у вас есть указатель на нее Улыбающийся
Записан

arhiv6
Гость
« Ответ #2 : Март 27, 2014, 09:32 »

Рассматривал такой вариант, но он не подходит. Ячейки могут занимать только часть таблицы. Если выделить ячейку, и после этого вызвать контекстное на свободном от ячеек пространстве, то выделение с ячейки не снимется и указатель в currentItem() вернет не 0. А по-хорошему контекстное меню вызваться не должно, т.к. щелчок был не на ячейке (как в варианте 2 первого поста).
Записан
AlexEx
Чайник
*
Offline Offline

Сообщений: 76


Просмотр профиля
« Ответ #3 : Март 29, 2014, 21:53 »

Как вариант, в слоте slotShowContextMenu для каждого action'а меню можно через его метод setData привязать ссылку на QTableWidgetItem, желательно не напрямую через прямое преобразование указателя (QVariant не работает с указателями), а через какой-нибудь вспомогательный QMap.
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #4 : Март 29, 2014, 21:55 »

Как вариант, в слоте slotShowContextMenu для каждого action'а меню можно через его метод setData привязать ссылку на QTableWidgetItem, желательно не напрямую через прямое преобразование указателя (QVariant не работает с указателями), а через какой-нибудь вспомогательный QMap.
QVariant вообще-то работает с указателями Улыбающийся

Регистрация своего типа:
http://qt-project.org/doc/qt-4.8/qmetatype.html#Q_DECLARE_METATYPE

Помещение своего типа:
http://qt-project.org/doc/qt-4.8/qvariant.html#setValue
или http://qt-project.org/doc/qt-4.8/qvariant.html#fromValue

Получение своего типа:
http://qt-project.org/doc/qt-4.8/qvariant.html#value
« Последнее редактирование: Март 29, 2014, 21:57 от gil9red » Записан

arhiv6
Гость
« Ответ #5 : Март 31, 2014, 16:03 »

Спасибо. Хватило передавать не указатель на QTableWidgetItem, а всего лишь номер столбца, поэтому не пришлось регистрировать свой тип. Сделал так:
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),  ui(new Ui::MainWindow)
{
    ui->setupUi(this);

        // создаю 4 ячейки
        ui->tableWidget->setColumnCount(4);
        ui->tableWidget->setRowCount(1);
        for (int i  = 0; i < 4; ++i)
            ui->tableWidget->setItem( 0, i, new QTableWidgetItem("Element"+QString::number(i)));

        ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
        ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);

        action1 = new QAction("action1",this);
        action2 = new QAction("action2",this);

        contextMenu=new QMenu();
        contextMenu->addAction(action1);
        contextMenu->addAction(action2);

        connect(ui->tableWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotShowContextMenu(const QPoint &)));
        connect(action1, SIGNAL(triggered()), this, SLOT(actionSlot1()));
        connect(action2, SIGNAL(triggered()), this, SLOT(actionSlot2()));
}

void MainWindow::slotShowContextMenu(const QPoint &pos)
{
    QTableWidgetItem *item;
    item = ui->tableWidget->itemAt(pos);

    if(!item)
        return;

    for (int i = 0; i < contextMenu->actions().size(); i++)
        contextMenu->actions().at(i)->setData(QVariant(ui->tableWidget->column(item)));

    contextMenu->exec(QCursor::pos()); // обязательно в конце функции
}

void MainWindow::actionSlot1()
{
    QAction* action = qobject_cast< QAction* >( sender() );
    qDebug() << "action 2, column" << action->data().toInt();
}

void MainWindow::actionSlot2()
{
    QAction* action = qobject_cast< QAction* >( sender() );
    qDebug() << "action 2, column" << action->data().toInt();
}
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.046 секунд. Запросов: 23.