Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Сигналы и собственный слот


Автор: theworldcreator 8.11.2008, 14:22
Ubuntu 8.10
g++ 4.3

Первая попытка создать собственную графическую программу. Язык C++
Создал набросок в "QT Дизайнере" - главное окно, несколько пунктов меню, в главном окне tab виджет, в единственном табе plain text editor.
Пытаюсь повесить на сигнал(нажатие кнопки "new") свою функцию, которая должна создавать новый таб. Функция точно работает. Сознательно закомментировал "Q_OBJECT" в MainWindow.h
main.cpp
Код

#include "MainWindow.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow *MainWindowObj = new MainWindow;
    return app.exec();
}


MainWindow.h
Код

#include "ui_main.h"

class MainWindow: public Ui::MainWindow
{
//Q_OBJECT
public:
    MainWindow(void);
public slots : 
    void CreateTab();
};


MainWindow.cpp
Код

#include "MainWindow.h"


MainWindow::MainWindow()
{
    QMainWindow *MainWindow = new QMainWindow;
    setupUi(MainWindow);
    QObject::connect(actionNew, SIGNAL(activated()), MainWindow, SLOT(CreateTab()));
    retranslateUi(MainWindow);
    MainWindow->show();
}

void MainWindow::CreateTab()
{
    QWidget *tab_2;
    QPlainTextEdit *plainTextEdit_2;
    tab_2 = new QWidget();
    tab_2->setObjectName(QString::fromUtf8("tab_2"));
    plainTextEdit_2 = new QPlainTextEdit(tab_2);
    plainTextEdit_2->setObjectName(QString::fromUtf8("plainTextEdit_2"));
    plainTextEdit_2->setGeometry(QRect(10, 0, 1271, 641));
    plainTextEdit_2->setTabChangesFocus(false);
    tabWidget->addTab(tab_2, QString());
    tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("MainWindow", "Tab 2", 0, QApplication::UnicodeUTF8));    
}



Компилю, компилятор вроде не ругается:
Код

alex@alex-laptop:~/qt/medit$ qmake -project;
alex@alex-laptop:~/qt/medit$ qmake medit.pro;
alex@alex-laptop:~/qt/medit$ make
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o MainWindow.o MainWindow.cpp
g++ -Wl,--no-undefined -o medit main.o MainWindow.o    -L/usr/lib -lQtGui -lQtCore -lpthread



Запускаю - тут как раз проявляется ошибка:
Код

alex@alex-laptop:~/qt/medit$ ./medit
Object::connect: No such slot QMainWindow::CreateTab()
Object::connect:  (sender name:   'actionNew')
Object::connect:  (receiver name: 'MainWindow')


Встроенные сигналы/слоты работают(для теста вешал на ту же кнопку "new" функцию "cut")

При этом я сознательно закомментировал "Q_OBJECT", ибо при его включение компилятор говорит следующее:
Код

alex@alex-laptop:~/qt/medit$ qmake -project;
alex@alex-laptop:~/qt/medit$ qmake medit.pro;
alex@alex-laptop:~/qt/medit$ make
/usr/bin/moc-qt4 -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. MainWindow.h -o moc_MainWindow.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o moc_MainWindow.o moc_MainWindow.cpp
moc_MainWindow.cpp:41: ошибка: ‘staticMetaObject’ не является элементом ‘Ui::MainWindow’
moc_MainWindow.cpp: In member function ‘virtual void* MainWindow::qt_metacast(const char*)’:
moc_MainWindow.cpp:56: ошибка: ‘qt_metacast’ не является элементом ‘MainWindow::qt_metacast(const char*)::QMocSuperClass’
moc_MainWindow.cpp: In member function ‘virtual int MainWindow::qt_metacall(QMetaObject::Call, int, void**)’:
moc_MainWindow.cpp:62: ошибка: ‘qt_metacall’ не является элементом ‘MainWindow::qt_metacall(QMetaObject::Call, int, void**)::QMocSuperClass’
make: *** [moc_MainWindow.o] Ошибка 1


Поискал в интернете, ошибка "No such slot" появлялась у очень большого количества людей, но все они опечатывались в название ыункции и передавали функции connect имя несуществующей функции. У меня все проверил раз пятнадцать - функция написанна правильно.


Заранее Очень благодарен.

Автор: mes 8.11.2008, 14:35
Цитата(theworldcreator @  8.11.2008,  14:22 Найти цитируемый пост)
При этом я сознательно закомментировал "Q_OBJECT", ибо при его включение компилятор говорит следующее:

Вы пошли не потому пути. Без макроса Q_OBJECT компилятор (а точнее moc) не будет добавлять реализацию для подключения ваших слотов.

Компилятор же ругается на Q_OBJECT по той же самой причине, не отработал moc, и не создал реазлизацию для введенных виртуальных функций.
А не отработал скорее всего потому, что у Вас вся реализация хранится в хидере. Добавьте в проект MainWindow.cpp и попробуйте перекомпилить 

P.S. а вобще то для вопросов по QT есть свой раздел 

Автор: theworldcreator 8.11.2008, 14:50
Извиняюсь, ввел в вас в заблуждение неправильным сообщением об ошибке в предыдущем посте(ошибка при использование Q_OBJECT), компилил без обновления make-файла, пост уже поправил. Но в целом это ничего не меняет, команда
Код

