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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Как лучше подойти к вопросу изучения QT? А также вопрос по setFilterWildcard.  (Прочитано 10424 раз)
Dragon
Гость
« : Май 13, 2010, 16:08 »

1. Начал изучать QT. Использую книгу М.Шлее (QT4.5. Профессиональное программирование на C++), Зоммерфельда и Бланшета, а также QT Assistant.
Опыт в С++ теоретический (недавно основы охватил по книге У.Савитч "Программирование на С++, 4 издание").

Читаю про элементы интерфейса, их создание (уже пообвыкся с указателями, немножечко начал понимать сигналы и слоты). Но чтобы что-то простое из прочитанного применить надо открывать книгу и не отрываясь от нее кодить. Конечно же вы ответите - "Все придет с практикой". Но практику эту нужно где-то взять. Хочется в этой сфере работать, но для этого надо знания. Посоветуйте, как подойти к вопросу изучения QT? Может есть какие-нить книги (англ?!) с заданиями или может присоветуете какой-нибудь подход в этом вопросе?

2. Вопрос по setFilterWildcard.
Есть две модели (model и proxyModel) и однострочное поле (роль фильтра).
В моделях выводится стринговый список. В поле вводим символы и в промежуточной модели (proxyModel) выводятся результаты в соответствии с регулярным выражением, которое обрабатывается слотом setFilterWildcard.
Как сделать, чтобы данные введенные в фильтр воспринимались setFilterWildcard как "XYZ*", а не "*XYZ*"?

Собственно код:
Код
C++ (Qt)
#include <QtGui>
 
int main(int argc, char** argv)
{
   QApplication app(argc, argv);
   QWidget wgt;
 
   QStringListModel model;
   model.setStringList(QStringList() << "Aurora" << "Permanent"
                                     << "Shock" << "Behind the wall"
                                     << "Material" << "Anesthesia");
 
   QSortFilterProxyModel proxyModel;
   proxyModel.setSourceModel(&model);
 
   QListView* pListView1 = new QListView;
   pListView1->setModel(&model);
 
   QListView* pListView2 = new QListView;
   pListView2->setModel(&proxyModel);
 
   QLabel* lbl = new QLabel("&Text:");
   QLineEdit* txt = new QLineEdit;
   lbl->setBuddy(txt);
 
   QObject::connect(txt, SIGNAL(textChanged(QString)),
                    &proxyModel, SLOT(setFilterWildcard(QString)));
 
   //Layout Setup
   QGridLayout* pgrdLayout = new QGridLayout;
   pgrdLayout->addWidget(pListView1, 0, 0);
   pgrdLayout->addWidget(pListView2, 0, 1);
   pgrdLayout->addWidget(lbl, 1, 0);
   pgrdLayout->addWidget(txt, 2, 0, 1, 2);
 
   wgt.setLayout(pgrdLayout);
   wgt.show();
 
   return app.exec();
}

Если я введу в поле "ne", то в proxyModel останутся записи Permanent и Anesthesia, вместо пустого списка.
Записан
crossly
Гость
« Ответ #1 : Май 13, 2010, 16:21 »

я думаю лучше будет произвести обработку строки в отдельном слоте и использовать setFilterRegExp
Записан
Dragon
Гость
« Ответ #2 : Май 13, 2010, 17:34 »

Хм, пока это мне кажется непосильной задачей. Случаем для этого отдельный класс разрабатывать не надо?
« Последнее редактирование: Май 13, 2010, 18:38 от Dragon » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


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

>>Случаем для этого отдельный класс разрабатывать не надо?
а что там разрабатывать?
в myclass.h пишешь:
Код
C++ (Qt)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QtGui>
 
class MainWindow : pulic QWidget
{
   Q_OBJECT
public:
   // конструктор класса
   MainWindow(QWidget *parent = 0);
   // деструктор класса
   ~MainWindow();
 
public slots:
   // слот
   void mySlot(/*тут аргументы, как у сигнала, с которым будешь соединять*/);
};
#endif //MAINWINDOW_H

в myclass.cpp пишешь:
Код
C++ (Qt)
#include "myclass.h"
// конструктор класса
MainWindow::MainWindow(QWidget *parent = 0):QWidget(parent)
{
//Сюда перетаскиваешь большую часть кода из функции main
 
// соединяешь сигнал (для примера - someSignal(int value)) нужного объекта (для примера - object) со своим слотом:
   connect(object, SIGNAL(someSignal(int)),
               this, SLOT(mySlot()));
   // обрати внимание в функции connect для сигналов и слотов не пишут имена аргументов, а только их тип
}
// деструктор класса
MainWindow::~MainWindow()
{
//тут может быть пусто
}
// слот
void MainWindow::mySlot()
{
//тут код того, что должен делать этот слот
}
 
