Qt - QPainter.DrawText doesnt draw the text - c++

I'm creating an analog clock in Qt-Creator 5, now I want to draw the numbers to the screen, but it doesn't work?
painter.drawText(QPoint(50, 50), "12");
I absolutely don't see the point why it doesn't work. when I replace this line in my code with a .drawEllipse, it works fine. So the position/color can't be the problem, except drawText would not use the setBrush() color.
Anyone knows how to correctly draw text on the screen with the QPainter?
//previous code only draws blue ellipses with white background
QColor secondColor(240,0,0);
painter.setPen(Qt::NoPen);
painter.setBrush(secondColor);
painter.save();
QFont font=painter.font() ;
font.setPointSize(18);
painter.setFont(font);
painter.drawText(QPoint(50, 50), "12");
because it's at the end of paintEvent it can't be overdrawn

setting the pen-style over
painter.setPen(colorStyle);
solved the problem. thanks to Mat

Related

Smoothing an inclined line

I can't find a proper way to draw a smooth inclined line without having it over-pixelated in Qt with the QPainterPath object.
Note that I know it doesn't make sense to draw the path in the paintEvent function, I put it there for sake of simplicity. I'm trying to draw the line directly in the central widget.
Hereafter is a snippet of my code:
void MyObject::paintEvent(QPaintEvent *)
{
QPainterPath aPath;
aPath.moveTo(40.0, 60.0); //random values to try
aPath.lineTo(254, 354.0);
QPainter painter(this);
painter.setPen(QPen(QColor(20, 20, 200), 10, Qt::SolidLine));
painter.drawPath(aPath);
}
And here is the result I get:
It's awful! The only beautiful lines I can draw are horizontal, vertical or 45° inclined ones...
If you are looking for drawing quality, the Qt documentation provides an illustrative example (5.X version) of the use of its render quality flags. Generally, you can use the flags specified here (5.X version), and set them using the QPainter::setRenderHint() (5.X version) function. See if you are able to achieve the desired quality using those methods. For your code, you'd be looking for something like
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
painter.setPen(QPen(QColor(20, 20, 200), 10, Qt::SolidLine));
painter.drawPath(aPath);

Is there a way to invert the QWidget::setMask() function or achieve similar effect?

I'm trying to "cut a hole" in my widgets background so that it's at a specif location totally transparent and that you you can see what is behind it. The problem is that the neither the size or the location of this "hole" are fixed, so it can basically be anywhere on the widget so that's why I can't use mask images.
There is the function setMask(QRegion) but the effect that I require would need to be inverted, so basically instead of only drawing the masked region it should be drawing all that is not covered by the mask.
Is there a way to achieve such effect?
Ok, with #ilotXXI help I've figured out a way which seems to be better then setting the widget mask:
if(mouseIsDown) // Only draw empty rect when mouse down
painter.setClipRegion(rectRegion.subtracted(emptyRegion));
painter.setBrush(QColor(0, 0, 0, 150)); //color for not-empty area
painter.drawRect(this->geometry()); // draw not-empty area
This seems to work much faster then setting the mask and I have no lag anymore. #ilotXXI thanks for the help :)
Try this:
const QRegion emptyRegion = <create your region>;
const QRegion rectRegion(QRect(QPoint(), widget->size()));
widget->setMask(rectRegion.subtracted(emptyRegion));

Multiple wxGLCanvas with OpenGL-wxPaintDC drawing combination

