Is there a way to change height of tkinter Treeview heading? - python-3.x

I got a problem with changing the height of the Treeview.heading. I have found some answers about the dimensions of Treeview.column, but when I access Treeview.heading in the documentation, there is not a single word about changing the height of the heading dynamically when the text doesn't fit (and wrapping it) or even just hard-coding height of the heading in pixels.
I don't have to split the text to two rows, but when I just keep it that long the whole table (as it has many entries) takes up the whole screen. I want to keep it smaller, therefore I need to split longer entries.
Here is how it looks like:

I can't find any documentation to verify this but it looks like the height of the heading is determined by the heading in the first column.
Reproducing the problem
col_list = ('Name', 'Three\nLine\nHeader', 'Two\nline')
tree = Treeview(parent, columns=col_list[1:])
ix = -1
for col in col_list:
ix += 1
tree.heading(f'#{ix}', text=col)
The fix
col_list = ('Name\n\n', 'Three\nLine\nHeader', 'Two\nline')
or, if you want to make it look prettier
col_list = ('\nName\n', 'Three\nLine\nHeader', 'Two\nline')
The only problem is I haven't figured out how to centre the heading on a two line header
Edit
The newlines work if it is the top level window but not if it is a dialog. Another way of doing this is to set the style. I've got no idea why this works.
style = ttk.Style()
style.configure('Treeview.Heading', foreground='black')

you can use font size to increase the header height for sometimes;
style = ttk.Style()
style.configure('Treeview.Heading', foreground='black', background='white', font=('Arial',25),)

Related

Visio Shape Text positioning below the shape using Text Transform

I have a building a set of stencil shapes and I need the text to display below the shape. I am using custom formulas to generate the text, and as such the volume of text changes from use case to use case.
What I have come across is using the Text Transform set of properties, and I have tried the following with success for a single line of text:
TxtWidth = TEXTWIDTH(TheText)
TxtPinX = Width * 0.5
TxtLocPinX = TxtWidth * 0.5
TxtHeight = Height * 0
TxtPinY = Height * -0.2
TxtLocPinY = TxtHieght * 0.5
TxtAngle = 0 deg
The problem arises when there is more than a single line of text to display -> the text appears 'half above (inside) and half below' the bottom the shape.
I would like to place all the text, regardless of how many lines there are, underneath the shape.
What I have tried is to set the TxtPinY = some formula different from above eg/ Height * -(TxtHeight). This seems to always result in an 'error in formula'.
I am sure that this is something simple that I am missing, but I cannot figure it out.
Can anybody point me in the right direction?
Cheers and thanks for taking a look at this,
The Frog
You could try the TEXTHEIGHT function to get around this. Specify a reasonable maximum text widht as a second parameter for it:
TxtHeight = TEXTHEIGHT(TheText,100)
TxtPinY = 0
TxtLocPinY = TxtHeight
You can use the code provided with the stencil available in this post:
http://visguy.com/vgforum/index.php?topic=7461.msg31490#msg31490

Ticks on color bar are overlapping because the values are very close to each other

