Добавление кастомных виджетов в QT design (через QT Creator)
Сделал по этой инструкции, только у меня class GraphicsView : public QGraphicsView.
При компиляции получаю ошибку в автоматически генерируемом ui_mainwindow.h что мой #include "graphicsview.h" не найден.
И в дизайнере не появляются слоты моего GraphicsView.
Хотя в проекте graphicsview.h есть и если делать через код, а не через дизайнер то всё работает.
Пробовал в QT Creator 17 и 12 версии.
Что не так?
Здесь:
автоматически генерируемый ui_mainwindow.h
По ссылке минимальный проект, воспроизводящий ошибку.
По комментарию @Kromster добавляю код: graphicsview.h
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include "mainwindow.h"
#include <QGraphicsView>
#include <QObject>
class MainWindow;
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
explicit GraphicsView(QWidget* parent = nullptr);
explicit GraphicsView(MainWindow * mainWindow = nullptr);
public slots:
void zoomAll();
private:
MainWindow *mainWindow;
};
#endif // GRAPHICSVIEW_H
и graphicsview.cpp
#include "graphicsview.h"
GraphicsView::GraphicsView(MainWindow *mainWindow) {
this->mainWindow = mainWindow;
};
GraphicsView::GraphicsView(QWidget* parent) {
};
void GraphicsView::zoomAll(){
qDebug() << "Слот zoomAll сработал";
};
Остальные файлы проекта созданы QT Creator и я их не менял. Только мой код при подключении GraphicsView через C++ код работает. Значит ошибка где-то в недрах проекта и поэтому найти её можно только скачав проект.
Ответы (2 шт):
Убрать ошибку компиляции помог совет @retmas:
Добавьте в CMakeLists.txt
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR})
Дополнительные нюансы:
- Для работы через дизайнер действительно нужен конструктор
GraphicsView(QWidget* parent = nullptr), спасибо @FrozenM, (безexplicitтоже всё работает), потому что там родителем без вариантов назначаетсяcentralwidget. Это при работе через код удобнее напрямую назначать родителемMainWindow. - Чтобы дизайнер начал видеть слоты кастомного
GraphicsViewнедостаточно прописать их в коде, надо ещё добавить их в дизайнере: правая кнопка мыши ->
- Убрать рамку вокруг
GraphicsViewполучилось только через код в MainWindow:setCentralWidget(ui->graphicsView);. Как сделать это через дизайнер я не нашёл. ПреобразоватьcentralwidgetвGraphicsViewу меня получилось, но без доступа к слотамGraphicsView, а это не вариант.
По ссылке исправленный проект в котором через Дизайнер настроено взаимодействие сигналов и слотов между GraphicsView и MainWindow.
PS: Я пока осваиваю QT, поэтому пробую разные возможности. Поделюсь свежими впечатлениями от QT Creator в режиме дизайнера:
Преимущества :
- Сразу есть визуальная составляющая. В чём то это упрощает проектирование (хотя это не так уж однозначно).
- Сложные диалоги c дочерними виджетами удобно делать в дизайне (хотя с простыми всё наоборот - см. ниже).
- Можно убрать из программы много (но не весь) кода описывающего UI и сосредоточиться на логике самой программы.
- При желании можно заглянуть и в текстовый xml формат описания UI.
- Экономится время на тестовых компиляциях, когда нужно просто посмотреть как сейчас выглядит UI.
- QT Creator в режиме дизайна наглядно показывает структуру возможностей и иногда предлагает хорошие варианты по структурированию названий. Это помогает на этапе освоения.
- Многое (хоть и не всё) интуитивно понятно.
- Удобно оформлять всплывающие подсказки и контекстную справку по элементам интерфейса.
Недостатки:
- Есть ограничения, когда то, что легко делается через код на C++, внезапно оказывается недоступно через дизайнер, например:
- добавление на ToolBar произвольных виджетов;
- настройка строки состояния - добавление на неё хоть каких-нибудь виджетов;
- триггерным actions (кнопкам на ToolBar и пунктам меню) нельзя назначить начальное состояние - это надо делать через код;
- нет возможности применить QActionGroup чтобы получить радиокнопки в меню и на ToolBar. Попадалось что вроде можно через ручную правку xml, но это жуткое извращение. Мой пример радиокнопок через C++ код;
- ограничены и неудобны настройки
connect; - при добавлении в action горячих клавиш нет возможности выбрать их из списка стандартных комбинаций - только ввести с клавиатуры. Пример на C++:
currentAct → setShortcuts(QKeySequence::New);. А значит надо либо их помнить, либо куда то ещё лезть за напоминанием (в C++ коде этот список легко доступен по F2 или Ctrl + мышь наQKeySequence::New).
Из-за этого не получается полностью перенести описание UI в дизайн и приходится городить комбинацию. Попадалось мнение что ограничения сделаны специально и тот же ToolBar прекрасен именно своей ограниченностью (только кнопки), но нет - выпадающие списки, поля редактирования и т.п. на ToolBar не блажь, а насущная необходимость. Да и при чём тут ограничения на наполнение строки состояния.
- Список
connectсигналов и слотов:
- не структурирован и, думаю, в большом проекте он будет из-за этого не читаем;
- автоматически не подхватывает сигналы и слоты из кода кастомных виджетов - их надо дополнительно указывать через интерфейс Дизайнера;
- неудобен для заполнения - накидать connect-ы в коде быстрее и проще;
- жестко ограничивает выбор объектов, например, попробуйте перенести в дизайнер
connect( ui→action_AboutQT, &QAction::triggered, this, &QApplication::aboutQt); Придется либо создавать промежуточный слот, либо комбинировать дизайн с C++ кодом.
Из-за всего этого настройки connect, на мой взгляд, лучше перенести в код.
- В текстовом варианте xml формат просто ужасен по сравнению с C++. Чрезмерно захламлён обязательными лишними словами и совершенно не нагляден. Кроме того, если, преодолев сопротивление QT Creator, перейти к ручному редактированию xml, то QT Creator потом может отказаться открывать его визуально. Обмануть QT Creator в этом вопросе можно, но реально работать с xml всё равно мазохизм.
- Не все моменты интуитивно понятны.
- Простые текстовые диалоги делаются просто ужасно. В коде они пишутся тривиально и красиво оформляются через html теги прямо в строке диалога. А в дизайне это геморрой.
Выводы:
- В дизайнере удобно делать только общий макет. Пытаться делать в нём весь UI явно не стоит.
- В программировании удобство чтения программ должно иметь приоритет над удобством их написания. В этом плане превратить часть кода в визуальный дизайн выглядит привлекательно - он нагляден и структурирован. Но всё что касается взаимодействия элементов формы с программой и между собой и обхода ограничений в функционале дизайнера, имхо, лучше делать через C++ код (ни в коем случае не через абсолютно нечитаемый xml самой формы). Т.е. имеет смысл делать UI как комбинацию дизайна с C++ кодом.
Qt Designer поддерживает установку плагинов, обрабатывающих пользовательские визуальные элемента. В действительности, в примерах есть даже готовый проект, который можно пощупать - AnalogClockPlugin. Это поможет правильно подключить все слоты, свойства, добавить необходимые сторонние заголовки в исходный код (хотя очень рекомендуется использовать PIMPL), позволит элементу правильно отображаться и работать в режиме предпросмотра, и т.д.
Сразу скажу о граблях на которые мы наступали - на Windows версии работают только плагины, построенные в release-конфигурации (с релизной библиотекой времени исполнения).