Adapt QMessageBox size to its text size - qt

I would like to create a QMessageBox::critical which would automatically adapt its size depending on the size of the content (the message text). How can I do it?
This is the message I would like to display on the QMessageBox
std::wstring tmpStrEx;
QDomNode tmpNodeParent = node.parentNode();
while(!tmpNodeParent.isNull() && tmpNodeParent.nodeName().toStdWString() != L"root"){
std::wstring tmpStrTmp;
tmpStrTmp = L"<"
+ tmpNodeParent.nodeName().toStdWString()
+ L" nm=\""
+ tmpNodeParent.toElement().attribute(QS(_T("nm")), QS(_T("undef")) ).toStdWString()
+ L"> ";
}
QString mex = "Error while reading vector.<br/><br/>Please check in:<br/><br/> " + tmpStrTmp ;
tmpStrTmp can be something like <vct nm="name"> <vcx nm="xyz">
I tried in these ways to build the QMessageBox:
First a simple:
QMessageBox::critical(this, "Error", mex);
This shows half message without the content in tmpStrTmp like this:
Error while reading vector.
Please check in:
I thought tmpStrTmp was the problem but if I put only tmpStrTmp in the QMessageBox, it shows its content. So, I thought it was a problem of space and I tried these two ways:
1.
QMessageBox msgBox;
QSpacerItem* spacer = new QSpacerItem(500, 500, QSizePolicy::Minimum, QSizePolicy::Expanding);
msgBox.setTextFormat(Qt::RichText);
msgBox.setText( mex );
QGridLayout* layout = (QGridLayout*)msgBox.layout();
layout->addItem(spacer, layout->rowCount(), 0, 1, layout->columnCount());
msgBox.exec();
2.
QMessageBox *box = new QMessageBox::QMessageBox(QMessageBox::critical, "Error", mex);
QGridLayout *layout = qobject_cast<QGridLayout *>(box->layout());
if (layout) {
QTextEdit *edit = new QTextEdit(mex);
edit->setReadOnly(true);
layout->addWidget(edit, 0, 1);
}
box->exec();
delete box;
but without success...any help? thanks

If you don't want your QMessageBox to simply widen out with your text, and break a new line at some point, you should create an instance of QMessageBox and set it to have a fixed width (QWidget::setFixedWidth()).
Another option is to pass in a text string with new lines (\n) in it, and it can handle it nicely.
Also, if you are using an instance, you can tell it that you are using RichText, and pass in a subset of html markups QMessageBox::setTextFormat(Qt::RichText), or even just make sure you use a valid html tag before your first newline character.
Hope that helps!

QMessageBox is a grid. I'm not sure how to adapt QMessageBox size to its text size but if you know what is going to be appear in the messagebox you can most definitely set it to a minimum(actually fixed) size by this way:-
QMessageBox messageBox;
QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
messageBox.setText( "Put text here" );
QGridLayout* layout = (QGridLayout*)messageBox.layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
messageBox.exec();

Related

Can't get TextArea to scroll to bottom

I am using Kotlin with JavaFX. In a TextArea which is programmatically appended, I want the scrollbar to always jump to the bottom when text is added.
To test this, I wrote this code:
taConsole.text = "Running " + pythonScriptPath
// retrieve output from python script
val bfr = BufferedReader(InputStreamReader(p.inputStream))
val lines = bfr.readLines()
for (i in 1..10) {
for (line in lines) {
taConsole.appendText("\n" + line)
}
}
Sadly, I cant get it to scroll to bottom. I already tried:
ta.selectEnd();
ta.deselect();
dataPane.setScrollTop(Double.MAX_VALUE);
and
val caret = taConsole.selectPositionCaret(taConsole.length)
I inserted them after the:
appendText("\n" + line)

Deleting a dinamically generated UI in QT?