I have an application with two classes extending wxGLCanvas and one extending wxWindow. They implement 3 types of possible visualization of the user objects. Only one of them is displayed at the same time. The two wxGLCanvas contain a combination of an OpenGL scene plus some text superposed using wxPaintDC. The wxWindow draws everything using wxBufferedPaintDC.
Problem 1: In some machines, when exchanging from one wxGLCanvas to the other one, during the first rendering of the scene a background image is displayed just until the first rendered image appears. This background image I found out that comes from the wxGLCanvas background.
Problem 2:In the same machines where problem 1 appears, when using the function wxClientDC.Blit, instead of taking the OpenGL scene with the superposed text it is taking the wxGLCanvas background image (same as problem 1) with the superposed text; so it is taking the canvas context excluding the OpenGL scene. In the other machines the result of the screenshot is correct.
INFO: When I select the wxWindow view, where all is drawn using wxBufferedPaintDC, the background image of both, problem 1 and 2, is updated to the frame displayed by the wxWindow. If I now switch between wxGLCanvases I will see the "flash" of the wxWindow view.
Code to take screenshot (Inside class extending wxGLCanvas):
wxClientDC lv_contexteVue(this);
int lv_largeurVue;
int lv_hauteurVue;
lv_contexteVue.GetSize(&lv_largeurVue,&lv_hauteurVue);
wxBitmap lv_vue(lv_largeurVue,lv_hauteurVue);
wxMemoryDC lv_contexteAux;
lv_contexteAux.SelectObject(lv_vue);
lv_contexteAux.Blit(0,0,lv_largeurVue,lv_hauteurVue,&lv_contexteVue,0,0);
lv_vue.SaveFile(wxString(er_cheminSauvegarde.c_str(),wxConvLibc,er_cheminSauvegarde.size()),wxBITMAP_TYPE_BMP);
lv_contexteAux.SelectObject(wxNullBitmap);
Code to display scene OpenGL followed by the overlayed text (Inside class extending wxGLCanvas):
wxPaintDC dc(this);
//dc.Clear();
dc.SetBackground(*wxBLACK);
dc.SetBackgroundMode(wxSOLID);
dc.SetTextBackground(*wxBLACK);
dc.SetTextForeground(*wxWHITE);
SetCurrent(mv_contexte);
if (!mv_estInitialise)
{
initialiser();
mv_estInitialise = true;
}
Evenement lv_demandeDessin(DEMANDE_AFFICHAGE_2DPLUS);
mp_controleur->traiterEvenement(lv_demandeDessin);
SwapBuffers();
//dc.ClearCache();
wxColour lv_couleurEspaceLibre = *wxWHITE;
dc.SetBrush(wxBrush(lv_couleurEspaceLibre));
dc.SetPen(wxPen(lv_couleurEspaceLibre, 1));
//Overlay Text
wxSize screenSize = this->GetSize();
//dc.SetTextForeground(wxColour(240, 240, 240, 255));
wxFont font(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false);
dc.SetFont(font);
//dc.SetTextBackground(wxColour(0, 0, 0, 200));
string formated = ConstantesATLAS::FILIGRANE_PRE+Constantes::VERSION+Constantes::FILIGRANE_POS;
wxString mystring = wxString::FromAscii(formated.c_str());
//dc.DrawText(mystring,5,screenSize.GetY()-20);
dc.DrawText(mystring,5,5);
Answer from wxWidgets forum to the same question posted here, all credit for them :)
https://forums.wxwidgets.org/viewtopic.php?f=1&t=40288&e=0
Summary: do not mix OpenGL and wxPaintDC. To take screenshot of openGL with overlayed text there are two good posibilities:
1-Put the overlayed text with OpenGL, e.g. a superposed orthographic projection. Then take screenshot using the function glReadPixels().
2-If text is overlayed using the DC, to take screenshot, first ask OpenGL to return all the viewport in an array. Transform this array to wxImage, resuperpose the text in the image the same way it is superposed in the repaint event, use the dc.Blit function to copy the image.

Qt Pixmap Manipulation

I'm attempting to create a process manager based on QPixmaps. These pixmaps are updated via a timer callback at 20Hz, so it appears like they're spinning.
Below is a screenshot of my current window.
The pixmap is a 2D array with [20][14] elements. 20 is the amount of time slices, 14 is the process status indicator. I know, there are only 13 displayed here on the screen.
I'm currently using the painter object and composition modes to add QImages together with the following code:
QImage textImage(mapIcon.size(), QImage::Format_ARGB32);
QImage resultImage(mapIcon.size(), QImage::Format_ARGB32);
QPainter textPainter(&textImage);
textPainter.setCompositionMode(QPainter::CompositionMode_Source);
textPainter.fillRect(mapIcon.rect(), Qt::black);
textPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
textPainter.setFont(QFont("Arial", 8, QFont::Bold));
textPainter.setPen(QPen(Qt::white));
textPainter.drawText(QRectF(0, 0, mapIcon.width(), mapIcon.height()),
Qt::AlignCenter, name);
textPainter.end();
QPainter resultPainter(&resultImage);
resultPainter.setCompositionMode(QPainter::CompositionMode_Source);
resultPainter.drawImage(0, 0, mapIcon);
resultPainter.setCompositionMode(QPainter::CompositionMode_Exclusion);
resultPainter.drawImage(0, 0, textImage);
resultPainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
resultPainter.setRenderHint(QPainter::HighQualityAntialiasing, true);
runnerIcons[x][y] = QPixmap::fromImage(resultImage);
My question is this: I don't want the inverted color scheme seen on the green labels, I want that color black. The white on black is ok, but the magenta isn't my favorite.
Is this possible in Qt? Or maybe ya'll have some suggestions to alternative solutions?
Thanks in advance.
There are a couple things you can do. You might check out the QPainter::setCompositionMode (mode) method. Maybe one of the other composition modes would be useful to you? Particularly QPainter::CompositionMode_Exclusion or QPainter::RasterOp_SourceXorDestination.
You could also use a complimentary color for the text. Magenta (blue+red) is opposite green on the color wheel. If you made the text magenta, it would probably show up well against both black and green. (I'm not saying it will look great - just that it will show up well.) Or maybe you could make the text 50% gray so that there is contrast in the luminance as well as in the color?
Also, you only have 13 icons, not 14. Not sure if it makes any difference.

Colored border of the transparent color key around text written on the transparent window

I created a Transparent Layered window with a color key that I use to make the window transparent.
So far it works all fine.
Writing text on it - using GDI+ - works, too...
The problem I encounter is, that the text has a thin border of the colorkey-color around the letters...
What I do in the WM_PAINT is:
1. Clear the drawing area Graphics::Clear(ColorKey);
2. Draw the text on it.
Screenshot of what i mean: http://imageshack.us/photo/my-images/709/cutp.jpg/
Anyone knows about how to avoid this?
Try calling Graphics::SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit).