Проблема с рисованием поверх виджета в Qt

Я не имел, в общем-то, опыта разработки на Qt, поэтому чтобы ничего нечаянно не испортить начал с проекта-примера с сайта Qt. Вот сам проект Image Viewer.

Техническая суть проекта: класс ImageViewer населдует QMainWindow, устанавливает своим «центральным виджетом» зону прокрутки QScrollArea, в которой находится QLabel с картинкой.

Исходный код есть на той же страничке в разделе «Files» сверху.

Проблема заключается в следующем: я хотел выполнять некое рисование поверх отображаемой картинки, но для примера сведём задачу к тому, чтобы просто нарисовать линию.

Вооружившись гуглом, я пришёл к такому варианту:

в файле imageviewer.h подключаем библотеку для рисования:
#include <QPainter>


и добавляем обработчик события отрисовки в класс:
protected:
    void paintEvent(QPaintEvent *);


В imageviewer.cpp опишем этот обработчик:
void ImageViewer::paintEvent(QPaintEvent * e)
{
    QPainter p(this);

    p.drawLine(0,0,100,100);
} 


Ожидалось, что в левом верхнем углу появится линия, но… нет.

Мне кажется, что проблема в том, что scrollArea перекрывает линию, поэтому для эксперимента я закомментировал строку
setCentralWidget(scrollArea);

в методе ImageViewer::ImageViewer(). Линия появилась, но картинка, понятно, перестала отображаться.

Пытался рисовать на scrollArea, так же безуспешно (картинка есть, линии нет):
void ImageViewer::paintEvent(QPaintEvent * e)
{
    QPainter p(scrollArea);

    p.drawLine(0,0,100,100);
}

Этот код выдавал в консоль QCreator-а сообщения вида
QPainter::begin: Paint device returned engine == 0, type: 1


Гугление привело к идее рисовать на scrollArea->viewport(), не помогло.

Внимание, вопрос: как сделать то же самое, но правильно?)
  • Вопрос задан
  • 14293 просмотра
Решения вопроса 1
Mezomish
@Mezomish
Унаследуйтесь от QLabel, переопределите его paintEvent, а в нём сначала вызовите QLabel::paintEvent(event);, после чего добавьте ваше собственное рисование.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Mezomish
@Mezomish
Собсна, код:

#include <QMainWindow>
#include <QScrollArea>
#include <QLabel>
#include <QApplication>
#include <QPainter>

class MyLabel : public QLabel {
protected:
	virtual void paintEvent(QPaintEvent* e) {
		QLabel::paintEvent(e);
		
		QPainter p(this);
		
		p.setPen(Qt::green);
		p.drawLine(0, 0, 100, 100);
	}
};

class ImageView : public QMainWindow {
public:
	
	ImageView() : QMainWindow() {
		QScrollArea* scr = new QScrollArea();
		setCentralWidget( scr );
		
		QLabel* label = new MyLabel();
		label->setPixmap(QPixmap("./moon_from_andrey.jpg"));
		scr->setWidget(label);
	}
};


int main(int argc, char* argv[]) {
	QApplication app(argc, argv);
	
	ImageView view;
	view.setGeometry(100, 100, 500, 400);
	view.show();
	
	return app.exec();
}



Результат:

Ответ написан
kulinich
@kulinich
С++ программист
Я как-то рисовал на кнопке так:
void PaintButtonUp::paintEvent(QPaintEvent *event) { QPushButton::paintEvent(event); QPainter paint(this); static const QPointF points[3] = { QPointF(3.0, 25.0), QPointF(10.0, 15.0), QPointF(17.0, 25.0), }; paint.setPen(QPen(Qt::darkGray, 2, Qt::SolidLine, Qt::RoundCap)); paint.setRenderHint(QPainter::Antialiasing, true); paint.setBrush(QBrush(Qt::gray, Qt::SolidPattern)); paint.drawPolygon(points, 3); }

Т.е. сначала вызывался стандартный метод
QPushButton::paintEvent(event);
а затем уже я отрисовывал на кнопке то, что мне было нужно.

Не знаю поможет это Вам или нет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы