QPainter not drawing text properly - c++

I am not able to draw path using QPainter drawText() method
QString Path = "/home/User"
QPainter *painter
QRectF centerRect = QRectF (textX,centerY + m_bounds.height()*0.15, fm.width(Path),fm.height());
painter->drawText(centerRect,Path,QTextOption(Qt::AlignCenter | Qt::AlignHCenter ));
In windows its drawing the text but on ubunthu Linux its showing only /home

QFontMetrics fm = painter->fontMetrics();
qreal centerY = ( m_bounds.height() - fm.height() -10 )/2;
qreal textX = 8;
QRectF centerRect = QRectF (textX,centerY + m_bounds.height()*0.15, fm.width(m_folderPath),fm.height());
painter->drawText(centerRect,m_folderPath,QTextOption(Qt::AlignCenter | Qt::AlignHCenter ));
fm.width(m_folderPath)
shows differnet value for /home/user and /homeuser4

Related

How to draw triangle and rhombus shapes using QT

I need to draw triangle shape and rhombus shapes like this image.In this code which design triangle shape (figure 1) but I need to add this shape to text "TRI" . And I also need to implement this code to design rhombus shape like (figure 2). please help me to solve this.
Figure 1
void MainWindow::on_btnTri_clicked()
{
QPen redPen(Qt::black);
redPen.setWidth(2);
QRectF rect = QRectF(0, 0, 200, 200);
QPainterPath path;
path.moveTo(rect.left() + (rect.width() / 2), rect.top());
path.lineTo(rect.bottomLeft());
path.lineTo(rect.bottomRight());
path.lineTo(rect.left() + (rect.width() / 2), rect.top());
QGraphicsPathItem* item = ui->graphicsView->scene()->addPath(path, redPen);
item->setFlag(QGraphicsItem::ItemIsMovable, true);
item->setFlag(QGraphicsItem::ItemIsSelectable,true);
}
Figure 2 I use this code to design figure 2 But which cannot pass parameters to change there size,My figure 1 designed code I can able pass two parameters to QRectF(0, 0, para1, para2); this for change triangle's size.so I need to change this code to do the same thing using QPainterPath or any other way.
void MainWindow::on_btnRomb_clicked()
{
QPolygonF romb;
romb.append(QPointF(20,40));
romb.append(QPointF(0,20));
romb.append(QPointF(20,0));
romb.append(QPointF(40, 20));
QGraphicsPolygonItem* itemR = ui->graphicsView->scene()->addPolygon(romb);
itemR->setFlag(QGraphicsItem::ItemIsMovable);
}
you must use the addText() method of QPainterPath, to place it in the center you must calculate the width and height of the text for it QFontMetrics is used:
QPen redPen(Qt::black);
redPen.setWidth(2);
QRectF rect(0, 0, 200, 200);
QPainterPath path;
path.moveTo(rect.left() + (rect.width() / 2), rect.top());
path.lineTo(rect.bottomLeft());
path.lineTo(rect.bottomRight());
path.lineTo(rect.left() + (rect.width() / 2), rect.top());
path.moveTo(rect.center());
QFont font("Times", 20, QFont::Bold);
QFontMetrics fm(font);
QString text = "TRI";
QSize size = fm.size(Qt::TextSingleLine, text);
path.addText(rect.center()+ QPointF(-size.width()*0.5, size.height()*0.5), font, text);
QGraphicsPathItem *item = ui->graphicsView->scene()->addPath(path, redPen);
item->setFlag(QGraphicsItem::ItemIsMovable, true);
item->setFlag(QGraphicsItem::ItemIsSelectable,true);
For the case of the diamond you should only get the midpoints of each vertex:
QPainterPath path;
QRectF rect(0, 0 , 100, 100);
path.moveTo(rect.center().x(), rect.top());
path.lineTo(rect.right(), rect.center().y());
path.lineTo(rect.center().x(), rect.bottom());
path.lineTo(rect.left(), rect.center().y());
path.lineTo(rect.center().x(), rect.top());
QGraphicsPathItem* itemR = ui->graphicsView->scene()->addPath(path);
itemR->setFlag(QGraphicsItem::ItemIsMovable);

Qt C++ How to Scale Text to Width w/QPainter

