Header Widget in Gtk.TreeViewColumn - font-size

There is a Treeview with several TreeViewColumns. Because the default font-size is to big for my usage, I need to set the font-size in the TreeViewColumn Header.
I tried to following:
tvc = Gtk.TreeViewColumn()
tvcl = Gtk.Label("Test")
tvc.set_widget(tvcl)
But the Header of the Column is empty then.
If it's possible to change the font of the TreeViewColumn().title, this would be enaugh.

Assuming you're using python (from the code), here's an example:
from gi.repository import Gtk
from gi.repository import Pango
tvc = Gtk.TreeViewColumn (None, renderer, col)
custom_header = Gtk.Label ('Test')
tvc.set_widget (custom_header)
tvc.get_widget ().override_font (Pango.FontDescription.from_string ('8') )
tvc.get_widget ().show_all ()

Related

resize listbox in PySimpleGui based on length of list

I'm trying to update the Listbox in PySimpleGUI to resize based on length of list but the update(size=len(mylist) says that size is not an allowed argument. Any work around to this?
I've seen some people try to make the window/layout into a function but I'm not sure if that's the right approach.
Thanks in advance.
Basically, the height or the width of a Listbox element should not be revised after initialized, or the size of window will be also changed and maybe out of screen.
There's no option provided to change the height or the width of the Listbox element in PySimpleGUI, but you can do it by tkinter code, element.Widget.configure(height=height, width=width).
Example Code
import PySimpleGUI as sg
name_list = sorted(['James', 'Robert', 'John', 'Michael', 'David', 'William', 'Richard', 'Joseph', 'Thomas', 'Charles'])
layout = [
[sg.Input('', key='Name'), sg.Button('Add')],
[sg.Listbox(name_list, size=(20, len(name_list)), expand_x=True, key='Names')],
]
window = sg.Window('Title', layout, finalize=True)
window['Name'].bind('<Return>', ' Return')
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event in ('Add', 'Name Return'):
name = values['Name']
if name and name not in name_list:
name_list = sorted(name_list+[name])
window['Names'].Widget.configure(height=len(name_list))
window['Names'].update(values=name_list)
window.move_to_center()
window.close()

Since update from vaadin 22 to 23 appending a element to the shadow root breaks the component

Original Question
I want to add a loading indicator overlay to the grid.
I tried to append the overlay element to the shadow root by using the attachShadow method.
The following code works well in vaadin 22.
final Grid<String> grid = new Grid<>();
final Element element = new Element("div");
element.setText("Hello");
add(grid);
grid.getElement().attachShadow().appendChild(element);
When I execute the same code in vaadin 23 it breaks the component.
Alternative solution
I tried to extend the grid component on the client side with the following typescript code
import { Grid } from "#vaadin/grid";
export class CustomGrid extends Grid {
static get is() {
return 'custom-grid';
}
}
customElements.define(CustomGrid.is, CustomGrid);
To use my custom grid in flow, I have extended the flow Grid class and added my custom typescript code with the #JsModule annotation.
#Tag("custom-grid")
#JsModule("./src/custom-grid/custom-grid.ts")
public class CustomGrid<T> extends Grid<T> {
}
I used the following code to add my custom grid to the layout
final CustomGrid<String> grid = new CustomGrid<>();
grid.addColumn(s -> s).setHeader("Hello");
grid.setItems(List.of("Item 1", "Item 2", "Item 3"));
add(grid);
The problem
The items are not visible. There are just blank rows.
ps: extending other components like buttons or comboboxes works pretty well.
I faced the same issue with my own customization of Vaadin's Grid.
I did exactly the same as you - and it worked with v22 but it does not with v23.
Although it's a dirty hack, it works by doing the follwing:
final Grid<String> grid = new Grid<>();
add(grid);
grid.getElement().executeJs("elem = document.createElement(\"div\"); elem.innerHTML=\"Hallo\"; this.shadowRoot.appendChild(elem);");

How to make text in vaadin Grid cell to wrap

I need to make Vaadin 8 Grid cell text wrap. I tried to follow this link in Vaadin Forum.
https://vaadin.com/forum/thread/16908210/vaadin-8-grid-wrap-long-lines
My Grid contains Strings only in every cell.
I have a StyleGenerator class like this:
public class MyGridStyleGenerator<ArrayList> implements StyleGenerator {
public String apply(Object item) {
return ".m-grid-cell-wrapper";
}
}
I am converting from Vaadin 6 so I still use old theme ("../reindeer/legacy-styles.css")
In my styles.css file, there is:
.m-grid-cell-wrapper {
word-wrap: break-word;
white-space: normal;
}
In the class that creates the Grid, I have:
Grid<List<String>> table = new Grid<>("My Test Grid");
//skip setting items code since the cell content shows up fine.
MyGridStyleGenerator style = new MyGridStyleGenerator();
table.setStyleGenerator(style);
table.setBodyRowHeight(35); // more than two lines of text height
I set each column width to a fixed value using setWidth() of Grid.Column so that more columns can be displayed in the given window.
The problem is that when the Grid is displayed, text longer than column width does not wrap.
What did I miss?
Thanks for any advice.
BTW, there is another question on this topic in Stack Overflow where the answer is to use label.setStyleName(ValoTheme.LAYOUT_HORIZONTAL_WRAPPING);
I don't have Label and don't use Valo style.
The CSS class controlling the Grid cell is .v-grid-cell, so I added the following in my styles.css file.
.v-grid-cell {
white-space: normal; }
This caused the text in Grid cell to wrap.

