Сan someone explain to me results of this test program?
#include <QApplication>
#include <QDebug>
#include <QFontMetrics>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFont font;
font.fromString("Monospace,14");
QFontMetrics fm(font);
qDebug() << "W : " << fm.width('W');
qDebug() << "8*W : " << 8*fm.width('W');
qDebug() << "WWWWWWWW: " << fm.width("WWWWWWWW"); // 8*W
return 0;
}
After comipiling this code with Qt5.11 I have such results:
W : 11
8*W : 88
WWWWWWWW: 92
Size of one character 'W' for this monospace font is 11. I expect that size of string that consists of 8 such characters should be 88. But QFontmetrics::width returns 92!
The problem was in rounding. If I use QFontMetricsF instead of QFontMetrics results are correct
W : 11.4375
8*W : 91.5
WWWWWWWW: 91.5
But I found another strange thing. QFontMetricsF::maxWidth() should returns qreal type, but in fact it always returns rounded value (11 in my example). It looks like bug in Qt.
https://bugreports.qt.io/projects/QTBUG/issues/QTBUG-73458?filter=allopenissues
Related
I have a problem with QPainter on QImage in Qt 5.4.
The image has Format_ARGB32. I want to set a given RGBA value on pixels in the image using a QPainter draw function and later read the value back using QImage::pixel.
Yet the value painted and the value read back are different. What am I doing wrong?
Sample code:
QImage image(100, 100, QImage::Format_ARGB32);
uint value = 0x44fa112b; //some value..
QPainter painter(&image);
painter.setCompositionMode(QPainter::CompositionMo de_Source);
QColor color(qRed(value), qGreen(value), qBlue(value), qAlpha(value));
QBrush brush(color);
painter.setBrush(brush);
painter.drawRect(0,0,image.width(), image.height());
uint value1 = image.pixel(50,50);
// value1 IS NOT EQUAL TO value. Why??
This works fine in Qt 5.7. Perhaps earlier Qt versions need the painter.end() call.
#include <QtGui>
int main(int argc, char ** argv) {
QGuiApplication app{argc, argv};
QImage image{100, 100, QImage::Format_ARGB32};
auto const set = 0x44fa112b;
QPainter painter(&image);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setBrush({{qRed(set), qGreen(set), qBlue(set), qAlpha(set)}});
painter.drawRect(image.rect());
if (false) painter.end(); //<< try with true here
auto readback = image.pixel(50,50);
qDebug() << hex << set << readback;
Q_ASSERT(readback == set);
}
Problem solved!!
Working properly when I tried with Qt 5.8
Looks like a bug with Qt 5.4.
Thanks to all :)
I've just started switching to QRegularExpression, and I'm using it to tokenize a string with multiple delimiter possibilities. I've encountered a surprising behavior, which seems to me to be a bug. I'm using Qt 5.5.1 on Windows.
Here's sample code:
#include <QRegularExpression>
#include <QString>
#include <QtDebug>
int main(int argc, char *argv[])
{
Q_UNUSED (argc);
Q_UNUSED (argv);
QRegularExpression regex ("^ ");
qDebug () << "Expected: " << QString ("M 100").indexOf(regex);
qDebug () << "NOT expected:" << QString ("M 100").indexOf(regex, 1);
qDebug () << "Expected: " << QString (" 100").indexOf(regex);
QRegularExpression regex1 (" ");
qDebug () << "Expected: " << QString ("M 100").indexOf(regex1);
}
And the output:
Expected: -1
NOT expected: -1
Expected: 0
Expected: 1
The use of the caret (^) when used with a starting position other than 0 in the "indexOf" call is preventing the expression from matching. Intuitively, I expected that the caret matches the string at the position that I specified. Instead, it simply never matches.
I'm going to switch my tokenizing to use splitRref to avoid this problem. While that's probably slightly cleaner anyway, I need to understand whether this is correct behavior or if I should be reporting a bug to Qt.
UPDATE: Using splitRef doesn't entirely solve my problem because I need to use a regular expression to detect if some tokens are floating point numbers, and I can't use a QRegularExpression with QStringRef. For that possibility, I have to convert my QStringRef token into an actual QString, which was what I was trying to avoid in the first place.
^ matches at the beginning of the subject string, or after a newline when in multiline mode. The offset does not alter these semantics. Hence, matching /^ / (in regex notation) against M 100 at offset 1 correctly results in no match.
Perhaps you want \G? From pcrepattern(3):
\G matches at the first matching position in the subject
The \G assertion is true only when the current matching position is at the start point of the match, as specified by the startoffset argument of pcre_exec(). It differs from \A when the value of startoffset is non-zero.
With that, this code:
QRegularExpression regex ("\\G ");
qDebug () << "Expected: " << QString ("M 100").indexOf(regex);
qDebug () << "NOT expected:" << QString ("M 100").indexOf(regex, 1);
qDebug () << "Expected: " << QString (" 100").indexOf(regex);
prints
Expected: -1
NOT expected: 1
Expected: 0
I have rich text items implemented using QGraphicsTextItem
To set font size, for example:
void set (int fontSize) {
QTextCursor _cursor = textCursor();
QTextCharFormat _format;
_format.setFontPointSize(fontSize);
_cursor.mergeCharFormat(_format);
setTextCursor(_cursor); }
A lot more complicated is to read the font size.
Assuming I have a selection, I must iterate through the document, through all QTextBlock, QTextFragment, reading the QTextCharFormat ...
But the simple option, if there is no selection, just reading the font size at cursor:
int get () {
return textCursor().charFormat().fontPointSize(); }
This works, but I found 3 issues:
1) Setting font size by QGraphicsTextItem properties:
QFont f = font();
f.setPointSize(20);
setFont(f);
this returns 0 by my get function above. To set the font size for the entire item, I have to use the same method as in the set function.
Shouldn't the setFont method set a font that can be read from the QTextCursor ?
2) setHtml can set formatting - but I don't see any way to read that formatting
How can I read the rich text formatting from an html fragment ? Is the only posiblity, parsing the html ?
3) (my current stumbling block)
Copy formatted text from an outside source and paste in the QGraphicsTextItem seems to maintain the formatting of the source - but how can I read that formatting ?
The get method above reads font size 0 if the text was pasted from outside.
font().pointSize() always returns 8. (I have not set it so I imagine that is a default)
Is there another method to read the text format ?
is the clipboard text formatted using html ?
How can I find the font size (or any other formatting) from the pasted text ?
(The same questions apply to block formatting, like alignment).
I think most of your problems could be solved by getting the QTextDocument for your QGraphicsTextItem object and work with it. QTextDocument and its methods (like QTextFormat::property(int propertyId)) can help you to get a lot of properties for your text.
1) If you set the size using the QFont object, you should get the size using the same way.
2) When you set the text using html, QGraphicsTextItem::font() is not useful so you need to get the QTextDocument and use their functions instead.
3) Same as 2. I think... because I don't have your code to test it :)
Well, here you have a code as an example. I hope this answer helps you.
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QTextCursor>
#include <QTextCharFormat>
#include <QFont>
#include <QDebug>
#include <QTextDocument>
#include <QTextBlock>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
/* ITEM 1 */
QGraphicsTextItem* item_1 = new QGraphicsTextItem("QGraphicsTextItem 1");
item_1->setTextInteractionFlags(Qt::TextEditorInteraction);
QFont f = item_1->font();
f.setPointSize(30);
item_1->setFont(f);
qDebug() << "textCursor().position() (returns 0): " <<
item_1->textCursor().position();
qDebug() << "textCursor().charFormat().fontPointSize() (returns 0): " <<
item_1->textCursor().charFormat().fontPointSize();
qDebug() << "font().pointSize() (returns 30 - OK!): " <<
item_1->font().pointSize();
QTextDocument* doc = item_1->document();
f = doc->defaultFont();
qDebug() << "pointSize (returns 30 - OK!): " << f.pointSize();
scene.addItem(item_1);
/* ITEM 2 */
QGraphicsTextItem* item_2 = new QGraphicsTextItem();
item_2->setPos(0, 50);
item_2->setHtml("<html><head/><body><p>"
"<span style=\"font-size:14pt; font-weight:600;\">QGraphics</span>"
"<span style=\"font-size:24pt; font-weight:600;\">TextItem 2</span>"
"</p></body></html>");
qDebug() << "font().pointSize() (returns 8, the default value): "
<< item_2->font().pointSize();
doc = item_2->document();
f = doc->defaultFont();
qDebug() << "pointSize (returns 8, the default value): " << f.pointSize();
QVector<QTextFormat> formats = doc->allFormats();
QVectorIterator<QTextFormat> i(formats);
while (i.hasNext()) {
QTextFormat format = i.next();
if (format.property(QTextFormat::FontPointSize).isValid())
qDebug() << "format.property (returns 14 or 24): " <<
format.property(QTextFormat::FontPointSize).toInt();
}
/*
* Get the block of text. In this example, we only have one block, but
* two text fragments (see below)
*/
QTextBlock text_block = item_2->document()->findBlock(1);
QTextBlock::iterator it;
for (it = text_block.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid())
qDebug() << "currentFragment.text(): " << currentFragment.text();
qDebug() << "currentFragment.charFormat().font().pointSize() "
"(returns 14 or 24, depending on"
"the current text fragment): " <<
currentFragment.charFormat().font().pointSize();
}
scene.addItem(item_2);
view.setFixedSize(640, 480);
view.show();
return a.exec();
}
I have to write a small QT program that reads in 3 mark percentages separated by commas and then do some further calculations on the marks... I have to use QInputDialog to do this but it seems like it's only possible to read in one value at a time.
at this stage I am only trying to read in and display the three marks.
When I run this code QTCreator stops working and I have to end the process in task manager.
Any idea how I can approach this would be much appreciated. Should I read in a string and then convert that to double values or is there a simpler way?
Thanks in advance.
Code:
#include <QTGui>
#include <QApplication>
#include <QString>
#include <QTextStream>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextStream cin(stdin, QIODevice::ReadOnly);
QTextStream cout(stdout, QIODevice::WriteOnly);
double mark1, mark2, mark3;
double passMarkNeeded = 0;
QInputDialog::getDouble(0, "Enter marks", "Marks", 1);
cin >> mark1 >> mark2 >> mark3;
cout << "User entered " << mark1 << mark2 << mark3;
return EXIT_SUCCESS;
}
Obviously you cannot use QInputDialog::getDouble because it won't allow you to input 3 values separated by commas. You should use QInputDialog::getText, QString::split and QString::toDouble:
QStringList list = QInputDialog::getText(0, "Input values", "Input values:").split(",");
if (list.count() == 3) {
double a = list[0].toDouble(),
b = list[1].toDouble(),
c = list[2].toDouble();
qDebug() << "Values:" << a << b << c;
}
I'm not sure why you use QInputDialog and the standard input (cin). QInputDialog is for GUI apps, and cin is console apps. It's strange and pointless to use them together in such a way.
The code
#include <QtCore>
#include <QtXml/QDomElement>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QDomElement* element = new QDomElement();
element->setTagName("feature");
qDebug() << element->tagName();
return app.exec();
}
prints simply "". However, as far as I can tell from the documentation it should print "feature". In fact
qDebug() << element->isNull();
prints true so something is not being set correctly. Does anyone know what I am doing wrong?
I'm using Qt 4.6.3 on openSUSE Linux 11.2.
You cannot use the default constructor. You need to use QDomDocument::createElement(const QString &tagName). The element needs to be part of a document. You cannot use it "standalone".
Here's what the documentation says for the QDomElement default constructor:
QDomElement::QDomElement ()
Constructs an empty element. Use the QDomDocument::createElement() function to construct elements with content.
By "empty" they mean null.