LINUX.ORG.RU

Qt: QPainter ругается, чтобы его вызывали из paintEvent(), хотя оттуда его и вызывают.


0

1
class QTextEditEnter : public QTextEdit
{
	Q_OBJECT
public:
	QTextEditEnter( QWidget *_parent ) : QTextEdit(_parent)
	{
		this -> setFrameStyle( QFrame::Sunken ); // Sunken!
	}

protected:
	virtual void keyPressEvent(QKeyEvent * event);
	virtual void paintEvent(QPaintEvent *_event)
	{
		QTextEdit::paintEvent( _event ); // это можно убрать - проблема не исчезает.
		QPainter pnt(this);
		pnt.setPen( QColor( 0, 0, 0, 0xff ));
		pnt.drawRect( 0, 0, width(), height());
	}

	signals:
		void signalPressEnter();
};

Понадобился специальный QTextEdit, который посылает событие, когда в нём жмут Enter. Чё-то paintEvent() какой-то странный. Я пытаюсь дорисовать рюшечки к стандартному виду, а он ругается. Стандартный вид я рисую, дёргая базовый paintEvent(), но QPainter pnt(this) и далее - не прокатывает:

QPainter::begin: Widget painting can only begin as a result of a paintEvent // чё за хрень? Ты и так вызван из paintEvent!!!111
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active

Не пойму, как это возможно...

★☆

Последнее исправление: kiverattes (всего исправлений: 1)
Ответ на: комментарий от alex_custov

Это даёт «Segmentation fault» (-;

У меня во всех самодельных виджетах используется такая конструкция: QPainter (this) и всё хорошо.

kiverattes ★☆
() автор топика
Ответ на: комментарий от alex_custov

В этом проекте практически один этот класс, больше ничего хитрого нет. Объект существует всё время жизни приложения, его дёргают много раз. Вот только с this он ругается, а с viewport() валится. Что ещё пробовать - ХЗ.

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

вынести его в отдельный проект и попробовать.

class QTextEditEnter : public QTextEdit
{
Q_OBJECT

public:
    QTextEditEnter( QWidget *_parent = 0) : QTextEdit(_parent)
    {
        setFrameStyle(QFrame::Sunken);
    }

protected:
    virtual void paintEvent(QPaintEvent *_event)
    {
        QTextEdit::paintEvent(_event);

        QPainter pnt(viewport());

        pnt.setPen(Qt::red);
        pnt.drawRect(20, 20, width()-40, height()-40); // small bug
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QTextEditEnter *e = new QTextEditEnter;
    e->show();

    return app.exec();
}
alex_custov ★★★★★
()
Последнее исправление: alex_custov (всего исправлений: 1)
Ответ на: комментарий от NikolaSh

Намёк не дошёл. Сообщение об ошибке меня больше всего удивляет - «paintEvent() должен вызываться в результате события...» - он у меня и так в результате события вызывается.

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

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

У меня он нормально работает на двух системах

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

Интересно, в чём могут быть отличия. Вот я вынесу в отдельный проект - а оно заработает. Всё равно будут те же вопросы - почему так.

kiverattes ★☆
() автор топика
Ответ на: комментарий от alex_custov

Интереснее более общее понимание - от чего это может происходить? Какие опции доступны юному программисту, чтобы устроить, чтобы ТАК БЫЛО? Что означает «вызывайте меня по paintEvent», когда он так и вызывается? Что это может означать? Явно, в обход event-loop, метод нигде не вызывается - точно.

kiverattes ★☆
() автор топика
Ответ на: комментарий от alex_custov

Вынес в отдельный проект - не работает.

xx@(none) ~ $ moc -v
Qt Meta Object Compiler version 63 (Qt 4.8.2)
xx@(none) ~ $ uname -a
Linux (none) 3.4.9-gentoo #8 SMP Tue Nov 6 10:09:47 MSK 2012 x86_64 Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz GenuineIntel GNU/Linux
xx@(none) ~ $ 

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

почему-то я сразу подумал о генте :) Я проверил даже на Windows с custom сборкой Qt - работает. Пробуй на другой системе.

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

Секрет разгадан!

// В конструктор QPainter передаем this.
// Вызываем базовый paintEvent в начале.
// РЕЗУЛЬТАТ: QPainter::begin: Widget painting can only begin as a result of a paintEvent
	virtual void paintEvent(QPaintEvent *_event)
	{
		QTextEdit::paintEvent( _event );
		QPainter pnt( this );
		pnt.setPen( QColor( 0, 0, 0, 0xff ));
		pnt.drawRect( 0, 0, width()-1, height()-1);
	}

// В конструктор QPainter передаём viewport() либо this.
// Вызываем базовый paintEvent ПОСРЕДИ использования нового QPainter.
// РЕЗУЛЬТАТ: Segmentation fault.
	virtual void paintEvent(QPaintEvent *_event)
	{
		QPainter pnt( viewport() );
		pnt.setPen( QColor( 0, 0, 0, 0xff ));
		QTextEdit::paintEvent( _event ); // WRONG PLACE!!!
		pnt.drawRect( 0, 0, width()-1, height()-1);
	}

// В конструктор QPainter передаём именно viewport().
// Вызываем базовый paintEvent в начале.
// РЕЗУЛЬТАТ: ура, всё работает! Видим обычный виджет + наша чёрная рамочка.
	virtual void paintEvent(QPaintEvent *_event)
	{
		QTextEdit::paintEvent( _event );
		QPainter pnt( viewport() );
		pnt.setPen( QColor( 0, 0, 0, 0xff ));
		pnt.drawRect( 0, 0, width()-1, height()-1);
	}
kiverattes ★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.