Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt4]не получается получить доступ к объекту


Автор: anatox91 9.4.2008, 11:10
и снова здрасьте!

есть класс диалогового окна, сделанный для главного окна(класс, унаследованный от QMainWindow), и в нем надо при нажатии кнопки проводить поиск в объекте класса QTextEdit, находящемся в главном окне, но при компиляции выводит ошибки:
user posted image
вот определение объекта:
MainWindow.h
Код

public:                              //15 строка
       MainWindow();         //16
       QTextEdit *textArea;  //17


вот слот поиска в FindDialog.cpp:
Код

void FindDialog::slotFind() {                                    //32
     strFind = lineFind->text();                                   //33
     if(!strFind.isEmpty()) {                                         //34
                            if(caseSensitivity->isChecked()) { //35
                                                            if(!(MainWindow::textArea->find(strFind, QTextDocument::FindCaseSensitively))) { //36
                                                                                                     nothing();  //37
                                                                                                     }                //38
                                                            }                                                          //39
                            else {                                                                                  //40
                                 if(!(MainWindow::textArea->find(strFind))) {                 //41
                                                                            nothing();                            //42
                                                                            }
                                 }
                            }
     else emptyString();
}


а это слот вызывающийся при выборе пункта меню в главном окне:
MainWindow.cpp
Код

void MainWindow::findNext() {
     FindDialog *findDlg = new FindDialog;
     if(findDlg->exec() == QDialog::Rejected) {
                        delete findDlg;
                        }
}


подскажите пожалуйста в чем ошибка?  smile 
 

Автор: SABROG 9.4.2008, 14:29
Код

MainWindow::textArea->find(strFind)


В способе доступа к указателю, через не статический объект textArea.

Либо используй прямой указатель на MainWindow, либо делай указатель textArea глобальным/статическим для всех классов типа MainWindow, правда это будет глупостью. Сделай френдом класс MainWindow в классе FindDialog или передавай указатель на MainWindow в конструкторе.

Автор: Mephisto 9.4.2008, 14:44
У FindDialog делаешь сигнал к примеру FindNext.
Далее просто:
Код

void MainWindow::findNext() {
     FindDialog *findDlg = new FindDialog;
     connect(findDlg, SIGNAL(FindNext()), SLOT(slotFind()));
     if(findDlg->exec() == QDialog::Rejected) {
                        delete findDlg;
                        }
}

Когда нужно именно искать из FindDialog, в нем пишешь код:
Код

emit FindNext();

Автор: anatox91 9.4.2008, 18:34
блин... я вконец запутался... помогите кто-нибудь...
в FindDialog.cpp я кроме конструктора сделал слот (вызывающийся после клика на кнопку в этом же классе)
Код

void FindDialog::fN() {
     emit fndNext();
}


в FindDialog.h сделал так
Код

public:
       FindDialog(QWidget *parent = 0);
       friend QString MainWindow::getStrFind();
       friend bool MainWindow::isSensitivity();
public slots:
       void fN();
signals:
        void fndNext();

в MainWindow.h добавил
Код

public slots:
        void findNext();
        void slotFind();

Код

public:
        QString getStrFind();
        bool isSensitivity();


в MainWindow.срр :
Код

void MainWindow::findNext() {
     FindDialog *findDlg = new FindDialog;
     connect(findDlg, SIGNAL(fndNext()), SLOT(slotFind()));
     if(findDlg->exec() == QDialog::Rejected) {
                        delete findDlg;
                        }
}
void MainWindow::slotFind() {
     QString strFind = getStrFind();
     if(!strFind.isEmpty()) {
                            if(isSensitivity()) {
                                                            if(!(textArea->find(strFind, QTextDocument::FindCaseSensitively))) {
                                                                                                     nothing();
                                                                                                     }
                                                            }
                            else {
                                 if(!(textArea->find(strFind))) {
                                                                            nothing();
                                                                            }
                                 }
                            }
     else emptyString();
}
QString MainWindow::getStrFind() {
        return lineFind->text();
}
bool MainWindow::isSensitivity() {
     return caseSensitivity->isChecked();
}


компилятор пишет что не знает что такое lineFind и caseSensitivity (в двух последних приведенных мною функциях)...  smile  smile 

походу надо как-то передавать объект класса FindDialog в френд-функции... только я уже не соображаю как...  smile 

Автор: SABROG 10.4.2008, 11:43
Френды хороши при использовании методов классов, которые не меняют внутреннего состояния объекта. Что-то типа функции перевода текста из одной кодировки в другую: QString & Utf8toAnsi(QString &), если эта функция приватна и находится в другом классе.

Без указателя на mainwindow не обойтись. В своих программах я передаю указатель на mainwindow в каждый класс как parent QObject'a.

Код

cfrSelectForm::cfrSelectForm(QWidget *parent): QDialog(parent, Qt::Sheet)
{
    main = qobject_cast<TMainWindow *>(parent);

Автор: anatox91 10.4.2008, 15:33
ты имел ввиду что при создании объекта-потомка(т.е. в конструкторе) оставить потомку указатель на базовый объект и через него уже творить все операции?

уррЯЯЯЯ!!! получилось!!! всем большое спасибо и по +

Автор: SABROG 10.4.2008, 15:35
Нет, я не про наследование. Просто если есть главное окно, то в каждый класс, который использует компоненты главного окна надо передавать указатель в конструкторе класса или в метод.

Или вообще указатель сделать глобальным для всех объектов, где нибудь в файле с main().

Автор: Mephisto 10.4.2008, 15:55
Цитата(SABROG @  10.4.2008,  16:35 Найти цитируемый пост)
Или вообще указатель сделать глобальным для всех объектов, где нибудь в файле с main().

 smile Я ьы не делал так, если честно. Вообще не пойму зачем и кому необходимо иметь ссылку на главную форму хоть убейте меня тут   smile 

Вот что-то врое главной формы:
Код

class MainWindow:QMainWindow{
Q_OBJECT
public slots:
       void showFindDialog(){
        FindDialog *findDlg = new FindDialog;
        connect(findDlg, SIGNAL(fndNext(bool, QString)), SLOT(slotFind(bool, QString)));
        if(findDlg->exec() == QDialog::Rejected) {
                        delete findDlg;
                        }
        };
        void slotFind(bool isSensitivity, QString TextToFind){/*Код который что-то ищет*/};
};

И собсвенно форма поиска:
Код

class FindDialog:QDialog{
Q_OBJECT
public:
       FindDialog();
public slots:
       void fN(){
          /*тут отправляем сигнал*/
          emit fndNext(true, QString("Найдем тратата"));
       }
signals:
        void fndNext(bool isSensitivity, QString TextToFind);
};


Добавлено @ 15:56
за разметку извиняйте, писал в окошке форумном, тяжело форматировать. :( Могут быть и описки.

Добавлено @ 15:56
Да, и обязательно сделать QMake!

Автор: anatox91 10.4.2008, 15:57
с примером Mephisto тоже самое... всегда вызывается функция nothing() при поиске...
сделал в точности как Mephisto:
FindDialog.h:
Код

public slots:
       void fn() { 
            bool b = caseSensitivity->isChecked();
            QString str = lineFind->text();
            emit fndNext(b, str); 
            }
signals:
        void fndNext(bool, QString&);


MainWindow.cpp
Код

void MainWindow::findNext() {
     FindDialog *findDlg = new FindDialog();
     connect(findDlg, SIGNAL(fndNext(bool, QString&)), this, SLOT(slotFind(bool, QString&)));
     if(findDlg->exec() == QDialog::Rejected) {
                        delete findDlg;
                        }
}
void MainWindow::slotFind(bool isSensitivity, QString& strFind) {
     bool result;
     if(!strFind.isEmpty()) {
                            if(isSensitivity) { 
                                              result = textArea->find(strFind, QTextDocument::FindCaseSensitively);
                                              if(!result) nothing();
                                               }
                            else { 
                                 result = textArea->find(strFind);
                                 if(!result) nothing();
                                 }
                                 }
     else emptyString(); 
}


может я где-то в if-else инструкциях напутал?...  smile 

мда.. походу точно где-то в инструкциях ошибка... потому что иногда находит то что нужно...

Автор: Mephisto 10.4.2008, 16:51
У меня вот так вот работает:
Код

#include <qmainwindow.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qtextedit.h>
#include <qlayout.h>

class WorkArea:public QWidget{
Q_OBJECT
public:
  WorkArea(QWidget* parent = 0):QWidget(parent){
    pedit = new QTextEdit(this);
    QPushButton* pb = new QPushButton(this);
    QVBoxLayout* playout = new QVBoxLayout(this);
    connect(pb, SIGNAL(clicked()), SLOT(FindClicked()));
    pb->setText("Find");
    playout->addWidget(pedit);
    playout->addWidget(pb);
  }
  QTextEdit* pedit;
public slots:
  void FindClicked(){
    emit FindNext(true, QString("TT"));
  }
signals:
  void FindNext(bool isSensetive, QString TextToFind);
};

class frmMain:public QMainWindow{
Q_OBJECT
public:
  frmMain(QWidget* parent = 0, Qt::WindowFlags flags = 0):QMainWindow(parent, flags){
    pwa = new WorkArea(this);
    setCentralWidget(pwa);
    connect(pwa, SIGNAL(FindNext(bool, QString)), SLOT(Finder(bool, QString)));
    pwa->show();
  }
  WorkArea* pwa;
public slots:
  void Finder(bool isSensetive, QString TextToFind){
    if (isSensetive){
      pwa->pedit->find(TextToFind, QTextDocument::FindCaseSensitively);
    }else{
      pwa->pedit->find(TextToFind);
    }
  }
};

int main(int argc, char** argv){
  QApplication app(argc, argv);
  frmMain m;
  QObject::connect(&app, SIGNAL(lastWindowCloased()), &app, SLOT(quit()));
  m.show();
  return app.exec();
}

#include <main.moc>


anatox91, а ты курсор установил в начало текстового окошка? Потому как по умлочанию он только ищет в тексте после курсора! Чтоб в обратную сторону поискать нужно установить флаг соответствующий.

Автор: anatox91 10.4.2008, 16:56
походу нет.. smile  а как его установить в начало?

и кстати что делает вот это:
Код

#include <main.moc>

?

Автор: Mephisto 10.4.2008, 17:14
anatox91, у меня только один файл - main.cpp. Лень быол разносить по отдельным хидерам.
Чтобы скомпилилось, нужно так в конце написать. Ента сенкс Архимеду, подсказал что так мона. smile

Цитата(anatox91 @  10.4.2008,  17:56 Найти цитируемый пост)
а как его установить в начало?

Мышкой ткнуть как минимум  smile 

А вообще я бы сделал прямой поиск, в случае неудачи обратный. 
Т.е. поиск в два шага:
1) Ищешь что нужно, проверяешь резалт, если не нашел, то к шагу 2
2) Ищешь назад, проверяешь резалт, если не нашел, то таки ничего нет smile 