I'm trying to display the exact values on one axis of the color bar and a basic scale on the other. However, some of the exact values are so close together their names overlap on the color bar. Is there a way for me to make the overlapping names appear as a list or just to the side the other values name? I've already tried rotation of the labels, setting vmin/vmax in the color bar method, and setting the ylim's of the second axis. I'm at a lose at what to try next. It feels like this is something matplotlib would allow but I can't find what method or kwargs that allow this manipulation. Many of the commented out tlines are the attempts I've made with help from many posts on StackOverflow. Thank you!!
Previous code deleted for clarity
UPDATE: Paul H here is a workable example with the same issue I'm trying to fix
# Make random data with same issue
x, y = np.linspace(-3, 1.5, 20), np.linspace(0, 0.5, 20)
# two different ranges used to simulate the same issue in my data
fake_phase = np.append(np.random.random_sample(15), np.arange(0.0, .005, 0.001))
fake_labels = np.array(['V439Oph', 'ALVir', 'YZVir', 'XXVir', 'V716Oph', 'BFSer', 'BLHer',
'RXLib', 'CEHer', 'V465Oph', 'V1180Sgr', 'CSCas', 'DQAnd', 'IXCas',
'UYEri', 'TWCap', 'AUPeg', 'MZCyg', 'SWTau', 'TXDel'], dtype=object)
# Plot data
fig, ax = plt.subplots(1,1,figsize=(15,10))
plt.tight_layout()
plt.plot(x, y, marker='.', ms=17, mew=2, linestyle='none')
# Make the same colorbar
norm = cm.colors.Normalize(vmin=0.0, vmax=1.0, clip=False)
cbar = fig.colorbar(cm.ScalarMappable(norm=norm, cmap='rainbow'), ax=ax, extend='both',
orientation='vertical', pad=0.005, use_gridspec=True)
cbar.set_ticks(fake_phase)
cbar.set_ticklabels(fake_labels)
cbar.ax.tick_params(which='major', labelsize='large', width=1.5, length=6)
cbar.set_label(label='Phase', size='xx-large', labelpad=40)
cbar.ax.set_aspect('auto')
ax2 = cbar.ax.twinx()
pos = cbar.ax.get_position()
pos.x0 += 0.1
ax2.set_position(pos)
plt.show();
The output of this code: Output of workable example
My issue is that the secondary axis on the colorbar (left axis) has values that are so close together their labels overlap. I'm hoping to find a way to space the labels so they are readable. I thought I found a way to accomplish this using axis.set_ticklabels() (set_ticklabels() documentation. In the **kargs section of the doc it references using text properties. In the text properties documentation text properties doc the property 'y' says you can set the y-position of the text. However, when I add this keyword to set_ticklabels() I get an error that the keyword is not recognized.. I've tried adding the property 'y' as a keyword and attribute but I get a keyword error or does not have that attribute error...
I'm calling the property wrong but I've never gotten this detailed in editing these parameters. I honestly don't know if this is the best way to solve this, but it's the closest I've gotten so far. I was hoping to use it to offset the labels so they were stacked vertically on top of each other in the same order but far enough apart that the label is readable.
Thanks for any input!

Tkinter both 'sticky' and 'rowconfigure' did not fill the empty space

I have 2 frames inside root which called "header_frame" and "activity_frame" both are in the same column which is "column=0". I want both frames to be resizeable matching its root parent filling all empty space like this :
I have tried all grid config possibilities including setting 'rowconfigure' on 'root', set activity_frame to stick on "North" which is header_frame, last but not least I've also tried to stick header_frame to south which is the result I do not want because those frame share same size (I hope header_frame has 'maxsize' attribute but sadly it didn't have). so this is the code that I've tried :
self.root = root
self.column = ""
self.search = ""
self.root.minsize(500,480)
self.comboboxValue = None
self.root.title("CUCI (CSV Unique Column Identifier)")
self.root.configure(background="powder blue")
self.root.grid_columnconfigure(0,weight=1)
self.root.grid_rowconfigure(0,weight=1)
self.root.grid_rowconfigure(1,weight=1)
#header frame
self.header_frame = tk.Frame(self.root)
self.header_frame.grid(row=0, column=0,sticky="NEW")
self.header_frame.grid_columnconfigure(0,weight=1)
self.header_frame.grid_rowconfigure(0,weight=1)
self.header_frame.configure(background="grey")
#activity Frame
self.activity_frame = tk.Frame(self.root)
self.activity_frame.grid(row=1, column=0,sticky="NEWS")
self.activity_frame.grid_columnconfigure(0,weight=1)
self.activity_frame.grid_rowconfigure(0,weight=1)
self.activity_frame.configure(background="grey",pady=1)
Here's the layout result from my code which I do not expect:
The point is that I want to fill those empty spaces with activity_frame to be stick-ed on 'header_frame'.Please I do not wish to use pack(self.activity_frame.pack(fill=tk.X)). I just want to use grid because it's easy to use
The reason for the gap is because you don't have the header frame stick to the bottom of the space it was given. If you change the sticky attribute for the header to be "nsew" you'll see that the header fills the extra space.
self.header_frame.grid(row=0, column=0,sticky="nesw")
I'm guessing you don't want the header frame to be so tall. If that is the case, give row 0 a weight of 0 instead of 1. That way all extra unallocated space will be given to row 1.
self.root.grid_rowconfigure(0,weight=0)
After doing so, and after adding a couple of other widgets to simulate your screen, this is what it looks like:

