АД
Алексей Девяткин30 августа 2016 г. 17:23

Знакомство с QPainter

paintEngine, QPainter, Qt

Доброго времени суток!
Заранее прошу простить мою некомпетентность в программировании.
Изучая урок, столкнулся с проблемой:при попытке нарисовать внутри QTabWidget линию с помощью QPainter, сталкиваюсь с тем, что ничего не отрисовывается, а в лог выскакивает сообщение
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active

Прошу помочь с решением данной задачи.
Самым великолепным будет проект с решением, т.к. мне намного проще разобраться с готовым решением, чем пытаться что-то синтезировать без наставника =)
.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QMainWindow>
#include <QWidget>
#include <QPainter>
 
namespace Ui {
class Widget;
}
 
class Widget : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
protected:
    /* Определяем виртуальный метод родительского класса
     * для отрисовки содержимого виджета
     * */
    void paintEvent(QPaintEvent *event);
 
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::Widget *ui;
};
 
#endif // WIDGET_H

.cpp

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(ui->tab); // Создаём объект отрисовщика
 
    painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap));
    painter.drawEllipse(100, 50, 150, 150);
}
 
void Widget::on_pushButton_clicked()
{
    repaint();
}

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

5
Evgenii Legotckoi
  • 30 августа 2016 г. 18:09

Добрый день!

Здесь ошибка в том, что метод paintEvent должен вызываться в классе объекта,
который будет выступать в качестве ui->tab. В уроке передаётся указатель this, который указывается на сам виджет окна. То есть необходимо сделать класс, наследованный от QWidget. В нём уже переопределить метод paintEvent(QPaintEvent * event), и установить экземпляр данного класса в качестве вкладки в QTabWidget. В коде это будет выглядеть следующим образом:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include "formtab.h"
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::MainWindow *ui;
    FormTab *m_formTab;
};
 
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_formTab = new FormTab(this);
    ui->tabWidget->addTab(m_formTab, "Paint Tab");
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
 
void MainWindow::on_pushButton_clicked()
{
    m_formTab->repaint();
}

formtab.h

#ifndef FORMTAB_H
#define FORMTAB_H
 
#include <QWidget>
#include <QPaintEvent>
 
namespace Ui {
class FormTab;
}
 
class FormTab : public QWidget
{
    Q_OBJECT
 
public:
    explicit FormTab(QWidget *parent = 0);
    ~FormTab();
 
protected:
    void paintEvent(QPaintEvent *event);
 
private:
    Ui::FormTab *ui;
};
 
#endif // FORMTAB_H

formtab.cpp

#include "formtab.h"
#include "ui_formtab.h"
 
#include <QPainter>
 
FormTab::FormTab(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormTab)
{
    ui->setupUi(this);
}
 
FormTab::~FormTab()
{
    delete ui;
}
 
void FormTab::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
 
    painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap));
    painter.drawEllipse(100, 50, 150, 150);
}

А вообще класс QPainter имеет некоторые ограничения при использовании. Обычно экземпляр QPainter без проблем работает с тем объектом, который является для него родителем, то есть если в экземпляр QPainter передан указатель на тот объект, в котором объявлен QPainter, то всё работает, как правило. В противном случае вылазит сообщение об ошибке, как у Вас.

paintercheck.zip

    АД
    • 30 августа 2016 г. 18:24
    Благодарю за развёрнутый ответ.
    А как возможно передать массив в QPainter для отрисовки для данной задачи?
    Предполагается формировать массив в MainWindow.
      Evgenii Legotckoi
      • 30 августа 2016 г. 18:41

      В FormTab написать метод, который принимает массив. Передать этот массив в экземпляр FormTab, допустим в слоте обработчике нажатия QPushButton, который у Вас уже написан. Ну и присвоить этот массив той переменной, которая будет содержать данный массив в FormTab. А потом уже вызвать repaint(). Логику отрисовки с этим массивом организовать в переопределённом методе paintEvent(QPaintEvent *event).

      Но я бы порекомендовал использовать сразу контейнер, например, QVector, если требуется передать ряд значений для отрисовки ломанной линии, к примеру. Ну и использовать QPainterPath для отрисовки этой линии. Вот в этом уроке в методе paint() сделана отрисовка и через линии и через QPainterPath.

        АД
        • 30 августа 2016 г. 20:03
        • Ответ был помечен как решение.

        Евгений, спасибо большое за консультацию.
        Получилось сделать как хотелось.
        Скидываю проект (вдруг кому-то пригодиться).

        painter.rar

          СГ
          • 24 сентября 2020 г. 12:49

          Здравствуйте! В ваших проектах (paintercheck.zip, painter.rar) отсутствует "ui_formtab.h". Без него не компилируется проект. Я компилирую в Qt Creator 4.3.1 по ubuntu 16.04. Как бы получить этот файл?

            Комментарии

            Только авторизованные пользователи могут публиковать комментарии.
            Пожалуйста, авторизуйтесь или зарегистрируйтесь
            Ua

            Qt - Тест 001. Сигналы и слоты

            • Результат:84баллов,
            • Очки рейтинга4
            Ua

            Qt - Тест 001. Сигналы и слоты

            • Результат:42баллов,
            • Очки рейтинга-8
            ОК

            Qt - Тест 001. Сигналы и слоты

            • Результат:47баллов,
            • Очки рейтинга-6
            Последние комментарии
            ИМ
            Игорь Максимов22 ноября 2024 г. 21:51
            Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
            Evgenii Legotckoi
            Evgenii Legotckoi31 октября 2024 г. 23:37
            Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
            A
            ALO1ZE19 октября 2024 г. 17:19
            Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
            ИМ
            Игорь Максимов5 октября 2024 г. 16:51
            Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
            d
            dblas55 июля 2024 г. 20:02
            QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
            Сейчас обсуждают на форуме
            f
            firstlunoxod15 февраля 2025 г. 13:46
            Рисование на QGraphicsScene при зажатой кнопке мыши Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
            Дмитрий
            Дмитрий3 февраля 2025 г. 16:24
            Создание deb-пакета. Как создать ярлык на рабочем столе после установки собственного deb-пакета? Всем привет. Сделал свой deb-пакет с программой. Всё устанавливается и работает. Ставлю по пути /usr/bin/my_application. Как для пользователя при установке пакета сразу создать ярлык на раб…
            NW
            Nayo Wai30 января 2025 г. 19:22
            не запускается компьютер!!! Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
            n
            nkly3 января 2025 г. 12:52
            Нужно запретить перемещение только некоторых итемов, остальные перемещать можно. Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
            M
            Marsel17 августа 2023 г. 0:26
            OAuth2.0 через VK, получение email Спасибо большое за помощь и простите за то что отнял время своей невнимательностью.

            Следите за нами в социальных сетях