Kivy Add Dropdown Programmtically to existing layout - kivy

I would like to add dropdown to a layout that I already have but I'm having issues when I add it. the layout randomly displays the options but not the mainbutton. Is there something am I adding the incorrect widget?
NOTE: I prefer to create my layouts dynamically, so I am not using the kv files. All of the examples I have seen just use the runapp function instead of adding the dropdown to an existing layout.
My Code:
Window.size = (Config.getint('graphics','width'),Config.getint('graphics','height'))
Window.top = 30
Window.left = 10
screen_width = 700
screen_height = 775
Window.clearcolor = color_palette["Royal Purple"]
Window.size = (screen_width,screen_height)
Config.write()
##~ dropdown function ~##
def createDropDown():
dropdown = DropDown()
categories = ['Cat1','Cat2','Cat3','Cat4']
for index in range(len(categories)):
btn = Button(text=categories[index], size_hint_y=None, height=44)
btn.bind(on_release=lambda btn: dropdown.select(btn.text))
dropdown.add_widget(btn)
mainbutton = Button(text='Hello', size_hint=(None, None))
mainbutton.bind(on_release=dropdown.open)
dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
return dropdown
##~~ My main layout class ~~##
class SimpleKivy0(App):
App.title = "New GUI"
btn_width = 0.2
btn_height = 0.05
txt_fld1 = None
entry_fld_Label = None
def build(self):
layout = FloatLayout()
banner_bground = layout.canvas.before
with banner_bground:
Rectangle(pos=(0,screen_height-(screen_height*0.1)),size=(screen_width, screen_height*0.1))
Color(68/255,210/255,201/255,1)
banner_Lbl = Label(text='Quick Query GUI',halign='left',valign='middle',font_size=((screen_height*0.1)*0.7),pos=(0,screen_height-(screen_height*0.1)),size_hint=(1,0.1))
banner_Lbl.bind(size=banner_Lbl.setter('text_size'))
layout.canvas.add(banner_bground)
layout.add_widget(banner_Lbl)
dropdown = createDropDown()
dropdown.size_hint=(.25,.1)
dropdown.pos = (screen_width*0.2,screen_height*0.2)
return layout
if __name__ == "__main__":
SimpleKivy0().run()
The screenshot:

The main thing you were missing is to add the mainbutton to your layout. Here is a working version of some of your code:
def createDropDown(layout):
dropdown = DropDown()
categories = ['Cat1','Cat2','Cat3','Cat4']
for index in range(len(categories)):
btn = Button(text=categories[index], size_hint=(None, None), size=(100,44))
btn.bind(on_release=lambda btn: dropdown.select(btn.text))
dropdown.add_widget(btn)
mainbutton = Button(text='Hello', size_hint=(None, None), size=(100,40), pos=(100,100))
mainbutton.bind(on_release=dropdown.open)
dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
# Add mainbutton to the layout
layout.add_widget(mainbutton)
##~~ My main layout class ~~##
class SimpleKivy0(App):
App.title = "New GUI"
btn_width = 0.2
btn_height = 0.05
txt_fld1 = None
entry_fld_Label = None
def build(self):
layout = FloatLayout()
banner_bground = layout.canvas.before
with banner_bground:
Rectangle(pos=(0,screen_height-(screen_height*0.1)),size=(screen_width, screen_height*0.1))
Color(68/255,210/255,201/255,1)
banner_Lbl = Label(text='Quick Query GUI',halign='left',valign='middle',font_size=((screen_height*0.1)*0.7),pos=(0,screen_height-(screen_height*0.1)),size_hint=(1,0.1))
banner_Lbl.bind(size=banner_Lbl.setter('text_size'))
layout.canvas.add(banner_bground)
layout.add_widget(banner_Lbl)
# create the dropdown and add the mainbutton to the layout
createDropDown(layout)
return layout

For those who are also having an issue with this, I came across an alternative called a spinner. The spinner object worked the same as I intended for the popup.
This is the code I added instead of the dropdown:
def get_spinner_selection(spinner,text):
print(text)
spinner = Spinner(text='Option1',values=('Option1','Option2','Option3'),size_hint=(0.2,0.1),background_color=(169/255,80/255,18/255,1))
spinner.bind(text=get_spinner_selection)
layout.add_widget(spinner)
queryType_Lbl = Label(text='Query Type:',valign='middle',size_hint=self.spinner.size_hint,pos=(spinner.x,spinner.top))

