I am trying to create a printable document using QTextDocument, which also includes a table, which I am adding using QTextCursor::insertTable.
However I have the requirement to use different background colors for the table rows. The table is meant to contain all days of a month, and weekends should have grey background, while workdays shall have no background.
I have tried this code:
QTextTable* table = cursor.insertTable(1, 7, normal); // 7 columns, and first row containing header
foreach (DayItem* day, month->days)
{
if (day->date.dayOfWeek() == 6 || day->date.dayOfWeek() == 7)
{
table->setFormat(background); // grey background
table->appendRows(1);
}
else
{
table->setFormat(normal); // white background
table->appendRows(1);
}
}
Now the issue with this is that the table->setFormat changes the format of the whole table, and I can't seem to find any function which lets me set the format for a row or a cell. There is formatting options for cells, however those are for the text format, and thus would not color the cell background.
I have also tried using QTextDocument::insertHTML and work with HTML tables, however Qt would not render the CSS correctly which I would use for styling the borders and so on.
How can I achieve alternating row background colors in QTextTable?
You can use QTextTableCell:setFormat to change the background color of each cell:
auto edit = new QTextEdit();
auto table = edit->textCursor().insertTable(3, 2);
for(int i = 0; i < table->rows(); ++i)
{
for(int j = 0; j < table->columns(); ++j)
{
auto cell = table->cellAt(i, j);
auto cursor = cell.firstCursorPosition();
cursor.insertText(QString("cell %1, %2").arg(i).arg(j));
auto format = cell.format();
format.setBackground(i%2 == 0 ? Qt::red : Qt::green);
cell.setFormat(format);
}
}
Related
I am using this code to set the initial size of my buttons:
// Now check button sizes
auto *pDC = m_btnPreview.GetDC();
if (pDC != nullptr)
{
pDC->SelectObject(GetFont());
auto sizeActualSize = pDC->GetTextExtent(strButtonText);
sizeActualSize.cx += 10;
if (sizeActualSize.cx > rctOK.Width())
{
// We need to consistently resize both buttons
int iButtonGap = rctCancel.left - rctOK.right;
rctCancel.left = rctCancel.right - sizeActualSize.cx;
rctOK.right = rctCancel.left - iButtonGap;
rctOK.left = rctOK.right - sizeActualSize.cx;
GetDlgItem(IDOK)->MoveWindow(rctCancel);
m_btnPreview.MoveWindow(rctOK);
}
ReleaseDC(pDC);
}
It works fine. I correctly set the font so that the size returned is right. But I have added a value of 10 to pad it a bit so that the button looks nicer:
Is there a specific MFC constant for the default gap around button? Rather than fudging it with a value of 10?
I am using QFormLayout with QLabels in the left column and various widgets in the right column. On the right, there are either labels, check boxes, combos or line edits. Unfortunately each of there controls has different natural height. But I would like to have each row in the form layout to have equal heights determined by the biggest one (I know in which row it is). Is there any simple way to achieve this? I cannot find anything like QFormLayout::setRowHeight().
One solution, just assign equal size to all widgets at runtime using the following function:
void setEqualRowHeight(QFormLayout *formLayout, int height)
{
QWidget *w;
for(int i = 0; i < formLayout->rowCount(); i++) {
QLayoutItem *item = formLayout->itemAt(i, QFormLayout::FieldRole);
if (item && (w = item->widget())) {
w->setFixedHeight(height);
}
}
}
Could you please help me to achieve layout as in this example?
Sample items in this list loads dynamically into view and length can be various. And it seems like the count of dots should change according to this. I try to use <table> element but it only I can set is dotted border to bottom and this is not my case because I need it in the middle of the row.
You could make the dots a vertically centered background for the TD. The content itself has a white background, so that the dots are hidden under the text.
Example here:
http://jsfiddle.net/willemvb/QkEzr/
Here is what you could do in a quick and easy way with just CSS. Just create three blocks(div's). And give a bottom border to the middle div. Then move it's position a bit higher(margin-top with a negative value). I guess that's what you needed.
If you're using table, then no problem. Just add another div inside the second column. And add the bottom border as I said above. And move the div upper. Simple.
Here's a javascript solution. The idea is to set the font to monospace, and then place dots depending on the number of characters in a given row relative to the max number of characters in the samples column.
var samplePts = new Array( new Array("Sample",23), new Array("Longer Sample",9), new Array("Much Londer Sample",125) );
var maxSampleLen = 0;
for (var i=0; i<samplePts.length; i++){
var currLen = samplePts[i][0].length;
if (currLen > maxSampleLen){
maxSampleLen = currLen;
}
}
for (var i=0; i<samplePts.length; i++){
var outputStr = "<div style='font-family: monospace;'>"+samplePts[i][0];
for (var n=0; n<maxSampleLen-samplePts[i][0].length+5; n++){
outputStr += "·";
}
outputStr += samplePts[i][1]+"</div>";
document.write(outputStr);
}
I need to change the color of the cells on сlick (only 2 colors: black and white), and then analyze the colors of cells to form an array with values: 1 - black, 0 - white?
Try this code to toggle the color
onClick="this.style.backgroundColor=='black' ? this.style.backgroundColor='white' : this.style.backgroundColor='black';"
And you get the Colors using this function
var tds = document.getElementsByTagName("td");
for(var i=0; i<tds.length; i++)
{
alert(tds[i].style.backgroundColor);
}
}
I have a DataGrid in my project. It doesn't fit's the width of the form, so the scrollBar appears. The DataGrid, on it's initial state, displays a few columns and a part of the next column (which would appear after scrolling).
Is there any way, I can get the width of this, displaying part?
You should get the width of the parent object.
let's say the datagrid is in your application, then you should get the width of the stage.(stage.stageWidth)
If your datagrid is on a certain x location in your application (or any other parent object) then you should take the width of the parent object - the x value of your datagrid. (stage.stageWidth - dataGrid.x)
Ok, I had some time to dig more deeply in this problem. I've searched a few classes to see, how the Adobe was implementing those grid behavior (displaying columns partly). So, for those, who'll need to deal with this, the needed part is in DataGrid.as file, method configureScrollBars .. actually, this part of it:
// if the last column is visible and partially offscreen (but it isn't the only
// column) then adjust the column count so we can scroll to see it
if (collectionHasRows && rowCount > 0 && colCount > 1 &&
listItems[0][colCount - 1].x +
visibleColumns[colCount - 1].width > (displayWidth - listContent.x + viewMetrics.left))
colCount--;
else if (colCount > 1 && !collectionHasRows)
{
// the slower computation requires adding up the previous columns
var colX:int = 0;
for (var i:int = 0; i < visibleColumns.length; i++)
{
colX += visibleColumns[i].width;
}
if (colX > (displayWidth - listContent.x + viewMetrics.left))
colCount--;
}
That's pretty much all code, that needed to catch and measure all those tricky divided cols in a grid :)