I am looking for an effective way to use the drawText method of QPainter according to a QRect. For example if I were to have a QRect as the origin with a size of 50x50: QRect(0, 0, 50, 50); and wanted to fit text so it fits from left to right. Here are a few of the examples that I currently have, but to no extent can I get them to move fluently.
Example 1:
font.setStyleHint(QFont::AnyStyle, QFont::PreferAntialias);
painter.setRenderHint(QPainter::TextAntialiasing);
QStyleOptionGraphicsItem option;
qreal lod = option.levelOfDetailFromTransform(painter.worldTransform());
QRectF r = textRect;
QFont f = font;
qreal aspectRatio = painter.fontMetrics().lineSpacing() / painter.fontMetrics().averageCharWidth();
int pixelsize = sqrt(r.width() * r.height() / aspectRatio / (m_text.length() * 3)) * aspectRatio;
f.setPixelSize(pixelsize);
int flags = Qt::AlignCenter | Qt::TextDontClip | Qt::TextWordWrap;
if ((pixelsize * lod) < 13)
flags |= Qt::TextWrapAnywhere;
QFontMetricsF fm(f);
QRectF tbr = fm.boundingRect(r, flags, m_text);
pixelsize = f.pixelSize() * qMin(r.width() * 0.65 / tbr.width(), r.height() * 0.65 / tbr.height());
f.setPixelSize(pixelsize);
painter.setFont(f);
painter.drawText(r, flags, m_text);
However this leaves me with jittery text that is not smooth.
Example 2:
float factor = (rectangle.width() / painter.fontMetrics().width(m_text))/2;
if ((factor < 1) || (factor > 1.25))
{
font.setPointSizeF(font.pointSizeF()*factor);
painter.setFont(font);
}
QPainterPath textPath;
textPath.addText(textRect.topLeft(), font, m_text);
painter.drawPath(textPath);
Example 3:
QImage image(size(), QImage::Format_ARGB32_Premultiplied);
{
QPainter p(&image);
p.setRenderHint(QPainter::TextAntialiasing);
QFont font;
font.setFamily("Roboto medium");
font.setPointSize((double)scalar/10);
font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias);
p.setPen(Qt::black);
p.setFont(font);
p.drawText(rect(), Qt::AlignLeft , m_text);
}
painter.drawImage(rectangle, image);
Honestly I am using these method to make circular buttons that can either have text, text+icon, or just an icon. I would like them to be scalable. Any method that can do as such would be greatly appreciated. Thank you very much.

save the current items on qwidget as image

I'm trying draw some rhombuses with random colors in a QWidget. And i want to save the current QWidget as image. I use such code to do this:
QPixmap pixmap(this->size());
this->render(&pixmap);
pixmap.save("test.png");
The problem is that the render() seems to call paintEvent again, and the paintEvent will draw the rhombuses with new random colors, so that i always get a different Image saved compared to the image displayed. Can someone tell me how to save the current QWidget? Thanks in advance.
Code for drawing rhombuses:
void Dialog::paintEvent(QPaintEvent *e) {
QPainter painter(this);
QRect background(0,0,this->geometry().width(),this->geometry().height());
painter.setBrush( QBrush( Qt::white ) );
painter.setPen( Qt::NoPen );
//QBrush bbrush(Qt::black,Qt::SolidPattern);
painter.drawRect(background);
int width = this->geometry().width();
int height = this->geometry().height();
//draw rectangles
int rec_size=64;
int rows=0;
int cols=0;
rows=floor((double)height/(double)rec_size);
cols=floor((double)width/(double)rec_size);
QPointF points[4]; // QRect rec(0,0,rec_size,rec_size);
for (int i=0;i<floor(rows);i++){
for (int j=0;j<floor(cols);j++){
painter.setBrush( QBrush( colors[rand() % color_size] ) );
//QPainter painter(this);
points[0] = QPointF(rec_size*(j),rec_size*(i+0.5));
points[1] = QPointF(rec_size*(j+0.5),rec_size*(i));
points[2] = QPointF(rec_size*(j+1),rec_size*(i+0.5));
points[3] = QPointF(rec_size*(j+0.5),rec_size*(i+1));
painter.drawPolygon(points, 4);
}
}
painter.end();
}
You can have a class member variable of boolean type to check in the paintEvent whether a random color should be used. Also a variable to save the index of the last color used is necessary:
bool isRandom;
int lastColor;
The paintEvent should be like :
void Dialog::paintEvent(QPaintEvent *e) {
...
if(isRandom)
{
lastColor = rand() % color_size;
painter.setBrush( QBrush( colors[lastColor] ) );
}
else
painter.setBrush( QBrush( colors[lastColor] ) );
...
}
The variable has true when drawing the widget regularly. When you want to save it's image, assign the variable to false, save the image and assign it to true again :
isRandom = false;
QPixmap pixmap(this->size());
this->render(&pixmap);
pixmap.save("test.png");
isRandom = true;

Is it possible to make a pdf with different page size in Qt?