QObject::connect(actionNew, SIGNAL(activated()), plainTextEdit, SLOT(paste()));

успешно привязывает кнопку "new" к действию "вставить в текстовое поле" БЕЗ включения Q_OBJECT.

Цитата

P.S. а вобще то для вопросов по QT есть свой раздел 

Извиняюсь, не увидел видимо.

Автор: mes 8.11.2008, 15:59
Цитата(theworldcreator @  8.11.2008,  14:50 Найти цитируемый пост)
успешно привязывает кнопку "new" к действию "вставить в текстовое поле" БЕЗ включения Q_OBJECT.

И что эта фраза меняет ? Вы слот чей берете ? у PlainTextEdita. Или Ввы утверждаете, что его класс откомпилен без Q_OBJECTa ?` smile 
макрос Q_OBJECT нужен не для connectа (старого) слота, а для реализации нового слота.

Цитата(theworldcreator @  8.11.2008,  14:22 Найти цитируемый пост)

//Q_OBJECT
public slots : 
    void CreateTab();

указание public slots: работает только в комплекте с Q_OBJECT.

Добавлено @ 15:59
а Вы это уже пробовали ? (естественно с расскоментированным Q_OBJECT)
Цитата(mes @  8.11.2008,  14:35 Найти цитируемый пост)
Добавьте в проект MainWindow.cpp и попробуйте перекомпилить 


Автор: theworldcreator 8.11.2008, 22:03
Извини, не понял что перенести в MainWindow.cpp

Автор: mes 8.11.2008, 22:46
Цитата(theworldcreator @  8.11.2008,  22:03 Найти цитируемый пост)
Извини, не понял что перенести в MainWindow.cpp 

sorry, не заметил что 
Цитата(theworldcreator @  8.11.2008,  14:50 Найти цитируемый пост)
пост уже поправил. 



Цитата(theworldcreator @  8.11.2008,  14:22 Найти цитируемый пост)
moc_MainWindow.cpp:41: ошибка: ‘staticMetaObject’ не является элементом ‘Ui::MainWindow’

потому что у Вас MainWindow не наследник QObject, a 
Цитата(theworldcreator @  8.11.2008,  14:22 Найти цитируемый пост)
class MainWindow: public Ui::MainWindow

наследуйтесь от QMainWindow, а Ui::MainWindow сделайте полем.

Автор: theworldcreator 8.11.2008, 22:56
Страшно извиняюсь, но я новичек в С++ и не знаю что такое поле(хотя догадываюсь)) и, главное, не знаю как его реализовать.

Автор: mes 8.11.2008, 23:00
Цитата(theworldcreator @  8.11.2008,  22:56 Найти цитируемый пост)
Страшно извиняюсь, но я новичек в С++ и не знаю что такое поле(хотя догадываюсь)) и, главное, не знаю как его реализовать. 

дело в названии, полем принято называть дата-элемент класса. В общем Вам нужно так :
Код

class MainWindow: public QMainWindow
{
//Q_OBJECT
  ...
 private:
   Ui::MainWindow  m_ui; // 
...

Автор: theworldcreator 8.11.2008, 23:16
Код

MainWindow.cpp:9: ошибка: ‘setupUi’ не является элементом ‘MainWindow’


функция, созданная в Ui::MainWindow, почему-то недоступна

Добавлено через 14 минут и 58 секунд
Нашел в книжке прекрасный пример, страшно похожий на мою ситуацию:

MainWindow.h
Код

#ifndef MainWindowH
#define MainWindowH

#include <QtGui>
#include "ui_main.h"

class MainWindow: public QMainWindow, public Ui::MainWindow
{
Q_OBJECT
 public:
    MainWindow(void);
 private slots : 
    void CreateTab();
};

#endif


MainWindow.cpp
Код

#include <QtGui>
#include "MainWindow.h"


MainWindow::MainWindow()
{
    setupUi(this);
    connect(actionNew, SIGNAL(activated()), this, SLOT(CreateTab()));
}

void MainWindow::CreateTab()
{
    QWidget *tab_2;
    QPlainTextEdit *plainTextEdit_2;
    tab_2 = new QWidget();
    tab_2->setObjectName(QString::fromUtf8("tab_2"));
    plainTextEdit_2 = new QPlainTextEdit(tab_2);
    plainTextEdit_2->setObjectName(QString::fromUtf8("plainTextEdit_2"));
    plainTextEdit_2->setGeometry(QRect(10, 0, 1271, 641));
    plainTextEdit_2->setTabChangesFocus(false);
    tabWidget->addTab(tab_2, QString());
    tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("MainWindow", "Tab 2", 0, QApplication::UnicodeUTF8));
}


main.cpp
Код

#include "MainWindow.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow *MainWindowObj = new MainWindow;
    MainWindowObj->show();
    return app.exec();
}


Огромное спасибо, mes

Автор: mes 8.11.2008, 23:33
Цитата(theworldcreator @  8.11.2008,  23:16 Найти цитируемый пост)
функция, созданная в Ui::MainWindow, почему-то недоступна 

ну так она та часть класса Ui::MainWindow , а не MainWindow .  
делайте m_ui.setupUi () , где m_ui имя поля класса  Ui::MainWindow. 
доступ к полю открыт только для методов MainWindow, так как поле приватное.

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