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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перетаскивание элементов QTableView: подсветка/обрамление ячеек под курсором  (Прочитано 5196 раз)
schmidt
Гость
« : Март 22, 2013, 18:32 »

Добрый вечер,

Стандартно при перетаскивании элементов QTableView отображается значение этого элемента рядом с курсором, но ячейки, над которыми протаскивают элемент, никак не подают вида, что сброс осуществляется именно в данную конкретную ячейку. Хотелось бы сделать так, чтобы ячейки изменяли цвет фона, или обрамлялись жирной границей, говоря пользователю "Эй, ты можешь сбросить это в меня!" Улыбающийся

Поиск по интернету дал информацию о том, как реализовать подсветку элемента QTableView в момент наведения на него курсора - с помощью делегата, и выглядит это так:

Код:
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                             const QModelIndex &index) const {
    if(index.isValid()) {
        if(option & QStyle::State_MouseOver) {
             // Курсор мыши наведен на элемент
        }
    }
}

Если я правильно понимаю, то решение моей проблемы состоит в том, чтобы отлавливать событие "начало перетаскивания" и подключать делегат с подсветкой?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Март 23, 2013, 11:02 »

Код
C++ (Qt)
void QAbstractItemView::setDropIndicatorShown( bool enable )
Записан

Qt 5.11/4.8.7 (X11/Win)
schmidt
Гость
« Ответ #2 : Март 23, 2013, 11:32 »

По какой-то неясной причине изменение showDropIndicator не дает никакого эффекта. Возможно я где-то в модели чего-то нагородил, перегружая методы, или с событиями QTableView. **Пошел впитывать Drag/Drop документацию полностью  Улыбающийся
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Март 23, 2013, 11:36 »

Наверняка при наследовании забываешь вызывать метод базового класса.
Записан

Qt 5.11/4.8.7 (X11/Win)
schmidt
Гость
« Ответ #4 : Март 23, 2013, 14:58 »

Создал тестовый проект, стал поочередно добавлять функционал до тех пор "пока не сломается" Улыбающийся А сломалось всё после того как я переопределил  метод mimeData(). Видимо, и вправду что-то магическое добавляет вызов

Код:
QMimeData* data = QAbstractTableModel::mimeData(indexes);

к объекту QMimeData, но все вернулось на свои места после этого  Улыбающийся
Записан
schmidt
Гость
« Ответ #5 : Март 23, 2013, 16:57 »

А если я хочу "прокачать" TableView, чтобы он обрамлял активную область сброса под курсором, если пользователь перетаскивает прямоугольный регион?

Код:
void MatrixDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                           const QModelIndex &index) const {
    /* Если в данный момент происходит перетаскивание выделенных ячеек,
     * Обрамлять активную область сброса границей */
    if(_isDraggedModeEnabled()) {
              // ...
    }
}

Есть ли способ из делегата добраться до выделения в QTableView? Улыбающийся

Код:
QItemSelectionModel * QAbstractItemView::selectionModel() const
Записан
schmidt
Гость
« Ответ #6 : Март 24, 2013, 07:16 »

Решил проблему иным путем: реализовал собственный делегат с методом setRegionBorder(), в переопределеном методе dragMoveEvent() у TableView вызываю метод setRegionBorder() делегата. В методе paint() делегата проверяю, не лежит ли ячейка на границе заданной setRegionBorder() области, и рисую линию сверху/справа/снизу/слева от ячейки:

Код:
//---------------------------------------------------------------------------------------
void MatrixDelegate::setRegionBorder(int upper_row, int left_column, int bottom_row, int right_column) {
    _left_border_column_idx = left_column;
    _upper_border_row_idx = upper_row;
    _right_border_column_idx = right_column;
    _bottom_border_row_idx = bottom_row;
}

//---------------------------------------------------------------------------------------
void MatrixDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                           const QModelIndex &index) const {
    if(index.isValid()) {
        int cell_row = index.row();
        int cell_column = index.column();
        /* Проверить, не является ли ячейка границей региона, к которому применяется обрамление */
        if(_isCellHasLeftBorder(cell_row, cell_column)) {
            // Отрисовать границу слева
            _drawLeftCellBorder(painter, option);
        }
        if(_isCellHasUpperBorder(cell_row, cell_column)) {
            // Отрисовать границу сверху
            _drawUpperCellBorder(painter, option);
        }
        if(_isCellHasRightBorder(cell_row, cell_column)) {
            // Отрисовать границу справа
            _drawRightCellBorder(painter, option);
        }
        if(_isCellHasBottomBorder(cell_row, cell_column)) {
            // Отрисовать границу снизу
            _drawBottomCellBorder(painter, option);
        }

        QStyledItemDelegate::paint(painter, option, index);
    }
}

//---------------------------------------------------------------------------------------
bool MatrixDelegate::_isCellHasLeftBorder(int row, int column) const {
    bool is_cell_between_horizontal_borders =
            ( (_upper_border_row_idx <= row) && (row <= _bottom_border_row_idx) );

    bool is_cell_lays_onto_left_edge = ( column == _left_border_column_idx );

    return ( is_cell_between_horizontal_borders && is_cell_lays_onto_left_edge );
}

//---------------------------------------------------------------------------------------
/* и.т.д. по аналогии */

//---------------------------------------------------------------------------------------
void MatrixView::dragMoveEvent(QDragMoveEvent *evt) {
    QModelIndex index_under_cursor = indexAt(evt->pos());
    int current_row = index_under_cursor.row();
    int current_column = index_under_cursor.column();

    QItemSelectionRange selected_range = selectionModel()->selection().first();
    int upper_row = selected_range.top();
    int bottom_row = selected_range.bottom();
    int left_column = selected_range.left();
    int right_column = selected_range.right();
    int selection_width = right_column - left_column;
    int selection_height = bottom_row - upper_row;

    _matrix_delegate->clearRegionBorder();
    _matrix_delegate->setRegionBorder(current_row, current_column,
                                           current_row + selection_height,
                                           current_column + selection_width);

    QTableView::dragMoveEvent(evt);
}
« Последнее редактирование: Март 24, 2013, 07:31 от Schmidt » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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