I'm doign a file transfer manager on Dialog the needs to dynamically generate a couple of UI elements. Here is the function that generates it:
void TransferData::createGraphicalUI(QDialog *parent, qint32 td_id){
status = new QLabel(parent);
filename = new QLabel(parent);
contact_label = new QLabel(parent);
accept = new IDPushButton(parent,td_id);
reject = new IDPushButton(parent,td_id);
cancel = new IDPushButton(parent,td_id);
progress = new QProgressBar(parent);
statlayout = new QHBoxLayout();
frameLayout = new QVBoxLayout();
frame = new QFrame(parent);
// Stylying the frame
frame->setStyleSheet("background-color: rgb(255, 255, 255);");
// Setting the messages.
QString htmlHeader = "<html><head/><body><p><span style='font-weight:792; color:#0000ff;'>";
QString htmlEnder = "</span></p></body></html>";
QString contactMsg = "Transfer ";
QString filenameMsg = "File name: </span><span>" + getFileToBeSent();
QString statusMsg = "Status: </span><span>";
cancel->setText("Cancel");
cancel->setIcon(QIcon(":/Icons/icons/cancel.png"));
cancel->setVisible(false);
if (getIsATransfer()){
// This is a transfer TO, the file will be uploaded
contactMsg = contactMsg + "to: </span><span> " + getConctacName();
statusMsg = statusMsg + "Waiting for file to be accepted.";
statlayout->addWidget(status);
statlayout->addWidget(cancel);
accept->setVisible(false);
reject->setVisible(false);
}
else{
// This is a transfer FROM, the file will be downlaoded
contactMsg = contactMsg + "from: </span><span> " + getConctacName();
statusMsg = statusMsg + "Transfer must be accepted before it begins.";
accept->setText("Accept");
accept->setIcon(QIcon(":/Icons/icons/ok.png"));
reject->setText("Reject");
reject->setIcon(QIcon(":/Icons/icons/cancel.png"));
statlayout->addWidget(status);
statlayout->addWidget(accept);
statlayout->addWidget(reject);
statlayout->addWidget(cancel);
}
status->setText(htmlHeader + statusMsg + htmlEnder);
filename->setText(htmlHeader + filenameMsg + htmlEnder);
contact_label->setText(htmlHeader + contactMsg + htmlEnder);
// Resettign the progress bar
progress->setValue(0);
// Putting it all together.
frameLayout->addWidget(contact_label);
frameLayout->addWidget(filename);
frameLayout->addLayout(statlayout);
frameLayout->addWidget(progress);
frame->setLayout(frameLayout);
}
This is called from a function that has a list of TransferData objects:
qint32 TransferManager::addTransfer(TransferData td){
// Getting the ID for this tranfer
qint32 transferID = transfers.size();
td.createGraphicalUI(this,transferID);
// Adding it to the UI
ui->globalTMLayout->addWidget(td.getFrame());
connect(td.getAcceptButton(),SIGNAL(wasClicked(qint32)),this,SLOT(onTransferAccepted(qint32)));
connect(td.getRejectButton(),SIGNAL(wasClicked(qint32)),this,SLOT(onTransferRejected(qint32)));
connect(td.getCancelButton(),SIGNAL(wasClicked(qint32)),this,SLOT(onTransferCanceled(qint32)));
// Adding the TD
transfers << td;
// If a transfer is added this needs to be shown
this->show();
return transferID;
}
Once the transfer is done I need to delete all the elements of the created UI. I do it like this:
void TransferManager::removeTransferData(qint32 which){
if (which < transfers.size()){
// Deleting the UI
transfers[which].removeGraphicalUI();
// Removing the frame
QFrame *frame = transfers.at(which).getFrame();
ui->globalTMLayout->removeWidget(frame);
// Removing the data itself
transfers.removeAt(which);
}
}
Where removeGraphicalUI is this function:
void TransferData::removeGraphicalUI(){
frameLayout->removeWidget(progress);
frameLayout->removeWidget(filename);
frameLayout->removeWidget(contact_label);
statlayout->removeWidget(cancel);
statlayout->removeWidget(status);
if (!getIsATransfer()){
statlayout->removeWidget(accept);
statlayout->removeWidget(reject);
}
}
What happens is that the frame is removed but everythign that was inside the frame remains. I've checked with a printed message an the code IS enering the removeUI function.
So why does this not work and what Is the proper way to delete dinamically generated UI?
Thanks!
Ok, so I haven't found the answer to my question but I did find the way to do this:
Basically the documentation says that when a QWidget descendant object is deleted, all their childs are deleted.
So what I did is basically used the QFrame as the parent for everything BUT the the layouts.
Then when I wanted to delete said frame I would simply invoke:
frame->~QFrame()
In the removeGraphicalUI() function and NOTHING more. Also I've commented this:
void TransferManager::removeTransferData(qint32 which){
if (which < transfers.size()){
// Deleting the UI
transfers[which].removeGraphicalUI();
// Removing the frame
// QFrame *frame = transfers.at(which).getFrame();
// ui->globalTMLayout->removeWidget(frame);
// Removing the data itself
transfers.removeAt(which);
}
}
As removing the frame from the GUI was no longer necessary. I hope this helps someone.