Related

Why is MediumTopAppBar (and Large) showing two TextField in compose?

I am trying to make the title of a screen editable.
MediumTopAppBar(
title = {
val name: String? = "Some Title"
var input by remember { mutableStateOf(name ?: "") }
when (state.isEditingTitle) {
true ->
TextField(
value = input,
onValueChange = { input = it },
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {
callbacks.onEditTitleChange(editTitle = false, updatedTitle = input)
})
)
false -> {
Text(
modifier = Modifier.clickable { callbacks.onEditTitleChange(true, null) },
text = name ?: "(No Title)"
)
}
}
},
... more app bar parameters
}
When I click on the title Text(...) and the view gets recomposed the AppBar shows two TextFields
How do I ignore the top one and only show the one in the bottom, like the Text() is only shown in the bottom?
(Fyi: the two TextInputs have their own remembered state and calls the callback with their own respective value)
Bonus question: How do I handle the remembered state "input" so that it resets every time the onDone keyboard action is triggered? Instead of val name: String? = "Some Title" it would of course be something in the line of val name: String? = state.stateModel.title
I found out why it does this, but I have no idea how to solve it (except for just making my own views and placing it close by)
It's easy to see when looking at the function for the MediumTopBar
// androidx.compose.material3.AppBar.kt
#ExperimentalMaterial3Api
#Composable
fun MediumTopAppBar(
title: #Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: #Composable () -> Unit = {},
actions: #Composable RowScope.() -> Unit = {},
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TwoRowsTopAppBar(
modifier = modifier,
title = title,
titleTextStyle = MaterialTheme.typography.fromToken(TopAppBarMediumTokens.HeadlineFont),
smallTitleTextStyle = MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
titleBottomPadding = MediumTitleBottomPadding,
smallTitle = title, // <- this thing, right here
navigationIcon = navigationIcon,
actions = actions,
colors = colors,
windowInsets = windowInsets,
maxHeight = TopAppBarMediumTokens.ContainerHeight,
pinnedHeight = TopAppBarSmallTokens.ContainerHeight,
scrollBehavior = scrollBehavior
)
}
There's some internal state shenanigans going on, probably checking for a Text being shown in the 2nd TopAppBarLayout (more digging required to find that), but not for any other view.
TwoRowsTopAppBar and TopAppBarLayout are not public, and can't be used directly.
This is explains why, but it would be interesting to see how to solve it (still using Medium or Large -TopAppBar)
it is stupid thing devs overlooked and should be warned against, at least. The answer is do not give default colors to your Typography TextStyles.
private val BodySmall = TextStyle(
fontSize = 10.sp,
lineHeight = 12.sp,
fontWeight = FontWeight.SemiBold,
fontFamily = Manrope,
color = Color.Black // REMOVE THIS
)
val OurTypography = Typography(
...
bodySmall = BodySmall
)

I am working on the auto suggestion list box the logic is good

