Tkinter Grid Columnspan ignored - grid

Consider the following python script
#!/usr/bin/env python
from Tkinter import Tk, Label
width = SOME_VALUE_HERE
root = Tk()
label1 = Label(root, text='1 columns wide')
label2 = Label(root, text='%i columns wide' % width)
label1.grid()
label2.grid(row=0,column=1,columnspan=width)
root.mainloop()
When I run this, no matter what value is set for 'SOME_VALUE_HERE', both labels take up half the window, regardless of whether or not Grid.columnconfigure is called, or the sticky parameter is used in grid().
Unless I've overlooked something, I would have thought that setting the columnspan would force the second label to be 'SOME_VALUE_HERE' times as wide as the first.
Have I misunderstood how grid works? How would I go about achieving this behavior?

By default, empty grid column are zero width, so you described the following table. Grid geometry manager will by default try to optimize the screen real estate used by your application. It will integrate all the constraint and produce the fittest layout.
+---------------+---------------++++
| 0 | 1 |||| <-- 2,3,4 empty, 0 width
+---------------+---------------++++
| 1 column wide | 4 column wide |
+---------------+---------------++++
To provide strict proportional column width, you have to use the uniform option of columnconfigure. uniform takes an arbitrary value to designate the group of the column that share these proportions, and the weight argument is used to properly handle widget resizing.
label1.grid(row=0, column=0)
label2.grid(row=0,column=1, columnspan=width)
for i in range(width+1):
root.grid_columnconfigure(i, weight=1, uniform="foo")
Note that with only these two labels, you could achieve the same layout by adjusting the width of column 1. Differences will occur still while you populate column 2,3,4...
label2.grid(row=0,column=1) #no columnspan
root.grid_columnconfigure(0, weight=1, uniform="foo")
root.grid_columnconfigure(1, weight=width, uniform="foo")

When you put something in column 1 with a columnspan of two (or more) that means it will be in column 1 and column 2 (etc). However, if there is nothing controlling the width of a column, that column will have a width of zero. You need to force column 2 to have a widtheither by putting something in there, giving it a minsize, or forcing uniform columns.
When I look at your code, I can't guess how wide you think column 2 should be, and neither can the computer.

I had a similar problem only to discover that the elements are limited by the widest widget. We can safely say that Tkinter is configured to make your app uniform in that it should be a regular repeating square/triangular structure. Solution to override default options.
With the Tkinter's automatic optimization in mind, play with the width and height of largest widget (grid box) and relate the other boxes to it proportionally.
Using the above method use columnspan to adjust the width.
Configure the widths by use of columnconfigure()

Related

Starting grid column from half of the column

I am trying to start grid column from half of the very first column.
I tried grid-start-column with different values but it's not working. Basically, it should be like following:
grid-column: 0.5/7
I know this is not the valid code, but just for explanation I write that.
Is it possible to start a column from the half of the column?
Is it possible to start a column from the half of the column?
No. It is not.
Let's say you have a grid container with five columns and want to start spanning from halfway inside the first column (grid-column: 1.5 / 5 ). This won't work because you're not starting at a column line. More technically, the grid-row-* and grid-column-* properties accept only integers as values.
However, there is a simple workaround:
Instead of five columns use 10 columns.
Then start spanning at the third column (grid-column: 3 / 10).
This creates an equivalent layout, which looks the same visually, but with more precise control of the columns.
More details here: Changing div heights using CSS grid

How do you get IFCWindow sill height

How to get the sill height (height above the floor) of a Ifcwindow in ifc file
There is no solution to get the height above the floor directly. This is because the height above for depends on several factors, like how the wall is created in which the window resides, etc.
It could be that the sillHeight is exported by the original modelling software to a custom IFC property. You could check for that, but since there is no common standard for it, it's risky.
Your best bet is to look into the ObjectPlacement property which IfcWindow inherits from IfcProduct. The ObjectPlacement defines how a product is placed either in world space or relative to its host. See https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2/HTML/schema/templates/product-local-placement.htm for details.
You need to read the ObjectPlacement property, and check if there is a RelativeTo property, if so, you need to fill into that property as well, and check if it's the placement of a floor. If so, you can stop the looping, and perform a matrix calculation on all the placements you harvested to calculate the placement of window relative to floor.
(Maybe even more simple: calculate world placement of window and floor separately, than subtract the two vector z values to get the height of window from floor)