не забываешь добавить в pro-файл оба этих фала
Код
Bash
SOURSES += myclass.cpp
HEADERS += myclass.h
« Последнее редактирование: Май 13, 2010, 21:34 от lit-uriy » Записан

Юра.
Dragon
Гость
« Ответ #4 : Май 14, 2010, 10:00 »

Цитировать
а что там разрабатывать?
Концепция класса в Qt отличается от классов в C++ по ряду вещей (наличие слотов и сигналов в Qt, к примеру). Я пока только изучаю элементы управления, создание их программно. Все примеры, которые сопровождаются и где использованы классы, унаследованные от какого-либо класса Qt относительно сложны т.к. по сути реализация той или иной функции происходит методами Qt (если можно так сказать).

За наводку спасибо. Буду разбираться, экспериментировать, пытаться что-либо сделать.
Если что, буду дальше задавать вопросы Улыбающийся
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #5 : Май 14, 2010, 10:34 »

>>Концепция класса в Qt отличается от классов в C++
да нет не отличается, просто халява добавлена вместо функций обратного вызова.
Слот - функция С++, с возможностью присоединения к нему сигналов. Всю химию о сигнально-слотовой связи берёт на себя MOC - метаобъектный компилятор.
Записан

Юра.
Dragon
Гость
« Ответ #6 : Май 14, 2010, 15:28 »

Запутался в слотах и сигналах и окончательно перестал что-либо понимать.

myregexp.h
Код
C++ (Qt)
#ifndef MYREGEXP_H
#define MYREGEXP_H
#include <QtGui>
 
class MyRegExp : public QWidget
{
public:
   MyRegExp(QWidget *parent = 0);
 
   ~MyRegExp();
 
public slots:
   void chkRegExp(QString);
};
 
#endif // MYREGEXP_H

myregexp.cpp
Код
C++ (Qt)
#include <QtGui>
#include "myregexp.h"
 
MyRegExp::MyRegExp(QWidget *parent)
{
   QStringListModel model;
   model.setStringList(QStringList() << "Aurora" << "Permanent"
                                     << "Shock" << "Behind the wall"
                                     << "Material" << "Anesthesia");
 
   QSortFilterProxyModel proxyModel;
   proxyModel.setSourceModel(&model);
 
   QListView* pListView1 = new QListView;
   pListView1->setModel(&model);
 
   QListView* pListView2 = new QListView;
   pListView2->setModel(&proxyModel);
 
   QLabel* lbl = new QLabel("&Text:");
   QLineEdit* txt = new QLineEdit;
   lbl->setBuddy(txt);
 
   connect(txt, SIGNAL(textChanged(QString)), this, SLOT(chkRegExp(QString)));
}
 
MyRegExp::~MyRegExp()
{
 
}
 
void MyRegExp::chkRegExp(QString)
{
}

В "void MyRegExp::chkRegExp(QString) {}" нужно писать, что будет делать слот. Т.е. проверка регулярного выражения. Но как я получу то, что уже есть в однострочном поле?

Была бредовая идея сделать что-нибудь вроде такого:
- получить строку из *txt
- ^ + содержимое *txt + "*" (для любого кол-ва символов после)
- отправить это все в proxyModel для вывода результатов по фильтру.

« Последнее редактирование: Май 14, 2010, 15:36 от Dragon » Записан
crossly
Гость
« Ответ #7 : Май 14, 2010, 15:41 »

для этого у тебя есть
Код:
connect(txt, SIGNAL(textChanged(QString)), this, SLOT(chkRegExp(QString)))
...
как только ты изменишь текст в поле ввода будет вызван слот chkRegExp в который будет передана твоя строка...
только нужно
Код:
chkRegExp(const QString &text/* <- это и будет текст который ты ввел */)
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #8 : Май 14, 2010, 16:55 »

>>void MyRegExp::chkRegExp(QString)
правило о том, что нельзя писать имя аргумента, относится только к функции connect. Т.е. свой слот пишешь так:
Код
C++ (Qt)
void MyRegExp::chkRegExp(QString value)
{
   QString var = value;
}
Ещё один полезный нюанс, функция sender() будучи вызванной в слоте вернёт указатель на QObject, который отправил сигнал в этот слот. Например, если с одним слотом соединены несколько виджетов, например кнопка (QPushButton) и поле ввода (QLineEdit), то можно для каждого определить свою обраьотку:
Код
C++ (Qt)
void MyRegExp::chkRegExp(QString value)
{
   QObject *o = sender();
   QLineEdit *le = qobject_cast<QLineEdit *>(o);
   // Если указатель не нулевой, то приведение типа удалось
   // это означает, что отправитель - объект типа QLineEdit
   if(le){
       // обработка для поля ввода
       QString var = value;
   }else{
      // обработка для остальных отправителей
   }
}
Записан