How do I show a lot of text using Vaadin?

I need to process some data and show processing logs on a webpage. (Around 300 lines of text).
I tried to use labels. At first it worked fine - page became scrollable and all text could be seen. But after around 100 labels page became unresponsive.
How to manage this task?
(I tried to look for some other components on webcomponents.org but couldn't find anything.)
TextArea
I tried one of the approaches mentioned in Answer by Leif Åstrand, using TextArea.
When I preload with 300 short lines, no problem. Clicking a button to add 10 more lines at a time works without a hitch. Using the web browser’s window scroll bar to scroll up and down works smoothly.
I used Vaadin 10.0.4 with Java 10.0.1 (Zulu by Azul Systems), in browser Safari 11.1.2 on macOS High Sierra on an external 4K monitor hooked up to a MacBook Pro Retina.
Here is the entire Vaadin app.
package com.basilbourque.example;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.router.Route;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* The main view contains a button and a template element.
*/
#HtmlImport ( "styles/shared-styles.html" )
#Route ( "" )
public class MainView extends VerticalLayout {
TextArea textArea;
// Constructor.
public MainView () {
this.setWidth( "100%" );
this.textArea = new TextArea( "Logs" );
this.textArea.setWidth( "100%" );
this.textArea.setReadOnly( true );
this.appendRows( 300 );
Button button = new Button( "Add 10 more rows" , event -> {
this.appendRows( 10 );
} );
this.add( button , this.textArea );
this.setClassName( "main-layout" );
}
private void appendRows ( int countRows ) {
List< String > entries = new ArrayList<>( countRows );
for ( int i = 1 ; i <= countRows ; i++ ) {
entries.add( Instant.now().toString() );
}
Collections.reverse( entries ); // Put newest on top.
String s = entries.stream().collect( Collectors.joining( "\n" ) );
textArea.setValue( s + "\n" + this.textArea.getValue() );
}
}
You can put all the text in only one component instead of creating a separate component for each line. If you want line breaks (i.e. \n) in the text to wrap to the next line, you can adjust the white-space CSS property for the element to be e.g. pre-line or pre-wrap instead. You can do this using component.getElement().getStyle().set("white-space", "pre-wrap").
Another alternative if you want to visually indicate the status of the text might be a readonly TextArea component.
I would also recommend using the Span component instead of Label in Vaadin 10. Label is using the <label> element in the browser which is actually only intended for labeling input fields, but not for general purpose chucks of text.

on_touch_down problems with dynamic created widgets in kivy

I'm new to kivy and need some assistance with the following problem. I adding numbers/operators as widgets (labels) dynamically and at a random position to a layout(FloatLayout). The idea is that when I clicked on a number/operator it will draw a circle around the number/operator. I get some very strange behaviour. Does not matter what number/operator I click the selection circle is only drawn around the last added label. Then to confuse me even more the other number/operator is circled if I press on some random point on the screen
following is the core of my code:
class SelectedObject(Label):
selected = BooleanProperty()
refresh = BooleanProperty()
def __init__(self, **kwargs):
super(SelectedObject, self).__init__(**kwargs)
self.center_x = randint(0, Window.width/2)
self.center_y = randint(0, Window.height/2)
self.bind( refresh = self.redraw )
def redraw(self, *args):
#print('Redraw for: ' + self)
self.canvas.after.clear()
if self.selected:
with self.canvas.after:
Line(circle=(self.center_x, self.center_y, 20))
self.canvas.ask_update()
def on_touch_down(self, touch):
print("touch#: " + str(touch))
if not self.collide_point(touch.x, touch.y):
return False
print("yip: " + self)
self.selected = not self.selected
self.refresh = not self.refresh # force a redraw
return True
class GameNumber(SelectedObject):
pass
class Operator(SelectedObject):
pass
class GameApp(App):
numberArr = ListProperty([])
operatorArr = ListProperty([])
def build(self):
f = FloatLayout()
#populate numberArr and operatorArr
self.buildLevel()
for number in self.numberArr:
numberItem = GameNumber(text = str(number))
f.add_widget(numberItem)
for operator in self.operatorArr:
f.add_widget(Operator(text = operator))
return f
The problem here is that you have not set sizes to the labels. So each label takes up as much space as it can and the last label being on top, it gets the circle.
You need to pass each GameNumber and Operator some sort of size_hint and/or size. For example, if you want each label to be 10 by 10, you can do something like this: numberItem = GameNumber(text=str(number), size_hint=(None, None), size=(10, 10)). You can set their size relative to the window size by for example setting size_hint=(0.1, 0.1).
Remember that size_hint is always (1, 1) by default, so you need to change it something else if you want your widgets to be smaller than the space of the container and set size_hint=(None, None) if you want to set a fixed size yourself.
If you want to position the labels randomly around the screen, take a look at pos_hint, which is more convenient than playing with the size of the window directly. Also, remember that there's a chance that multiple labels might get on top of each other or at the very borders of the window or even outside if you are not careful.
EDIT: To help you find the source of these kind of problems (that usually relate to layout issues), take a look at Kivy Widget Area Display

Resources