get the exact height of QTextDocument in pixels

I need to get the actual height of QTextDocument in order to be able to set the containing QPlainTextEdit to a minimum height (while keeping its width constant) so that it shows the whole content without the vertical scrollbar. I tried to follow this question (closed with with accepted answer) How do I determine the height of a QTextDocument? but it does not do what it promises.
A piece of code:
from PyQt5.QtWidgets import QApplication, QPlainTextEdit
app = QApplication([])
w = QPlainTextEdit()
w.setPlainText("Hello!")
print(w.document().size())
w.setPlainText("Hello!\nHello again!")
print(w.document().size())
prints out:
PyQt5.QtCore.QSizeF(35.0, 1.0)
PyQt5.QtCore.QSizeF(64.0, 2.0)
It seems that the width is measured correctly in pixels but the height just shows the number of lines instead of pixels. I think multiplying it with font pixel metric height does not help because there can be mixed formatting (in general it can be a rich text / HTML) and line spacing, document margins and maybe some other complicated stuff based on implementation details... etc.
So is there a way out?
So I finally found a solution but it is really ugly. If anyone knows anything better, please publish it.
from PyQt5.QtWidgets import QApplication, QPlainTextEdit
app = QApplication([])
w = QPlainTextEdit()
# test various formatting
w.appendHtml("<h1>Hello!</h1>")
w.appendHtml("<b>Hello!</b>")
w.appendPlainText("Hello!")
doc = w.document()
layout = doc.documentLayout()
h = 0
b = doc.begin()
while b != doc.end():
h += layout.blockBoundingRect(b).height()
b = b.next()
# magic formula: I do not know why the document margin is already
# once included in the height of the last block, and I do not know
# why there must be the number 1 at the end... but it works
w.setFixedHeight(h + doc.documentMargin() + 2 * w.frameWidth() + 1)
w.show()
app.exec_()
So this should show the box without scroll bar. If you decrease the height by 1, the scroll bar appears. This should work with any number of lines, document margins, frame widths, formatting etc. Hopefully.
Shot in the dark without testing
Have you looked # pageSize?
From the docs:
This property holds the page size that should be used for laying out the document
The units are determined by the underlying paint device. The size is
measured in logical pixels when painting to the screen, and in points
(1/72 inch) when painting to a printer.
By default, for a newly-created, empty document, this property
contains an undefined size.
If you set the pageSize, as directed by the other thread, I'd expect you'd get the value out in the pixels that QPlainTextEdit::setMinimumHeight needs.

What is the default width of an HTML table cell <td>?