Юра.
Dragon
Гость
« Ответ #9 : Май 15, 2010, 16:27 »

Решил проверить работу собственного слота (так сказать, разобраться в работе слотов и сигналов на практике через пробы и ошибки).

Пока он выглядит так (может это и бред, но прошу камнями не брсоаться, суть вопроса не в допустимости создания такого регулярного выражения):
Код
C++ (Qt)
void MyRegExp::chkRegExp(QString text)
{
   QRegExp rx("^" + text + "*");
}

Проверять буду дебаггером.
Но тут возник глупый вопрос. Т.к. весь код (списки, Proxy Model, однострочное поле для ввода, подпись (Label), ) находится в конструкторе класса. То в main.cpp остается только создать объект класса и отобразить его. Но что в таком случае нужно передать в конструктор класса чтобы все, что было записано в конструкторе, отобразилось?

При обычном:
Код
C++ (Qt)
MyRegExp reg;
reg.show();
Запускается просто пустое окно (Layout добавил в конструктор).
« Последнее редактирование: Май 15, 2010, 16:31 от Dragon » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #10 : Май 15, 2010, 20:18 »

>>Layout добавил в конструктор
А остальные виджеты в компоновщик добавил или они где-то в воздухе остались висеть?
Записан

Юра.
Dragon
Гость
« Ответ #11 : Май 15, 2010, 20:46 »

Вот так выглядит полностью конструктор:
Код
C++ (Qt)
MyRegExp::MyRegExp(QWidget *parent):QWidget(parent)
{
   QWidget wgt;
 
   QStringListModel model;
   model.setStringList(QStringList() << "Aurora" << "Permanent"
                                     << "Shock" << "Behind the wall"
                                     << "Material" << "Anesthesia");
 
   QSortFilterProxyModel proxyModel;
   proxyModel.setSourceModel(&model);
 
   QListView* pListView1 = new QListView;
   pListView1->setModel(&model);
 
   QListView* pListView2 = new QListView;
   pListView2->setModel(&proxyModel);
 
   QLabel* lbl = new QLabel("&Text:");
   QLineEdit* txt = new QLineEdit;
   lbl->setBuddy(txt);
 
   //chkRegExp SLOT
   connect(txt, SIGNAL(textChanged(QString)), this, SLOT(chkRegExp(QString)));
 
   //Layout setup
   QGridLayout* pgrdLayout = new QGridLayout;
   pgrdLayout->addWidget(pListView1, 0, 0);
   pgrdLayout->addWidget(pListView2, 0, 1);
   pgrdLayout->addWidget(lbl, 1, 0);
   pgrdLayout->addWidget(txt, 2, 0, 1, 2);
 
   wgt.setLayout(pgrdLayout);
}
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #12 : Май 15, 2010, 21:55 »

Улыбающийся Си++!

QWidget wgt; - это было в main'е, а тепрь твой класс им и является.
Собственно, когда конструктор закончит работу, то это объект будет разрушен (вышли из функции, в которой он объявлен) и его дочерние виджеты тоже.

Просто удали эту строку, т.к. вместо него ты и создавал класс MyRegExp.
а последнюю строку замени на
this->setLayout(pgrdLayout);
или просто
setLayout(pgrdLayout);
Записан

Юра.
Dragon
Гость
« Ответ #13 : Май 15, 2010, 22:09 »

Ага. Понял теперь где собака зарыта. Спасибо Улыбающийся

Т.е. в классе, в частности в конструкторе, лучше создавать объекты, выделяя динамическую память?
По крайней мере пришлось таким образом обойтись с моделями данных (чтобы данные списка отображали):
Код
C++ (Qt)
QStringListModel* model = new QStringListModel;
QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel;

P.S> А Qt мне нравится все больше и больше - дружелюбная она что-ли Улыбающийся
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #14 : Май 15, 2010, 22:19 »

>>Т.е. в классе, в частности в конструкторе, лучше создавать объекты, выделяя динамическую память?
НЕТ.
объекты нужно создавать так, как этого требует логика программы. Если объект нужен только в конструкторе, то создавать на стеке (обычная переменная). Если объект будет нужен и по окончании работы функции/конструктора, то динамически. А если к объекту нужно будет неоднократно обращаться из функций класса, то его нужно создавать динамически и указатель на него объявить членом класса (т.е. в описании, а не в конструкторе) иначе за пределами функции/конструктора сам указатель будет разрушен (и невиден компилятору).

Так, например, если тебе понадобится обращаться к модели  в других функциях класса, то указатель на неё нужно объявлять не в конструкторе, а в описании класса.
Записан

Юра.
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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