Draw text in QGLWidget when using raw OpenGL - qt

I am writing Qt app that wraps an external 3D engine.I use QGLWidget to encapsulate the engine API.I don't use any Qt GL API methods though I do create GL context using Qt API:
QGLFormat format;
format.setProfile(QGLFormat::CompatibilityProfile);
format.setVersion(4,2);
format.setDoubleBuffer(true);
format.setSwapInterval(1);
Now,I was searching for a way to draw text in the viewport and found Qt's rendeText().
I have tried to use it but no text is begin drawn.
That is how I do it:
qglColor(Qt::black);
this->renderText(50, 50, "Some text");
What do I miss here?
Btw, my depth buffer is off.

I use the following method to draw text in my OpenGL widgets:
void myGL_Widget::OGL_Draw_Text(QString text,float x,float y, float z, float red, float green, float blue)
{
glPushMatrix();
glColor3f(red, green, blue);
renderText(x, y, z, text);
glPopMatrix();
}

Related

How to use Qt QColormap in code?

I want to achieve something like this .
I looked into the Qt QColormap but I did'nt get enough information to code it. If someone knows how to do this. Please share code snippet.
It's more question about color models then Qt really but basically you are trying to make a full circle around edge of HSL color model while keeping saturation.
To produce something like that in Qt you will utilize gradient brush; since we want continuous blend I used QLinearGradient. If you look at the color wheel above you will notice that red color is at 0 degrees, green is at 120 degrees and blue is at 240 degrees. QLinearGradient works with range from 0-1 so this will transform to 0, 1/3, 2/3 respectively. We also need need to add final stop which will complete the gradient back to red color.
I added bit of alpha channel to keep the color tone down so you can experiment with that; final code will look something like this:
class ColorScale : public QWidget {
Q_OBJECT
public:
using QWidget::QWidget;
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
painter.setOpacity(0.9);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
QLinearGradient gradient(0, 0, 0, height());
QGradientStops stops;
stops << QGradientStop(0, Qt::red);
stops << QGradientStop(1.0/3, Qt::blue);
stops << QGradientStop(2.0/3, Qt::green);
stops << QGradientStop(1, Qt::red);
gradient.setStops(stops);
painter.fillRect(rect(), gradient);
}
};
And it produces this:
You can add labels by calling QPainter::drawText.

QT change QImage alpha

I need to change the alpha of a QImage I have so it blends with the other QImages behind and infront of it. This needs to be toggled quickly on and off.
Previously I've had to recreate every single image and give them new colors with just a different alpha value. But now I want to retain that same original image instead of redrawing and painting it.
I'm trying to do it like this now:
QImage image;
unsigned int rgb;
for(int y=0;y<image.height();y++){
for(int x=0;x<image.width();x++){
rgb=image.pixel(x,y);
image.setPixel(x,y,qRgba(qRed(rgb),qGreen(rgb),qRed(rgb),120));
}
}
I'm getting some fairly unpredictable behavior. When I toggle the image sometimes I lose colors or the alpha isn't changed. And if the alpha did get changed when I toggle back (I hardcode the alpha 255 elsewhere instead of 120) it doesn't go back to normal.
This doesn't seem like the right way to do this anyways, it shouldn't be this difficult. It seems like there should be a single function call on an image to change the alpha but I haven't found one yet.
If you are using the QImage in QGraphicsView or in some other QWidget, you should look into this QGraphicsEffect:
http://qt-project.org/doc/qt-4.8/qgraphicsopacityeffect.html
http://doc-snapshot.qt-project.org/4.8/qwidget.html#setGraphicsEffect
http://doc-snapshot.qt-project.org/4.8/qgraphicsitem.html#setGraphicsEffect
If you are using a QLabel, I would try this out:
#include <QLabel>
#include <QPainter>
class TransparentQLabel : public QLabel
{
Q_OBJECT
public:
explicit TransparentQLabel() : QLabel() {}
~TransparentQLabel(){}
void setOpacity(const qreal & val)
{
if (this->pixmap() == null || this->pixmap().isNull())
return;
QPixmap result(this->pixmap()->size());
result.fill(Qt::transparent);
QPainter painter;
painter.begin(&result);
painter.setOpacity(val);
painter.drawPixmap(0, 0, *(this->pixmap()));
painter.end();
QLabel::setPixmap(result);
}
};
This next bit is only slightly related to your question, but it is nice to know. If you are layering outside of your QApplication onto the operating system, you need some things like this:
this->setWindowFlags( Qt::WindowStaysOnTopHint |
Qt::FramelessWindowHint | Qt::Tool);
this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setAttribute (Qt::WA_TransparentForMouseEvents, true);
Here is an example of this stuff in action:
http://qt-project.org/wiki/QSplashScreen-Replacement-for-Semitransparent-Images
Hope that helps.