I haven't been able to find the answer to this question: Where in the spec or in UA documentation is the default width of a <td> defined?
I've searched the HTML Living Standard, the HTML5 Recommendation, and various other sources.
My understanding (based on usage and observation) is that a table cell will, by default, occupy the full width of the column in which it lives. And the cell cannot be given a different width than the column if other cells exist in the column.
I'm looking for official confirmation of this behavior, preferably in W3C or user agent documentation. But any authoritative reference is acceptable.
The physical/visual width of a table cell is defined not by HTML, but by CSS. The CSS 2.1 specification has an entire section dedicated to table layout that complements HTML's description of tabular data.
Furthermore, CSS itself does not fully define how the width of a cell is calculated. It does with the fixed table layout algorithm:
In the fixed table layout algorithm, the width of each column is determined as follows:
A column element with a value other than 'auto' for the 'width' property sets the width for that column.
Otherwise, a cell in the first row with a value other than 'auto' for the 'width' property determines the width for that column. If the cell spans more than one column, the width is divided over the columns.
Any remaining columns equally divide the remaining horizontal table space (minus borders or cell spacing).
The width of the table is then the greater of the value of the 'width' property for the table element and the sum of the column widths (plus cell spacing or borders). If the table is wider than the columns, the extra space should be distributed over the columns.
but it doesn't give anything beyond a rough guideline for auto table layout, which user agents are free to follow or deviate from (it lists a step-by-step procedure not unlike that of fixed table layout, but that entire list is non-normative). Generally you can expect consistent behavior from UAs in the most common scenarios — as you observe, an auto-sized table cell generally takes up as much space as required by its content, and no more. But dig into edge cases, and you'll find all sorts of crazy.
Here's the W3C standards on calculating the width of table columns. Basically it is left up to the implementing browser/agent.
If an author specifies no width information for a column, a user agent
may not be able to incrementally format the table since it must wait
for the entire column of data to arrive in order to allot an
appropriate width.
If column widths prove to be too narrow for the contents of a
particular table cell, user agents may choose to reflow the table.
Source: http://www.w3.org/TR/html401/struct/tables.html#h-11.2.4.4
Note: this is HTML4 docs.
A table cell's minimum width is 0 or the size of the largest word or image within that cell.
Table Sizing Algorithm
The default sizing algorithm requires two passes through the table data. In the first pass, word wrapping is disabled, and the user agent keeps track of the minimum and maximum width of each cell. The maximum width is given by the widest line. As word wrap has been disabled, paragraphs are treated as long lines unless broken by elements. The minimum width is given by the widest word or image etc. taking into account leading indents and list bullets etc. In other words, if you were to format the cell's content in a window of its own, determine the minimum width you could make the window before things begin to be clipped.
The minimum and maximum cell widths are then used to determine the corresponding minimum and maximum widths for the columns. These in turn, are used to find the minimum and maximum width for the table. Note that cells can contain nested tables, but this doesn't complicate the code significantly. The next step is to assign column widths according to the current window size (more accurately - the width between the left and right margins).
The table borders and intercell margins need to be included in the assignment step. There are three cases:
The minimum table width is equal to or wider than the available space. In this case, assign the minimum widths and allow the user to scroll horizontally. For conversion to braille, it will be necessary to replace the cells by references to notes containing their full content. By convention these appear before the table.
The maximum table width fits within the available space. In this case, set the columns to their maximum widths.
The maximum width of the table is greater than the available space, but the minimum table width is smaller. In this case, find the difference between the available space and the minimum table width, lets call it W. Lets also call D the difference between maximum and minimum width of the table.
For each column, let d be the the difference between maximum and minimum width of that column. Now set the column's width to the minimum width plus d times W over D. This makes columns with lots of text wider than columns with smaller amounts.
This assignment step is then repeated for nested tables. In this case, the width of the enclosing table's cell plays the role of the current window size in the above description. This process is repeated recursively for all nested tables.
If the COLSPEC attribute specifies the column widths explicitly, the user agent can attempt to use these values. If subsequently, one of the cells overflows its column width, the two pass mechanism may be invoked to redraw the table with more appropriate widths. If the attribute specifies relative widths, then the two pass model is always needed.
The column width assignment algorithm is then modified:
Explicit widths from the COLSPEC attribute should be used when given, provided they are greater than the minimum column width, otherwise the latter should be used.
For relative widths, the surplus space W, as defined above, is divided up between the columns appropriately, ensuring that each column is given at least its minimum width. If W is zero or negative, column widths should be increased over the minimum width to meet the relative width requirements.
If the table width is specified with the WIDTH attribute, the user agent attempts to set column widths to match. The WIDTH attribute should be disregarded if this results in columns having less than their minimum widths.

How to stop Grid, GridRow, GridItem from assigning proportional column widths

In Flex4 we use Grid, GridRow and GridItem to layout the components of our screens. Most screens look OK, but quite a few appear with large amounts of space between the label and field. This mainly happens when we want to have something like the following scenario...
Name [____________]
Age [__]
Gender [_]
Details
[__________________________________________]
[__________________________________________]
[__________________________________________]
|<col 1>|<------------ col 2 ------------->|
|<---------- grid and row width ---------->|
...where the Labels are in the first column, the top three fields are in the second column, and the bottom three fields span across both columns. Above is how we would like it appear, but Flex renders it like this...
Name [____________]
Age [__]
Gender [_]
Details
[__________________________________________]
[__________________________________________]
[__________________________________________]
|<--- col 1 --->|<-------- col 2 --------->|
|<---------- grid and row width ---------->|
We don't have the ability to set individual column widths in each screen as a) there are thousands of screens and b) the labels and components can be internationalised.
I can't quite work out the algorithm they use to assign each column its width, but I think it looks for the widest component in each column and then uses these to assign each column an appropriate proportional width.
All we want is for each column to be as thin as possible so it just contains just its widest component (ignoring those that span of course), and doesn't have any extra whitespace. Does anyone know how to achieve this result?

Resources