PDA

View Full Version : text orientation in qt



DEEPADEV
31st May 2012, 12:12
Hi All,
i want to rotate the text in the manner shown in the attachement
i.e if the text is "abcd"
i should rotate the each character of text by 90 degree in such a way that after i set the ttext in rotated manner , therafter whatever new character appear, they should appear in the same manner of 90 degree
Please help regarding it.

Thanks in advance:)

wysota
31st May 2012, 13:09
What exactly is the problem? What have you already tried to solve the problem?

DEEPADEV
1st June 2012, 04:46
i tried working with the following code

void TextOrientation::paintEvent(QPaintEvent* event )
{
QString str1 = textObject->toPlainText();
QByteArray ba = str1.toLocal8Bit();
char *c_str2 = ba.data();
painter.setFont(QFont("Arial", 20));
drawRotatedText(&painter, 90,120,100, tr(c_str2));
}

/************for drawing rotated text************/

void TextOrientation::drawRotatedText(QPainter *painter, float degrees, int x, int y, const QString &text)
{
painter->save();
painter->translate(x, y);
painter->rotate(degrees);
// painter->scale(70,70);
painter->drawText(0,0, text);
painter->restore();
}


but this will rotate only the text present currently in the textobject .
but i want even rotation whatever new characters are being typed, they should also appear in the same rotated manner.
Can you help me

d_stranz
1st June 2012, 05:38
Then you need to implement keyPress() and other key-related event handlers on your TextOrientation object so that they add or remove characters to the textObject instance as the user types them. As the textObject is changed, you must call your TextOrientation object's update() method to cause a paint event.

DEEPADEV
1st June 2012, 07:25
i have the code for textbox object to get updated while letters are being typed in a normal state. but once i call the paintevent , it will draw the text contained within the textbox in a specified degree. and it is not at all being included within textbox.it is getting drawn not within the textbox instead in the co-ordinates specified by me. I think i need to have some property of textbox such that once this property is set, the text typed within it will appear in the same degree rotated(ex:as once we set the italic property of font the characters within textbox and also newly typed will get displayed in italic)

wysota
1st June 2012, 09:18
Don't draw the whole text at once but instead draw each character one by one under the previous one.

DEEPADEV
1st June 2012, 12:57
can you please help me with some code as i am really new to Qt and am trying to crack it.
I don't understand how to merge the drawn text to the textbox so that it is visible within the textbox.and not in the position specified by me while drawing it

d_stranz
1st June 2012, 16:41
@Deepadev: You have confused me. I think what you are trying to say is that you have a QLineEdit or QTextEdit that the user is typing into, and you want to display the contents of the editor somewhere else (on your TextOrientation widget, I guess). Is that correct? The user is not typing directly into your TextOrientation widget, but into some other editor (QlineEdit or QTextEdit)?

If that is the case then you should implement a slot in the TextOrientation class that handles the textChanged() signal (from QTextEdit) or textChanged(const QString &) signal (from QLineEdit), whichever one you are using to get the text from the user. In that slot, you simply call update(), which will result in a repaint of the rotated text.



// TextOrientation.h:

class TextOrientation : public QWidget
{
Q_OBJECT;

public:
// usual constructor / destructor stuff

protected slots:

void onTextChanged( const QString & text ); // assumes "textObject" is a QLineEdit

// ...
};

// TextOrientation.cpp

TextOrientation::TextOrientation( QWidget * parent )
: QWidget( parent )
{
setupUi( this );

// ... other constructor stuff as needed

connect( textObject, SIGNAL( textChanged( const QString & ) ), this, SLOT( onTextChanged( const QString & ) ) );
}

void TextOrientation::onTextChanged( const QString & )
{

// Ignore the new text, since TextOrientation::paintEvent() retrieves it from textObject
// and just call update to schedule a repaint
update();
}

wysota
1st June 2012, 17:12
I think he doesn't know how to paint the rotated text.

d_stranz
1st June 2012, 17:24
I think he doesn't know how to paint the rotated text.

Could be. It isn't at all clear to me where the problem lies, and as usual there isn't enough source code to figure out what or where.

DEEPADEV
4th June 2012, 13:38
i tried code something like this.
i am a novice to Qt. so as per my knowledge , i tried something like this.
header file
-------------

class Dialog : public QDialog
{
Q_OBJECT
int fSize;
int flag1,flag2,flag;


public:
Dialog(QWidget *parent = 0);
void drawRotatedText(QPainter *painter, float degrees, int x, int y, const QString &text);
QRadioButton *rBtn1,*rBtn2,*rBtn;
QTextEdit *textObject;
void stcpy(char *src,char* dest);
void stcpy1(char *src,char* dest);
void click(QPainter *painter);


~Dialog();
protected:
virtual void paintEvent(QPaintEvent *e);


public slots:
void ischecked1();
void ischecked2();
void ischecked3();

};

source file
----------

#include "dialog.h"

Dialog::Dialog(QWidget *parent) : QDialog(parent)
{
fSize = 72;
/**********flags for preventing crash**************/
flag = 0;
flag1 = 1;
flag2 = 0;
setGeometry(0,0,400,400);
textObject = new QTextEdit(this);
textObject->setGeometry(10,10,300,150);
textObject->setText("deepa");
textObject->setVisible(true);
rBtn =new QRadioButton(this);
rBtn->setVisible(true);
rBtn->setGeometry(10,190,50,30);
rBtn->setChecked(true);
rBtn1 =new QRadioButton(this);
rBtn1->setVisible(true);
rBtn1->setGeometry(90,190,50,30);
rBtn2 =new QRadioButton(this);
rBtn2->setVisible(true);
rBtn2->setGeometry(170,190,50,30);

connect(rBtn,SIGNAL(clicked()),this,SLOT(ischecked 1()));
connect(rBtn1,SIGNAL(clicked()),this,SLOT(ischecke d2()));
connect(rBtn2,SIGNAL(clicked()),this,SLOT(ischecke d3()));
this->setAttribute( Qt::WA_TranslucentBackground, true );
}

void Dialog::ischecked1()
{
if(flag1 == 0)
{
rBtn->setCheckable(true);
QString str1 = textObject->toPlainText();
QByteArray ba = str1.toLocal8Bit();
char *src = ba.data();
char *dest = (char* )malloc(10) ;
memset(dest,0,10);
stcpy1(src,dest);
QString string = QString::fromLocal8Bit(dest);
textObject->setText(string);
flag1 = 1;
flag2 = 0;
flag = 0;
}

}


/*************This needs to be rotated using paintevent************/
void Dialog::ischecked2()
{
rBtn1->setCheckable(true);
flag = 1;
repaint();
}

void Dialog::ischecked3()
{
if (flag2 == 0)
{
rBtn2->setCheckable(true);
QString str1 = textObject->toPlainText();
QByteArray ba = str1.toLocal8Bit();
char *src = ba.data();
//textObject->setFont(QFont("Arial", 10));
char *dest = (char* )malloc(10) ;
memset(dest,0,10);
stcpy(src,dest);
QString string = QString::fromLocal8Bit(dest);
textObject->setText(string);
flag2 = 1;
flag1 = 0;
flag = 0;
}

}

/***********copying a string with \n to display in vertical order***********/
void Dialog::stcpy(char *src,char* dest)
{
int i,len = 0,j=0;
len=strlen(src);
qDebug()<<"Length ="<<len;
for(i=0;i<len;i++)
{
*(dest+j++) = *(src+i);
*(dest+j++) = '\n';
}
*(dest+j) = '\0';
}

/***********copying a string with \n to display in horizontal order***********/
void Dialog::stcpy1(char *src,char* dest)
{
int i,len = 0,j=0;
len=strlen(src);
qDebug()<<"Length ="<<len;
for(i=0;i<len;i=i+2)
{
*(dest+j) = *(src+i);
++j;
}
*(dest+j) = '\0';
}