Qt, QTextEdit, how to turn all the content in QTextEdit into a image.

I want to creat a image that contain the QTextEdit.
And I write the following code to create the image.
QSize s = textEdit->frameSize();
QPixmap p(s);
textEdit->render(&p);
p.save("textContent.png", "PNG");
But it can not contain the invisible contents.(while the contents is too long in QTextEdit)
I wander if there is a way to create a image which contain all the content in QTextEidt. And how.
Thanks.
i think, you can do it like via QTextDocument * QTextEdit::document () to receive QTextDocument * of your QTextEdit, and then draw it to QImage via void QTextDocument::drawContents ( QPainter * p, const QRectF & rect = QRectF() )
It draws the content of the document with painter p, clipped to rect. If rect is a null rectangle (default) then the document is painted unclipped.
check man here - http://harmattan-dev.nokia.com/docs/library/html/qt4/qtextdocument.html#drawContents
Or - the other way - take all the text from TextEdit via toPlainHtml() or toPlainText() - what's more suitable for your needs and draw it to QImage via QPainter's method QPainter::DrawText()

Qt : draw triangle image

I need to do something similar to QPainter::drawImage, but drawing a triangle part of the given picture (into a triangular region of my widget) instead of working with rectangles.
Any idea how I could do that, besides painfully trying to redraw every pixel?
Thanks for your insights!
If it is feasible for you to use a QPixmap instead of a QImage, you can set a bitmap mask for the QPixmap which defines which of the pixels are shown and which are transparent:
myPixmap->setMask(myTriangleMask);
painter->drawPixmap(myPixmap);
Here is another solution based on QImage:
MaskWidget::MaskWidget(QWidget* parent) : QWidget(parent) {
img = QImage("Sample.jpg"); // The image to paint
mask = QImage("Mask.png"); // An indexed 2-bit colormap image
QPainter imgPainter(&img);
imgPainter.drawImage(0, 0, mask); // Paint the mask onto the image
}
void MaskWidget::paintEvent ( QPaintEvent * event ) {
QPainter painter(this);
painter.drawImage(10, 10, img);
}
Mask.png is an image file with the same size as Sample.jpg. It contains an alpha channel to support transparency. You can create this file easily with The GIMP, for example. I added an alpha channel, changed all areas I want to have painted to transparent and all other areas to white. To reduce the size, I finally converted it to an indexed 2-bit image.
You could even create the mask image programmatically with Qt, if you need your triangle be computed based on various parameters.

Qt text with shadow

I see this in other applications, even though the appearance is ever so slightly, the effect is a much high contrast -> better readability.
The tabs on the left in Qt Designer for example, or the tabs at the top in Adobe Photoshop: the text has some sort of shadow, only ever 1 pixel surrounding the text with a contrasting colour.
Is there a simple way to do this with Qt? Or a more complex one?
Thank you.
Maybe QGraphicsDropShadowEffect?
There are a couple ways of achieving this effect, but conceptually you need to look at it as being two text layers with a slight offset.
I have done this before by re-implementing the paintEvent() method of a QWidget and drawing the text layers myself. Or you can reimplement the drawItemText() method of a custom QStyle. But basically that is how it is done.
Here is the way I did text shadow on all buttons with Qt5. I am not sure if this is possible with Qt4.
class MyProxyStyle : public QProxyStyle
{
public:
void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole /* = QPalette::NoRole */) const
{
if (textRole == QPalette::ButtonText && dynamic_cast<QAbstractButton*>(painter->device()))
{
QPalette palShadow(pal);
palShadow.setColor(QPalette::ButtonText, QColor(0, 0, 0, 100));
QProxyStyle::drawItemText(painter, rect.adjusted(1, 1, 1, 1), flags, palShadow, enabled, text, textRole);
}
QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
}
};
...somewhere in main()
QApplication a;
a.setStyle(new MyProxyStyle);
If you remove the QAbstractButton dynamic_cast the menu titles will also be shadowed which is not always desirable.

Resources