Python Docx Table row height

So column width is done using cell width on all cells in one column ike this:
from docx import Document
from docx.shared import Cm
file = /path/to/file/
doc = Document(file)
table = doc.add_table(4,2)
for cell in table.columns[0].cells:
cell.width = Cm(1.85)
however, the row height is done using rows, but I can't remember how I did it last week.
Now I managed to find a way to reference the rows in a table, but can't seem to get back to that way. It is possible to change the height by using the add_row method, but you can't create a table with no rows, so the the top row will always be the default height, which about 1.6cms.
There is a way to access paragraphs without using add_paragraph, does anyone know how to access the rows without using the add_row method because it was that that I used to set row height in a table as a default.
I have tried this but it doesn't work:
row = table.rows
row.height = Cm(0.7)
but although this does not give an error, it also has no effect on the height.
table.rows is a collection, in particular a sequence, so you need to access each row separately:
for row in table.rows:
row.height = Cm(0.7)
Also check out row.height_rule for some related behaviors you have access to:
https://python-docx.readthedocs.io/en/latest/api/table.html#row-objects
When you assign to table.rows.height, it just adds a .height instance attribute that does nothing. It's one of the side-effects of a dynamic language like Python that you encounter a mysterious behavior like this. It goes away as you gain more experience though, at least it has for me :)
Some additional information:
The answer here is correct, but this will give a minimum row height. Using WD_ROW_HEIGHT_RULE.EXACTLY will fix the cell height to the set row height ignoring the contents of the cell, this can result in cropping of the text in an undesirable way.
para = table.cell(0,0).add_paragrph('some text')
SOLUTION:
add_paragraph actually adds a blank line above the text.
Use the following instead to avoid using add_paragraph:
table.cell(0,0).paragraphs[0].text = 'some text'
or using add_run can make it easier to also work with the text:
run = table.cell(0,0).paragraphs[0].add_run('some text')
run.bold = True

two textplots in one plot

I have been trying to work with textplot in R and am unsure if my question is possible or not, I know that par() can't be used to place two textplots in one plot. I have been using a page and this code to try and figure things out.
My question is: Is it possible to have two textplots within the same plot?
For example, in the par(mfrow=c(1,1)) scenario below, plot 1 is a texplot of species length. Say I wanted to replicate that textplot twice in that plot. Is that possible?
based on this site:
http://svitsrv25.epfl.ch/R-doc/library/gplots/html/textplot.html
textplot(version)
data(iris)
par(mfrow=c(1,1))
info <- sapply( split(iris$Sepal.Length, iris$Species),
function(x) round(c(Mean=mean(x), SD=sd(x), N=gdata::nobs(x)),2) )
textplot( info, valign="top" )
title("Sepal Length by Species")
What I want to do is put a second textplot within that plot, underneath the original. For arguments sake, replicating that textplot twice in the plot.
Is this possible?
Thanks!
Maybe you've figured it out in the last four months but I thought I'd chip in an answer anyway.
The code provided is most of the way towards doing what you require already, you just have to provide some additional inputs to title() and/or par(). Namely specify that the title is to be above both of the plots by using title("your title", outer = TRUE) and you can further adjust the position of the title with an option in par(), use par(mfrow = c(2,1), oma = c(0,0,"top",0)). Hopefully this answers your question.
require('gplots')
data(iris)
info <- sapply(split(iris$Sepal.Length, iris$Species),
function(x) round(c(Mean = mean(x), SD = sd(x), N = gdata::nobs(x)),2))
## Replace top with a numerical value to control the position of the title with respect to the
## top of the page.
par(mfrow = c(2,1), oma = c(0,0, top ,0))
textplot(info, valign = "top")
textplot(info, valign = "top")
title("Sepal Length by Species", outer = TRUE)

Resources