Автор: SABROG 10.4.2008, 17:15
Цитата

Writing Make Rules for Invoking moc
For anything but the simplest test programs, it is recommended that you automate running the moc. By adding some rules to your program's makefile, make can take care of running moc when necessary and handling the moc output.
We recommend using Trolltech's makefile generation tool, qmake, for building your makefiles. This tool generates a makefile that does all the necessary moc handling.
If you want to create your makefiles yourself, here are some tips on how to include moc handling.
For Q_OBJECT class declarations in header files, here is a useful makefile rule if you only use GNU make:
         moc_%.cpp: %.h
                 moc $(DEFINES) $(INCPATH) $< -o $@
If you want to write portably, you can use individual rules of the following form:
         moc_foo.cpp: foo.h
                 moc $(DEFINES) $(INCPATH) $< -o $@
You must also remember to add moc_foo.cpp to your SOURCES (substitute your favorite name) variable and moc_foo.o or moc_foo.obj to your OBJECTS variable.
Both examples assume that $(DEFINES) and $(INCPATH) expand to the define and include path options that are passed to the C++ compiler. These are required by moc to preprocess the source files.
While we prefer to name our C++ source files .cpp, you can use any other extension, such as .C, .cc, .CC, .cxx, and .c++, if you prefer.
For Q_OBJECT class declarations in implementation (.cpp) files, we suggest a makefile rule like this:
         foo.o: foo.moc

         foo.moc: foo.cpp
                 moc $(DEFINES) $(INCPATH) -i $< -o $@