If the size of the page is same, then no problem, but I need the page size should be the size of Image(which is variable),
void DgJpgToPdf::convertToPdf( const QStringList& theImagePathList, const QString& theOutputFileName )
{
QPrinter printer;
printer.setOrientation(QPrinter::Portrait);
printer.setOutputFormat( QPrinter::PdfFormat );
printer.setOutputFileName( theOutputFileName );
QPainter painter;
painter.begin( &printer );
//printer.newPage();
foreach( QString fileName, theImagePathList ){
QImage imgObj( fileName );
printer.setPaperSize( QSizeF(imgObj.width(), imgObj.height()), QPrinter::DevicePixel );
painter.drawImage( 0, 0, imgObj );
printer.newPage();
}
painter.end();
}
You may wish to use QPdfWriter rather than QPrinter. You'll have to pick a PPI for the image, but if you want to save at 96 PPI, you could do something like
QPdfWriter pdfWriter(theOutputFileName);
pdfWriter.setTitle(theDocumentTitle);
pdfWriter.setCreater(yourApplicationName);
const qreal horizontalMarginMM = 2.0; // 2mm margin on each side
const qreal verticalMarginMM = 2.0;
QPagedDevice::Margins margins;
margins.left = margins.right = horizontalMarginMM;
margins.top = margins.bottom = verticalMarginMM;
pdfWriter.setMargins(margins);
bool newPage = false;
QPainter painter;
painter.begin(&pdfWriter);
foreach (const QString& fileName, theImagePathList) {
QImage imageObj(fileName);
if (newPage)
pdfWriter.newPage();
newPage = true;
qreal pageWidthMM = imgObj.width() / 96.0 * 25.4 + 2*horizontalMarginMM;
qreal pageHeightMM = imgObj.height() / 96.0 * 25.4 + 2*verticalMarginMM;
imgObj.setDotsPerMeterX(96.0 / 25.4 * 1000.0);
imgObj.setDotsPerMeterY(96.0 / 25.4 * 1000.0);
pdfWriter.setPageSizeMM(QSizeF(pageWidthMM, pageHeightMM));
painter.drawImage(0, 0, imageObj);
}
painter.end();

How to draw text surrounding circle?

Using QT, how would I go about taking user-supplied input (text) and drawing the font in such a way that it "follows" a circular path?
I really know nothing at all about QT but if I understood your question right, I found the solution with a simple google search. Code is below and here is the source link:
http://developer.qt.nokia.com/faq/answer/how_do_i_make_text_follow_the_line_curve_and_angle_of_the_qpainterpath
#include <QtGui>
#include <cmath>
class Widget : public QWidget
{
public:
Widget ()
: QWidget() { }
private:
void paintEvent ( QPaintEvent *)
{
QString hw("hello world");
int drawWidth = width() / 100;
QPainter painter(this);
QPen pen = painter.pen();
pen.setWidth(drawWidth);
pen.setColor(Qt::darkGreen);
painter.setPen(pen);
QPainterPath path(QPointF(0.0, 0.0));
QPointF c1(width()*0.2,height()*0.8);
QPointF c2(width()*0.8,height()*0.2);
path.cubicTo(c1,c2,QPointF(width(),height()));
//draw the bezier curve
painter.drawPath(path);
//Make the painter ready to draw chars
QFont font = painter.font();
font.setPixelSize(drawWidth*2);
painter.setFont(font);
pen.setColor(Qt::red);
painter.setPen(pen);
qreal percentIncrease = (qreal) 1/(hw.size()+1);
qreal percent = 0;
for ( int i = 0; i < hw.size(); i++ ) {
percent += percentIncrease;
QPointF point = path.pointAtPercent(percent);
qreal angle = path.angleAtPercent(percent);
qreal rad =qreal(0.017453292519943295769)*angle; // PI/180
// From the documentation:
/**
QTransform transforms a point in the plane to another point using the following formulas:
x' = m11*x + m21*y + dx
y' = m22*y + m12*x + dy
**/
// So the idea is to find the "new position of the character
// After we apply the world rotation.
// Then translate the painter back to the original position.
qreal sina = std::sin(rad);
qreal cosa = std::cos(rad);
// Finding the delta for the penwidth
// Don't divide by 2 because some space would be nice
qreal deltaPenX = cosa * pen.width();
qreal deltaPenY = sina * pen.width();
// Finding new posision after rotation
qreal newX = (cosa * point.x()) - (sina * point.y());
qreal newY = (cosa * point.y()) + (sina * point.x());
// Getting the delta distance
qreal deltaX = newX - point.x();
qreal deltaY = newY - point.y();
// Applying the rotation with the translation.
QTransform tran(cosa,sina,-sina,cosa,-deltaX + deltaPenX,-deltaY - deltaPenY);
painter.setWorldTransform(tran);
painter.drawText(point,QString(hw[i]));
}
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Widget widget;
widget.show();
return app.exec();
}