Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Маркер в таблице...

Автор: fortero 18.4.2011, 13:51

Добрый день Господа!
Есть вот такой незамысловатый код:

#include <QtGui>
#include <QtCore>

int main(int argc, char ** argv){
    QApplication app(argc, argv);
    
    QTableWidget table(2, 2);
    QStringList tit;
    tit << "Columens Name" << "Columens Phone";
    table.setHorizontalHeaderLabels(tit);
    
    QTableWidgetItem *item1 = new QTableWidgetItem("Vasy");
    QTableWidgetItem *item2 = new QTableWidgetItem("77777777");
    QTableWidgetItem *item3 = new QTableWidgetItem("Pety");
    QTableWidgetItem *item5 = new QTableWidgetItem("11111111");
    
    table.setItem(0,0, item1);
    table.setItem(0,1, item2);
    table.setItem(1,0, item3);
    table.setItem(1,1, item5);
    
    table.setSortingEnabled(true);
    QString s =
        
        " QHeaderView::down-arrow {"
        "    image: url(img/down.png); width: 18px"
        " }"
        " QHeaderView::up-arrow {"
        "    image: url(img/up.png); width: 18px"
        " }";
    app.setStyleSheet(s);
    table.resizeRowsToContents();

    
    table.show();
    
    
    return app.exec();
}

Это простая табличка, из 2 колонок и 2 строк, сортировка работает… Вод только осталось решить 2 проблемы я не селён в QT, я только начинаю. Подскажите пожалуйста как сделать что бы когда я 1 раз кликаю на строку марке не ячейку подсвечивал а всю строку и второе разумеется не пробовал редактировать. То есть мне нужна табличка которая не будет редактироваться, а маркер подсвечивать будет всю строку, как это сделать???
Спасибо за внимание!

Автор: fortero 18.4.2011, 14:37

С первой проблемой я догадываюсь как решить нашёл я слот selectRow(int row), то есть зная на какой строке стоит маркер можно при помощи connect передать номер строки, тогда как связать эти действия? То есть как послать нужный сигнал???

Автор: fortero 18.4.2011, 15:07

Помоему я нашёл решение, скажите насколько это правильно но чёрт возми оно работает:

QObject::connect(&table, SIGNAL(cellClicked(int, int)), &table, SLOT(selectRow(int)));


Как же быть со вторым вопросом? Запрет редактирования???

Автор: wiz29 18.4.2011, 15:14

Цитата(fortero @ 18.4.2011, 15:37) *
... тогда как связать эти действия? То есть как послать нужный сигнал???

Не совсем понятно о чем идет речь.

Цитата(fortero @ 18.4.2011, 16:07) *
Помоему я нашёл решение, скажите насколько это правильно но чёрт возми оно работает:
QObject::connect(&table, SIGNAL(cellClicked(int, int)), &table, SLOT(selectRow(int)));

Абсолютно нормальное решение.

Цитата(fortero @ 18.4.2011, 16:07) *
Запрет редактирования???

    QTableWidgetItem* pItem = new QTableWidgetItem(tr("blablabla"));
        pItem->setFlags(pItem->flags() & (~(Qt::ItemIsEditable)));

Автор: fortero 18.4.2011, 16:09

[quota]

    QTableWidgetItem* pItem = new QTableWidgetItem(tr("blablabla"));
        pItem->setFlags(pItem->flags() & (~(Qt::ItemIsEditable)));

[/quote]

А я вот ещё нашёл, подайдёт?
table.setEditTriggers(QAbstractItemView::NoEditTriggers);

Автор: wiz29 18.4.2011, 16:37

да подойдет, если нужен запрет на редактирование всего представления таблицы.

Автор: silver47 18.4.2011, 17:42

Цитата(fortero @ 18.4.2011, 13:51) *
а маркер подсвечивать будет всю строку, как это сделать???

Цитата(fortero @ 18.4.2011, 17:07) *
Помоему я нашёл решение, скажите насколько это правильно но чёрт возми оно работает:


Мне кажется так лучше:
QTableWidget::setSelectionBehavior(QAbstractItemView::SelectRows);

Автор: fortero 18.4.2011, 17:44

Новый вопрос, теперь решил я передовать сигнал в слот другого класса, вот таким способом:

QObject::connect(&table, SIGNAL(itemDoubleClicked(QTableWidgetItem)), &ddd, SLOT(dial(QTableWidgetItem)));

Но не чего не происходит, а когда я пробовал так:
QObject::connect(&table, SIGNAL(cellDoubleClicked(int, int)), &ddd, SLOT(dial(int, int)));


То всё работало передовался номер строки и колонки, а как же передать содиржимое ячейки?

Автор: ruzik 18.4.2011, 17:48

tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //Выделить всю строку
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //Запрет редактирования

Автор: silver47 18.4.2011, 18:10

Цитата(fortero @ 18.4.2011, 19:44) *
То всё работало передовался номер строки и колонки, а как же передать содиржимое ячейки?


Ну логично предположить, что, если вы ячейку не редактируете, а просто выделяете, то нужно бы создать свой сигнал, который будет испускаться при выделении ячейки, и который будет передавать ее содержимое. Если точно не знаете, что будет в ячейке, то рекомендую в сигнале передавать тип QVariant

Для этого свяжем сигнал выделения ячейки с неким слотом:
QObject::connect(table, SIGNAL(clicked(QModelIndex)), this, SLOT(someSlot(QModelIndex)));

// слот
    // берем значение ячекий
QVariant value(index.sibling(index.row(), index.column()).data(Qt::EditRole));
    // испускаем сигнал со значением
emit cellValue(value);

Автор: fortero 18.4.2011, 18:24

Уже получилось передать ячейку:

MyDialog *ddd = new MyDialog;
QObject::connect(&table, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), ddd, SLOT(dial(QTableWidgetItem *)));


Вопрос следующий а как из объекта класса QTableWidgetItem извлечь данный и к примеру привратить в класс QString????

Автор: silver47 18.4.2011, 18:26

Цитата(fortero @ 18.4.2011, 20:24) *
Уже получилось передать ячейку:
MyDialog *ddd = new MyDialog;
QObject::connect(&table, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), ddd, SLOT(dial(QTableWidgetItem *)));


Вопрос следующий а как из объекта класса QTableWidgetItem извлечь данный и к примеру привратить в класс QString????


Смотрите мой пост выше. А из QTableWidgetItem вы можете получить текст просто, вызвав метод QTableWidgetItem::text();

Автор: fortero 18.4.2011, 18:29

А чем плох мой способ передачи???

Автор: silver47 18.4.2011, 18:30

Цитата(fortero @ 18.4.2011, 20:29) *
А чем плох мой способ передачи???


Ничем. Нормальный способ :) Только, как мне кажется, он будет работать только с QTableWidget. У QTableView передать ячейку не удастся.

Автор: fortero 18.4.2011, 18:38

Всем кто участвовал огромное спасибо у меня всё получилось!!! :clapping:

Автор: fortero 20.4.2011, 21:14

А ещё вопрос, а если мне надо по клавише Enter вызывать сигнал, как это организовать с клавишами я пока не работал ещё??? То есть мне нужно когда я стою на нужной строке и жму клавишу Enetr происходило действие...

Автор: silver47 21.4.2011, 5:06

Цитата(fortero @ 20.4.2011, 23:14) *
А ещё вопрос, а если мне надо по клавише Enter вызывать сигнал, как это организовать с клавишами я пока не работал ещё??? То есть мне нужно когда я стою на нужной строке и жму клавишу Enetr происходило действие...


1. Изменения которые необходимо внести в заголовочный файл того виджета, на котором таблица расположена:
protected:
    virtual void keyPressEvent(QKeyEvent *pe);


2. Теперь создадим описанный нами метод:
void Widget::keyPressEvent(QKeyEvent *pe){    
    if ((pe->key() == 16777220) | (pe->key() == 16777221)) this->someSlot(); // Enter
}


16777220 и 16777221 - это коды двух клавиш Enter. Чтобы узнать какой код у кнопки, поставьте вывод qDebug() << pe; в самом начале метода. Для того, чтобы знать нажаты ли кнопки-модификаторы (Alt; Ctrl; Shift), нужно проверить вот такое вот условие:

if (pe->modifiers() & Qt::ShiftModifier) // зажат шифт
if (pe->modifiers() & Qt::AltModifier) // зажат альт
if (pe->modifiers() & Qt::CtrlModifier) // зажат Ctrl


Опять же, все тот же, Макс Шлее страница 259

Автор: fortero 2.5.2011, 2:26

Цитата(silver47 @ 21.4.2011, 5:06) *
Цитата(fortero @ 20.4.2011, 23:14) *
А ещё вопрос, а если мне надо по клавише Enter вызывать сигнал, как это организовать с клавишами я пока не работал ещё??? То есть мне нужно когда я стою на нужной строке и жму клавишу Enetr происходило действие...


1. Изменения которые необходимо внести в заголовочный файл того виджета, на котором таблица расположена:
protected:
    virtual void keyPressEvent(QKeyEvent *pe);


2. Теперь создадим описанный нами метод:
void Widget::keyPressEvent(QKeyEvent *pe){    
    if ((pe->key() == 16777220) | (pe->key() == 16777221)) this->someSlot(); // Enter
}


16777220 и 16777221 - это коды двух клавиш Enter. Чтобы узнать какой код у кнопки, поставьте вывод qDebug() << pe; в самом начале метода. Для того, чтобы знать нажаты ли кнопки-модификаторы (Alt; Ctrl; Shift), нужно проверить вот такое вот условие:

if (pe->modifiers() & Qt::ShiftModifier) // зажат шифт
if (pe->modifiers() & Qt::AltModifier) // зажат альт
if (pe->modifiers() & Qt::CtrlModifier) // зажат Ctrl


Опять же, все тот же, Макс Шлее страница 259


Спасибо, это очень интересно, но а как мне в слот передать информацию о месте нахождения маркера, когда мышей я кликал то я использовал вот такой вариант:
connect(mtab, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(dubleClic_slot(int )));

А тут как быть, как узнать отмеченный маркер, причём последний, ведь случайно можно две строки выделить!
Спасибо за внимание!


Автор: silver47 2.5.2011, 6:05

гм... Наверное будет работать тоже самое:

QModelIndex index(QTableView::curentIndex());  вместо QTableView - подставьте свою таблицу
if(!index.isValid)) return; // выход если индекс не корректен

QString Str;
Str = index.sibling(index.row(), index.column()).data(Qt::EditRole).toString(); // поместили в переменную Str текст выделенной ячейки

Автор: fortero 2.5.2011, 19:49

Одна проблема, у меня не QTableView а QTableWidget, а функций индекс там нет...

Автор: fortero 2.5.2011, 22:01

Кажеться победил:

void TableCl::keyPressEvent(QKeyEvent *pe){
    if ((pe->key() == 16777220) | (pe->key() == 16777221))
    {
    QList<QTableWidgetItem *>  *tList = new QList<QTableWidgetItem *>(mtab->selectedItems());
              if(!tList->empty())
    this->dubleClic_slot(tList->last()->row());
    delete tList;
    }
}


Silver47 покритекуйте, может что-то не так?

Автор: Алексей1153 4.5.2011, 21:00

1) волшебные цифры лучше заменить на мнемоники (Qt::Key_Return и Qt::Key_Enter)
2) new, по моему, тут не нужен (вернее, можно без кучи обойтись):

QList<QTableWidgetItem *>  tList(mtab->selectedItems());
if(!tList.empty())
{
    dubleClic_slot(tList.last()->row());
}

Автор: fortero 5.5.2011, 1:08

Цитата(Алексей1153 @ 4.5.2011, 21:00) *
1) волшебные цифры лучше заменить на мнемоники (Qt::Key_Return и Qt::Key_Enter)
2) new, по моему, тут не нужен (вернее, можно без кучи обойтись):
QList<QTableWidgetItem *>  tList(mtab->selectedItems());
if(!tList.empty())
{
    dubleClic_slot(tList.last()->row());
}


А если можно поподробней о new, просто у меня не совсем ещё сформировалось понимание когда он нужен а когда нет?
Почему Вы считаете что тут он не нужен прокаментируйте пожалуйста.
Спасибо за внимание!

Автор: Алексей1153 5.5.2011, 20:42

об операторе new подробнее, чем любая книжка по C++ я рассказать не сумею. Если коротко - это работа с кучей, new выделяет память из кучи под переменную, delete возвращает. Автоматически вызываются конструктор и деструктор соответственно

В данном случае наличие new/delete совершенно необязательно, так как автоматическая локальная переменная выполнит всё то же самое. Но если хочется, можно оставить и так, как у тебя ))

Автор: fortero 6.5.2011, 3:43

Цитата(Алексей1153 @ 5.5.2011, 20:42) *
об операторе new подробнее, чем любая книжка по C++ я рассказать не сумею. Если коротко - это работа с кучей, new выделяет память из кучи под переменную, delete возвращает. Автоматически вызываются конструктор и деструктор соответственно

В данном случае наличие new/delete совершенно необязательно, так как автоматическая локальная переменная выполнит всё то же самое. Но если хочется, можно оставить и так, как у тебя ))


В каких случаях Куча актуальна будет?
Я не совсем чувствую грань когда следует в QT пользоватся динамической памятью а когда нет...

Автор: Алексей1153 6.5.2011, 19:20

Цитата(fortero @ 6.5.2011, 6:43) *
Я не совсем чувствую грань когда следует в QT пользоватся динамической памятью а когда нет...

речь не про Qt, а про C++ , кстати


Цитата(fortero @ 6.5.2011, 6:43) *
В каких случаях Куча актуальна будет?


например, если бы был массив большого размера. Локальные переменный размещаются на стеке, а стек имеет ограниченный размер. Если стек переполнен, то программа в лучшем случае просто аварийно завершится.
Также, для массивов с изменяемым размером. Контейнеры Qt и STL тоже внутри себя используют кучу для хранения данных. По последней причине, кстати, контейнеры можно спокойно использовать как локальные переменные, так как, по сути, "локальное" тело переменной - несколько указателей и счётчиков количества элементов. А данные лежат на куче

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)