I would like to straighten my layout I made with pySimpleGUI. In the documentation, I found the Element Sizer which allows to specify a size in pixels. This does not seem to work easily with all other Elements which use a different measure for size (character width/height?). So if I create a layout like the following:
layout = [
[sg.Sizer(0,10), sg.Button("Test", size=(7,1))],
[sg.Text(size=(0,10)), sg.Button("Test", size=(7,1))]
]
The resulting window looks like this, with two unaligned buttons:
Is there a way to convert the "standard measure" used in most Elements to pixels? Or is simply using empty Text Elements best practise for this use case?
Related
I have a QtWidget, built in QtCreator. Let's say there are 10 QLineEdits in the widget named Edit0 to Edit9. The data that is supposed to go in them is stored in a Python list data. Is there a way to put those 10 QLineEdits in a Python list so I can basically assign their values like:
for index in range(len(data)):
Edit[index].setText('{:.2}'.format(data[index]))
Since you're using python, you can access fields via string:
for index in range(len(data)):
getattr(ui, f"Edit{index}").setText('{:.2}'.format(data[index]))
But relying on the name is an ugly style.
You can also iterate over the layout which contains the edits.
Here is how to do it in C++, the method names are the same in python.
But that becomes ugly if you want to add something else to the layout, e.g., a Button.
Neither of these methods do scale.
If you have many edits in a fixed pattern, you should consider creating them yourself with your code and put them in a list in the first place.
edits = []
for index in range(42):
edit = QLineEdit()
edits.append(edit)
ui.some_layout.addWidget(edit) # add edit to the layout
# later:
for edit, data in zip(edits, data):
edit.setText('{:.2}'.format(data[index]))
However, it seems to me like you're building a table.
Do you know QListWidget, QTableWidget, QListView and QTableView?
So I'm new to tkinter, but I've got what I want working, up to a certain point.
I'm not sure I've set it up correctly, but I've got a world map with buttons on the right, and an events log on the left, which fills up with labels as stuff happens.
Issue is that after a little while, the whole log fills up.
What is the best way to delete all the labels, or maybe delete the oldest (top) label each time?
Here's what I mean:
Defined here:
root=Tk()
Map=PhotoImage(file="C:/Users/Willam/Desktop/CWProgram/map2.gif")
background=Label(root,image=Map).place(x=100,y=0,relwidth=1,relheight=1)
Title=Label(root,text=' LOG').pack(anchor=NW)
And I create my labels like this:
info=Label(root,text='Select a sector to move units from',wraplength=170)
info.pack(anchor=NW)
I tried the usual info.destoy() and info.forget(), but these only work on the last label used in that function.
Should I have grouped all labels or something?
As PM 2Ring suggested it is usually useful to append labels to a list for future ref:
tmp = Label(...)
labels.append(tmp)
then just:
foreach label in labels: label.destroy()
If you do not want a list, and you're sure you want to clear everything in root:
foreach label in root.children.values(): label.destroy()
The children dict always holds the objects contained within. If you want to keep the map label, you will have to make your own list as I showed, without appending info into it.
I would recommend using:
info.pack_forget()
For each pack you created you must do it in the format:
packname.pack_forget()
Which if you have a lot of packs is impractical, but otherwise it works very well.
This also makes it very easy to selectively remove some labels and leave others as it will not purge all packs that you placed.
Just use:
root.children.clear
After clearing screen just input map and functions again...
I am trying to create a roguelike using the Text widget.
I have figured out a few things, namely that I can set the size of the widget using width and height options and that I can find the pixel height or width of said widget. However, what I want to do is have the widget resizable (pack(expand="yes", fill="both")) but be able to refresh the displayed text on a resize. Is there a way to get the character dimensions when the widget is running without resorting to winfo_width() and math based on pixel dimensions of characters?
I've run into that exact same problem a couple times jaccarmac, and to my knowledge there is no way to find the width of a string of characters. Really the only way is to use the winfo_ commands: width, height, geometry. However, it kind of sounds like you just want to make sure that all of the text is displayed if you change the label and add more text. If that is the case, you don't have to worry about it. That should all be taken care of by the widgets themselves. If you don't see them expanding to show all of your label, that usually means one of the widgets containing that label is not set to expand (either using expand=YES with .pack, or columnconfigure(i, weight=1) for .grid).
A final thought; in the pack arguments make sure it's YES, and not "yes". That uppercase YES is not a string, but a variable name defined by Tkinter.
There is no way to automatically get the width in characters, but it's easy to calculate, assuming you're using a fixed width font. One way to do this is to use the font_measure method of a font object. Use font_measure to get the width of a '0' (or any other character for that matter; I think tk users zero internally, not that it matters with a fixed width font), then use this in your calculations.
This is an old question, but after doing some research I've found that there actually is a way to get height/width info directly without maths or playing with font widths using the Text widget's cget() method:
text_widget = tk.Text()
width_in_char = text_widget.cget('width')
height_in_char = text_wdiget.cget('height')
Since the Text widget stores its height and width configuration in characters, simply querying for those parameters will give you what you're looking for.
I try to put sixteen checkbuttons into frame, placing them into four columns like:
c1 = Tkinter.Checkbutton(group.interior(), text = 'Name', indicatoron= 1, variable = self.Checkvar_nr, command=cb)
c1.(row = 0, column = 0)
and so on up to:
c16.(row = 3, column = 3)
Everything's fine except columns vertical alignment because of the differences in the length of the text used.
How to align then horizontally?
I don't quite understand the problem, since columns must be vertically aligned since it's a grid. I think what you're saying is that the items in each column aren't aligned to a column boundary. Try using sticky='w' when adding each checkbutton to the grid. This will cause them to "stick" to the left edge of the column.
As an option, try placing each element in a non-stretchable graphic element.
The thought is that the layout manager is maximizing the use of the screen real estate. Because you want to take up more space, which is contrary to the layout manager's algorithm, you will need to find a graphic container that doesn't "change size".
Sometimes you can do this through manually editing the text string (less preferred). Other times you can use a table like structure (HTML for instance). Other times you can use a frame with defined width and height attributes. These frames are then placed inside of the columns as elements.
Note: It's been a long time since I played with Tk. I'm going by memory. Best of luck!
(edit:) Going from memory, the columns will adjust their width based on content. If there are several three character labels in the first column and five character labels in the second column, the width of the two columns will be different. (Note: This will be depended on the layout manager.) If there is a 'fixed width' option for the layout manager in question, then it should keep all column widths the same.
With layout managers that rearrange with dimensions based on content (HTML, CSS, etc), it is sometimes necessary to place the content inside "immovable" containers. Usually these are frames. The frames work as bounding boxes. This approach works when the element that needs to have a width and height does not have that feature.
I'm trying to change the alternating background color of a treeview. I know that this should normally be left up to the theme, but I'd like to override to test the gtk Style functionality. According to the treeview documentation here, I learned that the TreeView has several style options that are Read-only, including "even-row-color", "odd-row-color" and "allow-rules"(which according to the documentation, allows drawing of even and odd row colors). And I know that in order to override those Read-only settings I've got to change the style in a gtkrc-style file or string.
So my string for a treeview looks like:
gtk.rc_parse_string( """
style "custom-treestyle"{
GtkTreeView::odd-row-color = "#00CBFF"
GtkTreeView::even-row-color = "#90EE90"
GtkTreeView::allow-rules = 1
}
widget "*custom_treeview*" style "custom-treestyle"
""")
treeview.set_name("custom_treeview" )
This parses without error and the result is that the even-row-color gets applied to both even and odd rows.
EDIT: I discovered from some more testing that my parse string must be getting overridden from some other style settings.
print treeview.style_get_property( 'allow-rules' )
print treeview.style_get_property( 'odd-row-color')
print treeview.style_get_property( 'even-row-color')
Gives the result:
True
None
None
Which are all default settings. Normally I would think that it's simply not parsing the string and setting the appropriate values, but in this case the background color does change to the color I specified( only it paints every row's background to one color).
What am I doing wrong?
I finally figured out my issue with this styling method.
The 'allow-rules' style property isn't the only property that tells the treeview to color the rows in alternating colors. According to the documentation, the treeview has another property that hints to the engine that it should draw rows in alternating colors. The 'rules-hint' property, False by default, when True successfully colors my TreeView in alternating odd/even row colors!
So, in code, add this line to the code in the question:
treeview.set_rules_hint( True )
And that's it, a TreeView with alternating colored rows!