I am working on the project the application is working fine
but small issue with list box,
I created a class where we can call get suggestion from the entry data a sample code is given below
from tkinter import *
root = Tk()
root.geometry('300x300')
search = StringVar()
search1 = StringVar()
search_list = ["Apple", "Ball", "cat", "dog"]
Label(root, text="Search :").pack(pady=15)
search1_ent = Entry(root, textvariable=search)
search1_ent.pack(pady=15)
search2_ent = Entry(root, textvariable=search1)
search2_ent.pack(pady=15)
list_box = Listbox(root, height=10, width=20)
EntryList.EntryBoxListLink(search_list, list_box, search1_ent, search, 90, 87, 20)
root.mainloop()
I created a py file on the name Entry list in that created a class Entry box list link,
It may not be perfect code but worked fine.
the class code is
import contextlib
from tkinter import *
class EntryBoxListLink:
"""this class is created to link entry box and the listbox"""
def __init__(self, list_data='', list_box='', entry_box=None, set_variable='', x_axis=38, y_axis=52, width=20,
next_entry=None):
self.list_data = list_data
self.list_box = list_box
self.entry_box = entry_box
self.set_variable = set_variable
self.x_axis = x_axis
self.y_axis = y_axis
self.width = width
def destroyListBox(event):
"""this is the command when the list box to place forget"""
with contextlib.suppress(BaseException):
self.list_box.place_forget()
def searchIList(event):
"""this gives the list box where the data no are aligned"""
self.list_box.config(width=self.width)
self.list_box.place(x=self.x_axis, y=self.y_axis)
self.list_box.bind('<Leave>', destroyListBox)
self.list_box.bind('<Double-1>', itemsSelected)
self.list_box.bind('<Return>', itemsSelected)
if self.list_data is not None:
match = [i for i in self.list_data if
(self.set_variable.get().lower() or self.set_variable.get().capitalize()) in i]
self.list_box.delete(0, END)
for c in match:
try:
self.list_box.insert(END, c.title())
except BaseException:
self.list_box.insert(END, c)
if not match:
destroyListBox(None)
if self.set_variable.get() == "":
destroyListBox(None)
def itemsSelected(event):
"""when the no is selected from list box it aligned to
the phone number and gives the data"""
for i in self.list_box.curselection():
self.set_variable.set(self.list_box.get(i))
self.entry_box.focus_set()
destroyListBox(None)
if next_entry is not None:
next_entry.focus()
def set_entry_focus(event):
if list_box.curselection()[0] == 0:
return self.entry_box.focus_set()
def focusAndSelect():
self.list_box.focus_set()
self.list_box.select_set(0)
self.entry_box.bind("<KeyRelease>", searchIList)
self.entry_box.bind("<Down>", lambda event: focusAndSelect())
self.list_box.bind("<Up>", set_entry_focus)
the issue is when I select the second entry box the list box should be gone,
to be more frank when the search1 and listbox are not in focus the list box should be place forget!

minimum_height doesn't work in a Layout inside .py (only work in .kv)?

I've tried to make a program that uses a scroll, I tried with RecycleView
class TestApp(App):
def build(self):
rc = RecycleView()
box = BoxLayout(orientation="vertical", size_hint_y=None)
b1 = Button(text="1", size_hint_y=None, height=500)
b2 = Button(text="2", size_hint_y=None, height=500)
b3 = Button(text="3", size_hint_y=None, height=500)
box.add_widget(b1)
box.add_widget(b2)
box.add_widget(b3)
box.height = box.minimum_height
rc.add_widget(box)
return rc
if __name__ == '__main__':
TestApp().run()
I was expected that I was able to use the scroll, but the minimum_height seems that is always 0, and I don't want to give the exact height number by hand.
Thank you so much
You have to bind minimum_height to the height using setter as follow:
box.bind(minimum_height=box.setter('height'))
Snippets - py file
def build(self):
rc = RecycleView()
box = BoxLayout(orientation="vertical", size_hint_y=None)
...
box.bind(minimum_height=box.setter('height'))
rc.add_widget(box)
return rc
Output

Synchronizing Tooltips over multiple plots bokeh

