I am writing an application on kivy, and I have a problem in the button. The problem is that when you click on the button - it does not work, but there is click in different places (buttons) it will start working
This is my kv code:
Button:
id:add_task
text:"Add"
size_hint:(1,1)
background_color:(135/255,194/255,133/255)
background_normal:''
on_press: root.add_new_task()
And here I implement the change of color and text of the button when you click on it:
def add_new_task(self):
if self.ctrl_add_tast == 0:
self.add_task.text = "Cancel"
self.add_task.background_color = (219/255, 74/255, 74/255)
self.input_add_task.opacity = 1
self.input_add_task.size = (395,175)
self.ctrl_add_tast = 1
elif self.ctrl_add_tast == 1:
self.add_task.text = "Add"
self.add_task.background_color = (135/255, 194/255, 133/255)
self.input_add_task.opacity = 0
self.input_add_task.size = (0,0)
self.ctrl_add_tast = 0
When executing this code, a button appears. When clicked, it changes the color and text.
Everything works as it should, but you need to click on the button in different places to make it work (to be more precise, it is necessary to click on the left, lower and upper sides, about 20 pixels)
And I do not use the "padding" properties in this place
Related
I want to write a simple program to detect simultaneous left and right mouse clicks using tkinter. I referred to the question Detect simultaneous left and right clicks in tkinter gui and made some changes, but came across some problems. Here's the code:
from tkinter import *
def call_back_left(event, v, h):
global left, right
if right:
right = False
else:
left = True
root.after(1000, left_judge_right(v, h))
def left_judge_right(v, h):
global left, right
if left:
print(f'Button on row{v}, column{h}\t\tleft click')
left = False
else:
print(f'Button on row{v}, column{h}\t\tboth clicks')
def call_back_right(event, v, h):
global left, right
if left:
left = False
else:
right = True
root.after(1000, right_judge_left, v, h)
def right_judge_left(v, h):
global left, right
if right:
print(f'Button on row{v}, column{h}\t\tright click')
right = False
else:
pass
left = False
right = False
root = Tk()
vertical, horizontal = 4, 4
map_area = Frame(root, pady=10)
map_area.pack(side=TOP)
for v in range(vertical):
for h in range(horizontal):
button = Button(map_area, text=' ', width=5, height=2)
button.grid(row=v, column=h)
button.bind("<Button-1>", lambda event, i=v, j=h: call_back_left(event, i, j))
button.bind("<Button-3>", lambda event, i=v, j=h: call_back_right(event, i, j))
root.mainloop()
The detection for both clicks sometimes worked but sometimes didn't, so I made the first parameter to the root.after() function to be 1000 microseconds (as shown in the codes).
As I understand, if I run the code above and do left click firstly then right click within 1 second, the function running sequence should be:
call_back_left --> call_back_right --> wait about 1 sec --> left_judge_right --> right_judge_left
And the print outcome should be:
"Button on rowX, columnY both clicks"
However, the result is:
"Button on rowX, columnY left click"
"Button on rowX, columnY right click"
It seemed like the function running sequence is:
call_back_left --> left_judge_right --> wait about 1 sec --> call_back_right --> right_judge_left
Then I tried doing right click firstly and then left click within 1 sec, and it worked fine without any problems.
Please tell me why this problem occurs and how to fix it.
is there any possibility in Kivy to make a button invisible, so that you run the on_press method of the button underneath when you click the first inviseible button?
Edit
class PlayGame(ButtonBehavior, Widget):
button = ObjectProperty(None)
def on_press(self):
do_something()
class PlayButton(Button):
def on_press(self):
if self.opacity == 1:
do_something()
elif self.opacity == 0:
return None
When I run this I can't click on the screen in the area where the button is (even when invisible) to run on_press() of PlayGame root widget.
Yes, make its opacity 0 and override its on_touch_down to do nothing (i.e. returning None, or you can return False if you like).
I am setting the state of the button to "down" in the py file (and later to "normal" on the event of touch_up), but the on_press in the kv file is not working, nothing happens when I click the button. How could I fix this so that I could make things happen when the button is pressed?
Python:
if touch.y/self.height > 0 and touch.y/self.height < 0.155 and 0.5 < touch.x/self.width < 1:
self.results.opacity = 0.5
self.results.state = "down"
#self.manager.current = "sc2"
touch.x = 0
touch.y = 0
Kv:
Button:
id: results
text: "See results"
on_press:
print("hey")
I created a button 'Add InputBox' that will add an input box once the
user presses it since i won't be knowing the number of InputBoxes the
user may require.
These InputBoxes should be arranged vertically such that each one added
will be created at a specific position right below the previous one
without considering the size_hint (even if it's one input box, it
should not cover the screen. If i told it to be at position (0, 10), it
should not span past that position).
I tried the BoxLayout whose first InputBox created covered the
whole screen. The second one takes up 50% of the screen. The 3rd one,
1/3 of the screen and so on.
I checked out the FloatLayout too with the code below:
class NextWindow(Screen):
def __init__(self, **kwargs):
super(NextWindow, self).__init__(**kwargs)
self.count_box = 1
self.layout = FloatLayout()
def addInputBox(self, obj):
inputBox = TextInput(multiline=False,size_hint=(0.2, 0.05),
pos_hint={'top': self.count_box})
if self.count_box < 150:
self.count_box = self.count_box + 10 #Changes the value of the position
self.layout.add_widget(inputBox) #so that the next InputBox is created
else: #under the previous one.
pass #When 14 InputBoxes have been created
At the press of the button
'Add InputBox', the value of self.count_box is changed so that the value of
'top' changes after each call so that the next InputBox goes under the previous one.
This did not take up the whole screen. It displayed just the first InputBox but subsequent ones are not shown on the screen when 'Add InputBox' is pressed.
This stems from a poor understanding of the property pos_hint. A way to carry it out is to ignore pos_hint and supply the actual positional property, 'pos'. The value of 'pos' is changed after every click of the 'Add Course' button.
I'm using the grid technique in Tkinter, Python. The code below runs when the user presses a button. But I can't get it to remove the widgets it created (all of which are on row 5) when the user clicks the button again.
Here is the procedure:
def create_equation(self):
R = int(self.entReactants.get())
for i in range(R):
entRCompound = Entry(self.kcFrame, width=10)
entRCompound.grid(row=5,column=i*2)
entRCompound.config(bg="SpringGreen")
if i == R-1:
lblReverse = GenLabel(self.kcFrame,text=" ⇌ ")
lblReverse.grid(row=5, column=i*2+1)
lblReverse.config(bg="aqua")
else:
lblPlus = GenLabel(self.kcFrame,text=" + ")
lblPlus.grid(row=5, column=i*2+1)
lblPlus.config(bg="aqua")
for i in range(int(self.entProducts.get())):
entPCompound = Entry(self.kcFrame, width=10)
entPCompound.grid(row=5,column=R*2+i*2)
entPCompound.config(bg="orange")
if i != int(self.entProducts.get())-1:
lblPlus = GenLabel(self.kcFrame,text=" + ")
lblPlus.grid(row=5, column=R*2+i*2+1)
lblPlus.config(bg="aqua")
When the button is pressed, I want it to delete the widgets it created when the button was last pressed and create the new set of widgets. This code is executed for the first press of the button as well, so there would not be anything on row 5 before it is pressed.
Any ideas?