Pdf Generation Using ITextSharp for Cheque Like Structure

I have requirement of online cheque generation.
I am using ,
using iTextSharp.text;
using iTextSharp.text.pdf;
I have dynamic cheque Height and width,font and fontsize.
And obviously cheque number with account information in all page of document.
My code goes like this
Document doc = new Document(new Rectangle(width, height), 0, 0, 0, 0);
string path = Server.MapPath("~/REPORTFILES");
var writer = PdfWriter.GetInstance(doc, new FileStream(path + "/cheque.pdf",FileMode.Create));
doc.Open();
BaseFont f_cn = BaseFont.CreateFont("c:\\windows\\fonts\\calibri.ttf", BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
for (int i = fromchq; i <= tochq; i++)
{
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
cb.SetFontAndSize(f_cn, 14);
cb.SetFontAndSize(f_cn, fontsize);
cb.SetTextMatrix(cord_x, cord_y);
cb.ShowText(getProperty(propertyName,i.ToString().PadLeft(FromChqNo.Length, '0')));
cb.EndText();
doc.NewPage();
}
Here cord_x and cord_y is the co-ordinate location of that text.
Everything works fine i got pdf of my custom size.
like this :
But while printing it into the cheque
its work fine untill it has space enough to print single page. my xps image is attached bellow.
Area in red curve is skiped to be printed.
I mean to ask how can i make it posible that it will print serially, and completely fullfill my requirement that a cheque leaf of any height ,width,font will be printed serially. Thank you all in advance and also thanks for reading my problem.

how to force a justified alignment on a pdfpcell

to justify a text on a pdfpcell i know these commands
PdfPCell Example= new PdfPCell(new paragraph("Some text here",MyFont));//previous created font
Example.HorizontalAlignment = Element.ALIGN_JUSTIFIED;
but i have a hmtl string , and i need to decode, and im doing like this
string txt = "long html string text"
PdfPCell Example2= new PdfPCell();
List<IElement> sr = HTMLWorker.ParseToList(new StringReader(txt ), style);//style was previous created
foreach (IElement element in sr)
{
Example2.AddElement(element);
}
Example2.SetLeading(0f, 1.5f);
Example2.Border = 0;
Example2.PaddingBottom = 20;
Table1.AddCell(Example2);//table declared previous
ok , until this point all is working and my pdfp document is fine but i need to ignore the alignment of the html string and force all text to be justified.
im tried this
Example2.HorizontalAlignment = Element.ALIGN_JUSTIFIED;
but doesnt work .
In the first example, you're working in "text mode" and the properties of the cell are respected.
As soon as you use AddElement (), you're working in "composite mode" and the properties of the cell are ignored (as documented in my book). Instead, the properties of the separate elements are used.
In answer to your question: you shouldn't define the alignment at the level of the cell, but at the level of the element.

How to automatically set TextField()'s width

I'm trying to set the width of a Textfield() object based on it's string content that I have set-
Is there a way to dynamically set this once the string has been sent to the object?
I have:
var t1:TextField = new TextField()
t1.x = stage.stageWidth / 2;
t1.y = stage.stageHeight / 2;
t1.text = "some string that i would want to render";
t1.textColor = 0x000000;
t1.cacheAsBitmap = true;
addChild(t1);
Thanks for any suggestions...
jml
TextField.autoSize?
edit:
You should read the documentation correctly, it's a member variable that actually needs to be set. I'll give you a quick example on how this works:
var tf:TextField = new TextField();
tf.text = 'Some text.';
tf.autoSize = TextFieldAutoSize.LEFT;
tf.x = ( stage.stageWidth - tf.width ) / 2;
tf.y = ( stage.stageHeight - tf.height ) / 2;
Alternatively you can also align the text field first and use TextFieldAutoSize.CENTER to keep it aligned in the center.
t1.text = "Some text";
t1.width = t1.textWidth + 5;
t1.height = t1.textHeight + 5;
Why the + 5? Because Adobe sucks and adds an internal gutter around your stuff. Per the docs this is supposed to be 2px per side, but it's actually slightly more, so you add another +1 for good measure.
you could try using the getCharBoundaries() method (it returns a rectangle surrounding a character at a specified index). Use that to get the rectangle from the first and last chars and set the width to the difference of those rectangles.
Pretty convoluted, there's got to be a better way, but if not this should work.

Resources