I have created a grid plot using bokeh consisting of multiple vertically stacked line charts senter code hereharing same X axis.My requirement is to have a tooltip displayed on all the charts on hovering over a point on one of the charts.Tried multiple ways, but couldn't find a solution.It would be great if someone out there assist me in resolving this issue.
from bokeh.palettes import RdBu3, RdYlGn3
from bokeh.plotting import figure, output_notebook, show
from bokeh.io import show
from bokeh.models import ColumnDataSource, BoxAnnotation, Button, HoverTool, Text, Circle
from bokeh.models.callbacks import CustomJS
from bokeh.layouts import column, gridplot
from bokeh.models.widgets import TextInput, Div, Select
output_notebook()
#Main Data Source
source = ColumnDataSource(df)
#Filtering the data source based on some condition
df1 = df[Some_Condition]
#Filtered Data Source
sc = ColumnDataSource(df1)
#Callback to be executed on selecting a value from Select widget
callback_select = CustomJS(args=dict(source=source, sc=sc),code="""
var indices = [];
var val = cb_obj.value
sc.data['xx'] = []
sc.data['yy'] = []
sc.data['Date'] = []
for (var i = 0; i < source.get_length(); i++){
if (source.data['ZZ'][i] == val){
sc.data['xx'].push(source.data['xx'][i])
sc.data['yy'].push(source.data['yy'][i])
sc.data['Date'].push(source.data['Date'][i])
} else {
}
}
sc.change.emit();
""")
#Select Widget
select = Select(title="ZZ:", value="Select", options=["Opt1", "Opt2", "Opt3"], callback = callback_select)
#Tooltips to be displayed
TOOLTIPS = [("Value: ", "#{xx}")]
TOOLTIPS1 = [("Value: ", "#{yy}")]
#Tools to be shown on plot
_tools_to_show = 'box_zoom,pan,save,reset,tap,wheel_zoom,crosshair'
#First Chart
p1 = figure(x_axis_type="datetime", plot_height=200, tools = _tools_to_show)
p1.xaxis.visible = False
p1.xgrid.grid_line_color=None
p1.ygrid.grid_line_alpha=0.5
p1.xaxis.axis_label = 'Date'
p1.yaxis.axis_label = 'xx'
#Second Chart
p2 = figure(x_axis_type="datetime", plot_height=200, tools = _tools_to_show)
p2.xgrid.grid_line_color=None
p2.ygrid.grid_line_alpha=0.5
p2.xaxis.axis_label = 'Date'
p2.yaxis.axis_label = 'yy'
#Line charts
c11 = p1.line(x='Date', y='xx', source = sc, color = "green")
c12 = p1.circle(x='Date', y='xx', source = sc)
c21 = p2.line(x='Date', y='yy', source = sc, color = "blue")
c22 = p2.circle(x='Date', y='yy', source = sc)
#Text to be displayed over points on the charts.
visible_text1 = Text(x='Date', y='xx', text='xx', text_color='black', text_alpha=0.5)
visible_text2 = Text(x='Date', y='yy', text='yy', text_color='black', text_alpha=0.5)
#Adding text to the graphs
crt1 = p1.add_glyph(sc, visible_text, selection_glyph=visible_text1)
crt2 = p2.add_glyph(sc, visible_text2, selection_glyph=visible_text2)
#This piece of code does display multiple tooltips but shows vague behaviour viz. displaying a tooltip where there is no glyph
hover1 = HoverTool(renderers=[c12, c22], tooltips = TOOLTIPS)
hover2 = HoverTool(renderers=[c22, c12], tooltips = TOOLTIPS1)
#Adding hover tools
p1.add_tools(hover1)
p2.add_tools(hover2)
#Creating a grid for plotting
grid = gridplot([select, p1, p2, p3, p4], ncols=1, plot_width=1000, plot_height=1000)
show(grid)
As of Bokeh 1.2 there is not a good way to accomplish this. There is an open issue about this on GitHub #1547 - Coordinate tooltips across multiple plots that you can follow for updates or add your voice to.

How can I add a fontsize selector in typo3 6.2?

I want to add a fontsize selector in typo3 6.2. so I have created the following three files:
fontsize_normal.css
fontsize_medium.css
fontsize_large.css
and the relevant typoscript settings looks as follows:
config {
linkVars = L(0-2)
uniqueLinkVars = 1
}
obj.fontsize = COA
obj.fontsize {
1 = TEXT
1.wrap = <div>|</div>
1.value = A
1.value.typolink.parameter.data = page:uid
1.value.typolink.additionalParams = &L=0
2 < .1
2.wrap = <div>|</div>
2.value = A+
2.value.typolink.additionalParams = &L=1
3 < .1
3.wrap = <div>|</div>
3.value = A++
3.value.typolink.additionalParams = &L=2
}
But if I include the css I am getting a blank screen, so something should be wrong
page = PAGE
page {
includeCSS {
[globalVar = GP:L = 0]
selectorcss = fileadmin/system/Public/Css/fontsize_normal.css
[globalVar = GP:L = 1]
selectorcss = fileadmin/system/Public/Css/fontsize_medium.css
[globalVar = GP:L = 2]
selectorcss = fileadmin/system/Public/Css/fontsize_large.css
[global]
}
}
Multiple problems here :
'L' is used as the language variable. Using this (without disabling it) will conflict with TYPO3's languages selection. You will need to create your own variable.
Conditions can not be used INSIDE your typoscript:
[globalVar = GP:L = 0]
page = PAGE
page {
includeCSS {
selectorcss = fileadmin/system/Public/Css/fontsize_normal.css
}
}
[global]
Aldo you can create a font size selector with typoscript, I think a javascript approach would be much easier and flexible.
It will give you the option to manipulate your DOM (or replacing your stylesheet, or loading a new stylesheet, or setting a new body font-size , etc ...) and you can safe your settings in a cooky for further use.
On a usability point of view, Font-size selectors are obsolete: Users can set there own font size in a browser & font-sizes should be relative (using em's instead of px)..

Resources