This guarantees that make will run the moc before it compiles foo.cpp. You can then put
         #include "foo.moc"
at the end of foo.cpp, where all the classes declared in that file are fully known. 


Цитата

enum QTextDocument::FindFlag
flags QTextDocument::FindFlags
This enum describes the options available to QTextDocument's find function. The options can be OR-red together from the following list:

Constant
Value
Description
QTextDocument::FindBackward
0x00001
Search backwards instead of forwards.
QTextDocument::FindCaseSensitively
0x00002
By default find works case insensitive. Specifying this option changes the behaviour to a case sensitive find operation.
QTextDocument::FindWholeWords
0x00004
Makes find match only complete words.

The FindFlags type is a typedef for QFlags<FindFlag>. It stores an OR combination of FindFlag values.

Автор: anatox91 10.4.2008, 17:20
Mephisto, хорошо так и сделаю

SABROG, про QTextDocument::FindBackward я итак знал, а вот про мос спасибо, почитаю

еще раз всем большое спасибо!

Автор: SABROG 10.4.2008, 17:22
Цитата(anatox91 @ 10.4.2008,  17:20)
Mephisto, хорошо так и сделаю

SABROG, про QTextDocument::FindBackward я итак знал, а вот про мос спасибо, почитаю

еще раз всем большое спасибо!

Цитата

void QTextEdit::moveCursor ( QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor )
Moves the cursor by performing the given operation.
If mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over. This is the same effect that the user achieves when they hold down the Shift key and move the cursor with the cursor keys.
This function was introduced in Qt 4.2.
See also QTextCursor::movePosition().

Автор: Mephisto 10.4.2008, 17:30
SABROG, ага. Можно конечно каретку двинуть. Но мне больше по душе поиск в обоих направлениях, ибо позиция курсора не изменится если ничего не найдешь! А если двинуть курсор в начало и ничего не найдешь, то пользователю нужно будет самому найти где же он остановился. 
А вообще по хорошему направление поиска лучше задать из твоего FindDialog. 

Автор: SABROG 10.4.2008, 17:38
Цитата(Mephisto @ 10.4.2008,  17:30)
SABROG, ага. Можно конечно каретку двинуть. Но мне больше по душе поиск в обоих направлениях, ибо позиция курсора не изменится если ничего не найдешь! А если двинуть курсор в начало и ничего не найдешь, то пользователю нужно будет самому найти где же он остановился. 
А вообще по хорошему направление поиска лучше задать из твоего FindDialog.

Я потому сначала коммент про флаги направлений вставил, а потом попутно ответил на вопрос про каретку.

Автор: anatox91 10.4.2008, 19:36
а никак нельзя сначала запомнить положение курсора, а потом, после поиска, восстановить его в прежнюю позицию?

хотя не, это бред, только что сам убедился - тогда всегда ищет только первое нужное слов и при следующем поиске находит тоже самое...

Автор: Mephisto 11.4.2008, 09:17
Лучше всего из формы поиска задавать направление как по мне

Автор: anatox91 11.4.2008, 09:22
Mephisto, думаю для пользователя это будет не удобно(вручную искать в одну сторону, а потом в другую, если не нашел ничего)
в конце концов сделал вот так:
Код

void MainWindow::slotFind(bool isSensitivity, const QString& strFind) {
     bool result;
     if(!strFind.isEmpty()) {
                            if(isSensitivity) {
                                              result = textArea->find(strFind, QTextDocument::FindCaseSensitively);
                                              if(!result) result = textArea->find(strFind, QTextDocument::FindBackward | QTextDocument::FindCaseSensitively);
                                              if(!result) nothing();
                                              }
                            else {
                                 result = textArea->find(strFind);
                                 if(!result) result = textArea->find(strFind, QTextDocument::FindBackward);
                                 if(!result) nothing();
                                 }
                            }
     else emptyString(); 
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)