void Dialog::paintEvent(QPaintEvent* e )
{
QPainter painter(this);
painter.setBackgroundMode(Qt::TransparentMode);
painter.setBrush(QColor(255,215,100));
painter.setFont(QFont("Arial", 10));
QRectF rectangle1(0, 180, 350, 40);
painter.drawRect(rectangle1);
painter.drawText(28,199,tr("abc"));
drawRotatedText(&painter, 90,120,196, tr("abc"));
painter.drawLine(195,197,195,195);
painter.drawText(200,200,tr("a"));
painter.drawText(200,210,tr("b"));



/*********functionality of second radiobutton**********/

QString str1 = textObject->toPlainText();
QByteArray ba = str1.toLocal8Bit();
char *c_str2 = ba.data();
if(flag == 1)
{
painter.setPen(QColor("red"));
painter.setFont(QFont("Arial", 20));
drawRotatedText(&painter, 90,50,300, tr(c_str2));
flag = 0;
}

}

/************for drawing rotated text************/

void Dialog::drawRotatedText(QPainter *painter, float degrees, int x, int y, const QString &text)
{
painter->save();
painter->translate(x, y);
painter->rotate(degrees);
// painter->scale(70,70);
painter->drawText(0,0, text);
painter->restore();
}




Dialog::~Dialog()
{

}


But this is not working properly as i need to change the contents of textedit after this property is set so that the characters typed thereafter should appear in the same rotated format.
Hope this will make u clear about my problem

wysota
4th June 2012, 16:34
What is the problem? Apart the fact you are not using layouts, of course.

DEEPADEV
5th June 2012, 05:06
i want the text to appear within the textbox and not in the position specified by me while drawing.
This is not the proper method of rotating as it won't be applied to the text later typed within textbox.
I told earlier also, that it should work like property so that once the property is set to 90 degree, the characters typed thereafter within textbox should be typed in 90 dgree angle only. For example: once we set italic property the text later typed appears in italic only within the textbox.

is there any method to do as such?
THANKS IN ADVANCE

wysota
5th June 2012, 09:18
I told earlier also, that it should work like property so that once the property is set to 90 degree, the characters typed thereafter within textbox should be typed in 90 dgree angle only. For example: once we set italic property the text later typed appears in italic only within the textbox.
And the text typed earlier?

DEEPADEV
5th June 2012, 10:00
that tooooooo should appear rotated

amleto
5th June 2012, 10:53
that's different to how e.g. bold and italic work

wysota
5th June 2012, 12:36
Does this do what you want?


#include <QtGui>



class RotatedText : public QWidget {
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(int angle READ angle WRITE setAngle)
Q_PROPERTY(int letterAngle READ letterAngle WRITE setLetterAngle)
Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
public:
RotatedText(QWidget *parent = 0) : QWidget(parent) {
m_angle = 0;
m_spacing = 10;
m_letterAngle = 0;
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);
}
const QString &text() const { return m_text; }
int angle() const { return m_angle; }
int letterAngle() const { return m_letterAngle; }
int spacing() const { return m_spacing; }
QSize sizeHint() const { return QSize(100,100); }
public slots:
void setText(const QString &txt) { if(m_text == txt) return; m_text = txt; emit textChanged(m_text); update(); }
void setAngle(int a) { if(m_angle == a) return; m_angle = a; emit angleChanged(a); update(); }
void setLetterAngle(int a) { if(m_letterAngle == a) return; m_letterAngle = a; emit letterAngleChanged(a); update(); }
void setSpacing(int s) { if(m_spacing == s) return; m_spacing = s; emit spacingChanged(s); update(); }
signals:
void textChanged(const QString &);
void angleChanged(int);
void letterAngleChanged(int);
void spacingChanged(int);
protected:
void paintEvent(QPaintEvent *) {
QPainter p(this);
p.translate(width()/2, height()/2);
p.rotate(m_angle);
for(int i=0; i< m_text.size(); ++i) {
QString letter = m_text.mid(i,1);
p.save();
p.translate(i*m_spacing, 0);
p.rotate(m_letterAngle);
p.drawText(0,0, letter);
p.restore();
}
}

private:
QString m_text;
int m_angle;
int m_spacing;
int m_letterAngle;
};

#include "main.moc"

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

