LINUX.ORG.RU

QCustomPlot и функция paintEvent

 , , ,


0

1

В проекте рисую графики с помощью QCustomPlot. Графики рисуются, я счастлив. Захотелось мне нарисовать отдельный прямоугольник не связанный с QCustomPlot. Раньше делал так: 1) В классе QMainWindow делал переопределение для paintEvent:

protected:
    void paintEvent(QPaintEvent*) override;

2) Потом в mainwindow.cpp делал определение функции paintEvent:

void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter;
QBrush   brush;
QColor   color(0, 0, 255);
 
painter.begin(m_mainWidget);
 
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); // Обрисовка.
 
color.setRgb(100, 0, 0); // Настройка цвета.
brush.setColor(color);                   // Применение настроек цвета.
 
brush.setStyle(Qt::SolidPattern);        // Настройка стиля заливки.
painter.setBrush(brush);                 // Заливка.
painter.drawRect(QRect(m_mainWidget->width()-100, m_mainWidget->height()-100, 200, 200)); // Прорисовка прямоугольника.
 
painter.end();
}

3) Где надо, например по нажатию кнопки, вызывал функцию repaint() и всё рисовалося.

Но тут не заработало. Отладчик просто не переходит в мой paintEvent. Покопал в QCustomPlot, оказалось в библиотеке тоже используется paintEvent. И когда я вызываю в своей программе repaint(), то происходит переход в paintEvent, который переопределён в QCustomPlot, а не в мой. Я понимаю, что можно запихнуть своё рисование в библиотеку, но не хочется пачкать библиотечный файл. Помогите убогому сделать правильно.


Ответ на: комментарий от m0rph

Я конечно читал об этом, но как применить прочитанное не знаю. Полагаю Ваш следующий комментарий будет таким «читай книжки». p.s.: теги нубский вопрос и чайник стоят не спроста.

RedOrm
() автор топика

Насколько я понимаю, у тебя фокус внутри QCustomPlot, а перегружаешь ты класс MainWindow. По идее тебе нужно отнаследоваться от какого-то библиотечного класса в QCustomPlot и там перегрузить нужный тебе класс и его метод paintEvent(). И при этом не забыть из перегруженного метода вызвать потом оригинальный код paintEvent() в библиотеке: к примеру, так: QCustomPlot::paintEvent(), либо по указателю parent.

EXL ★★★★★
()
Ответ на: комментарий от EXL

QCustomPlot - название библиотеки, с помощью которой я рисую графики. В проекте она представлена парой файлов .cpp и .h. Для рисования собственно графиков, я использую класс QCustomPlot из этой библиотеки. В моём проекте, в хидере главного окна, в классе MainWindow я объявляю объект:

private:
    QWidget     *m_mainWidget  = nullptr; // Указатель на виджет который будет назначен центральным.
    QCustomPlot *m_graphWidget = nullptr; // Указатель на виджет с графикой.

Затем, в конструкторе MainWindow, я инициализирую:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      m_mainWidget(new QWidget(this)),
      m_graphWidget(new QCustomPlot(m_mainWidget)), // тут указал предком центральный виджет а не this.

Не претендую на правильность изложенного и буду счастлив если подскажите как правильно.

Теперь по Вашему комментарию. Функция:

  virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
объявлена собственно в классе QCustomPlot и переопределяется в файле .cpp:
void QCustomPlot::paintEvent(QPaintEvent *event)

Ваша фраза:

По идее тебе нужно отнаследоваться от какого-то библиотечного класса в QCustomPlot и там перегрузить нужный тебе класс и его метод paintEvent().

Получается я должон создать ещё один объект, который будет наследником класса QCustomPlot, объявить в этом классе метод paintEvent и переопределить его так как уже мне надо. Так?

Ваша фраза:

И при этом не забыть из перегруженного метода вызвать потом оригинальный код paintEvent() в библиотеке: к примеру, так: QCustomPlot::paintEvent(), либо по указателю parent.

Не понял. В текущем проекте я его вообще не вызываю. Вызов берёт на себя библиотека. В новом проекте я хочу нарисовать дополнительно прямоугольник, рисовать его, как я думал, буду в paintEvent(), а вызов этой функции буду делать функцией repaint().

RedOrm
() автор топика
Ответ на: комментарий от RedOrm

Если я правильно понял вопрос, тебе нужно создать свой класс, наследовав его от QCustomPlot и переопределить в нем виртуальную функцию paintEvent(). Внутри этой функции надо сначала вызвать QCustomPlot::paintEvent(), а потом отрисовать поверх то, что требуется (например прямоугольник). Ну а потом использовать свой класс вместо QCustomPlot.

m0rph ★★★★★
()
Последнее исправление: m0rph (всего исправлений: 2)
Ответ на: комментарий от m0rph

Правильно ли я понимаю? Мне не нужно в описании класса MainWindow объявлять объект класса QCustomPlot *. Нужно сделать отдельный класс наследуемый от QCustomPlot и уже этот класс будет и рисовать график и прямоугольник. Так?

RedOrm
() автор топика
Ответ на: комментарий от m0rph

Да, только совсем не обязательно иметь указатель именно на объект базового класса (QCustomPlot). Можно использовать указатель на объект своего класса-наследника.

Если человек новичек, то ему желательно уложить в голове вот это:

Понимание наследования и механизма виртуальных методов в C++.

Xintrea ★★★★★
()

Захотелось мне нарисовать отдельный прямоугольник не связанный с QCustomPlot.

Немного зайду с другой стороны. Я бы использовал Qwt вместо QCustomPlot, она зарекомендовала себя идеально.

Непонятно, про какой прямоугольник (и где это он отдельно?) идет речь.

Не знаю как в QCustomPlot, но в Qwt для рисования любых элементов на «канве графика» (квадратов, маркеров, загогулек и много чего еще), используются объекты, отнаследованные от неких Items (по сути в Qwt - любые элементы, это Items, кроме осей).

Так вот, чтобы нарисовать что угодно, достаточно создать новый объект - MyRect, унаследованный от Item, и переопределить его метод paint() (или как то так, я не помню), реализовать отрисовку чего угодно, а потом «приаттачить» этот MyRect на «канву графика».

Но если тебе нужно рисовать не на графике - то наследуешья от виджета/фрейма, переопределяешь его метод paint(), реализуешь в нем рисование кандибобриков, а готовый виджет добавляешь в лейаут.

т.е. непонятно, зачем тебе какие-то квадратики рисовать где - то самому, да и кроме того, переопределять для этого гравный paint() от MainWindow - непрвильно ну вот вообще.

kuzulis ★★
()