Добавление кастомных виджетов в 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 шт):

Автор решения: mur

Убрать ошибку компиляции помог совет @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 в режиме дизайна наглядно показывает структуру возможностей и иногда предлагает хорошие варианты по структурированию названий. Это помогает на этапе освоения.
  • Многое (хоть и не всё) интуитивно понятно.
  • Удобно оформлять всплывающие подсказки и контекстную справку по элементам интерфейса.

Недостатки:

  1. Есть ограничения, когда то, что легко делается через код на C++, внезапно оказывается недоступно через дизайнер, например:
  • добавление на ToolBar произвольных виджетов;
  • настройка строки состояния - добавление на неё хоть каких-нибудь виджетов;
  • триггерным actions (кнопкам на ToolBar и пунктам меню) нельзя назначить начальное состояние - это надо делать через код;
  • нет возможности применить QActionGroup чтобы получить радиокнопки в меню и на ToolBar. Попадалось что вроде можно через ручную правку xml, но это жуткое извращение. Мой пример радиокнопок через C++ код;
  • ограничены и неудобны настройки connect;
  • при добавлении в action горячих клавиш нет возможности выбрать их из списка стандартных комбинаций - только ввести с клавиатуры. Пример на C++: currentAct → setShortcuts(QKeySequence::New);. А значит надо либо их помнить, либо куда то ещё лезть за напоминанием (в C++ коде этот список легко доступен по F2 или Ctrl + мышь на QKeySequence::New).

Из-за этого не получается полностью перенести описание UI в дизайн и приходится городить комбинацию. Попадалось мнение что ограничения сделаны специально и тот же ToolBar прекрасен именно своей ограниченностью (только кнопки), но нет - выпадающие списки, поля редактирования и т.п. на ToolBar не блажь, а насущная необходимость. Да и при чём тут ограничения на наполнение строки состояния.

  1. Список connect сигналов и слотов:
  • не структурирован и, думаю, в большом проекте он будет из-за этого не читаем;
  • автоматически не подхватывает сигналы и слоты из кода кастомных виджетов - их надо дополнительно указывать через интерфейс Дизайнера;
  • неудобен для заполнения - накидать connect-ы в коде быстрее и проще;
  • жестко ограничивает выбор объектов, например, попробуйте перенести в дизайнер connect( ui→action_AboutQT, &QAction::triggered, this, &QApplication::aboutQt ); Придется либо создавать промежуточный слот, либо комбинировать дизайн с C++ кодом.

Из-за всего этого настройки connect, на мой взгляд, лучше перенести в код.

  1. В текстовом варианте xml формат просто ужасен по сравнению с C++. Чрезмерно захламлён обязательными лишними словами и совершенно не нагляден. Кроме того, если, преодолев сопротивление QT Creator, перейти к ручному редактированию xml, то QT Creator потом может отказаться открывать его визуально. Обмануть QT Creator в этом вопросе можно, но реально работать с xml всё равно мазохизм.
  2. Не все моменты интуитивно понятны.
  3. Простые текстовые диалоги делаются просто ужасно. В коде они пишутся тривиально и красиво оформляются через html теги прямо в строке диалога. А в дизайне это геморрой.

Выводы:

  • В дизайнере удобно делать только общий макет. Пытаться делать в нём весь UI явно не стоит.
  • В программировании удобство чтения программ должно иметь приоритет над удобством их написания. В этом плане превратить часть кода в визуальный дизайн выглядит привлекательно - он нагляден и структурирован. Но всё что касается взаимодействия элементов формы с программой и между собой и обхода ограничений в функционале дизайнера, имхо, лучше делать через C++ код (ни в коем случае не через абсолютно нечитаемый xml самой формы). Т.е. имеет смысл делать UI как комбинацию дизайна с C++ кодом.
→ Ссылка
Автор решения: Swift - Friday Pie

Qt Designer поддерживает установку плагинов, обрабатывающих пользовательские визуальные элемента. В действительности, в примерах есть даже готовый проект, который можно пощупать - AnalogClockPlugin. Это поможет правильно подключить все слоты, свойства, добавить необходимые сторонние заголовки в исходный код (хотя очень рекомендуется использовать PIMPL), позволит элементу правильно отображаться и работать в режиме предпросмотра, и т.д.

Сразу скажу о граблях на которые мы наступали - на Windows версии работают только плагины, построенные в release-конфигурации (с релизной библиотекой времени исполнения).

→ Ссылка