QWidget w;
QVBoxLayout *l = new QVBoxLayout(&w);
QLineEdit *le = new QLineEdit;
l->addWidget(le);
le->setPlaceholderText("Enter text");
RotatedText *txt = new RotatedText;
l->addWidget(txt);
QObject::connect(le, SIGNAL(textChanged(QString)), txt, SLOT(setText(QString)));
le->setText("Some example text");
QSlider *angle = new QSlider(Qt::Horizontal);
l->addWidget(angle);
angle->setRange(0, 359);
angle->setValue(txt->angle());
QObject::connect(angle, SIGNAL(valueChanged(int)), txt, SLOT(setAngle(int)));
QSlider *letterAngle = new QSlider(Qt::Horizontal);
l->addWidget(letterAngle);
letterAngle->setRange(0, 359);
letterAngle->setValue(txt->letterAngle());
QObject::connect(letterAngle, SIGNAL(valueChanged(int)), txt, SLOT(setLetterAngle(int)));
QSlider *spacing = new QSlider(Qt::Horizontal);
l->addWidget(spacing);
spacing->setRange(0,100);
spacing->setValue(txt->spacing());
QObject::connect(spacing, SIGNAL(valueChanged(int)), txt, SLOT(setSpacing(int)));

QPushButton *button = new QPushButton("Pause animation");
button->setCheckable(true);
QPropertyAnimation *a1 = new QPropertyAnimation(angle, "value", button);
QPropertyAnimation *a2 = new QPropertyAnimation(letterAngle, "value", button);
a1->setLoopCount(-1);
a2->setLoopCount(-1);
a1->setDuration(9000);
a2->setDuration(5000);
a1->setStartValue(angle->value());
a2->setStartValue(letterAngle->value());
a1->setEndValue(359);
a2->setEndValue(359);
a1->start();
a2->start();
QObject::connect(button, SIGNAL(toggled(bool)), a1, SLOT(setPaused(bool)));
QObject::connect(button, SIGNAL(toggled(bool)), a2, SLOT(setPaused(bool)));
l->addWidget(button);

w.show();

return app.exec();
}

DEEPADEV
6th June 2012, 06:58
Thanks a lot. You gave me more than what i needed.I will try to implement it as per my requirements.:):):)

DEEPADEV
19th June 2012, 08:25
The above code works perfectly fine but was not able to implement it within the Qtextedit object as it was not editable within that. So i used the following code for vertical orientation of text character by character and is working for me


void Orientation::Btn_clicked()
{
QString str1 = textedit->toPlainText();
QByteArray ba = str1.toLocal8Bit();
char *src = ba.data();
char *dest = (char* )malloc(strlen(src)+1) ;
memset(dest,0,strlen(src)+1);
stcpy(src,dest);
QString string = QString::fromLocal8Bit(dest);
textedit->setText(string);
}
}

/***********copying a string with \n to display in vertical order***********/
void Orientation::stcpy(char *src,char* dest)
{
int i,len = 0,j = 0;
len=strlen(src);
for(i=0;i<len;i++)
{
*(dest+j++) = *(src+i);
*(dest+j++) = '\n';
}
*(dest+j) = '\0';
}



Also i am attaching the code for rotation as may be it is useful for freshers of Qt.
I have done it within Qtextedit paintevent



void textedit::paintEvent(QPaintEvent *e)
{
QPainter painter(viewport());
painter.rotate(Angle);
painter.translate(xPos,yPos);

QAbstractTextDocumentLayout::Selection selection;
selection.cursor = textCursor();
selection.format = textCursor().charFormat();
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.cursorPosition = textCursor().position();
ctx.selections.append(selection);
document()->documentLayout()->draw(&painter,ctx);

u can specify the angle of rotation and the co-ordinates to be visible in the above code and use it for rotating the text.It is editable as we are rotating the layout and not drawing the text.
Hope this code will others like me.
If further improvements can be done to this code please do mention.
This site helped me a lot. Thankyou

wysota
19th June 2012, 09:52
Why didn't you say you wanted the text to be part of QTextEdit? We'd have told you that you were supposed to implement your own QTextObject for that...