I am attempting to have a functioning back button to take user back to the main screen, seen below as 'Social', but cannot seem to make it function. I have tried multiple solutions that I've found on this site and some others, but haven't seemed to fix the issue yet.
I have tried multiple solutions that I've found on this site and some others, but haven't seemed to fix the issue yet. I am trying to avoid a Kivy file currently, but have accepted that at some point I'm going to have to make one.
#Main Screen
class Social(GridLayout):
title = "Welcome To PedaShield"
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.cols = 3
#FB 'Icon'
self.facebook = Button(text="Facebook")
self.facebook.bind(on_press=self.fb_signin)
self.add_widget(self.facebook)
#Button for Facebook Screen
def fb_signin(self, instance):
datastop.screen_manager.current = "FBSignin"
#Create FB sign-in screen w/ options
class FBSignin(GridLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.cols = 4
if os.path.isfile("fbprev_details.txt"):
with open("fbprev_details.txt", "r") as f:
d = f.read().split(",")
prev_username = d[0]
prev_password = d[1]
else:
prev_username = ""
prev_password = ""
#row 1
self.add_widget(Label())
self.add_widget(Label(text="Username: "))
self.username = TextInput(text=prev_username, multiline=False)
self.add_widget(self.username)
self.add_widget(Label())
#row 2
self.add_widget(Label())
self.add_widget(Label(text="Password: "))
self.password = TextInput(text=prev_password, multiline=False)
self.add_widget(self.password)
self.add_widget(Label())
#row 3 include checkbox for saving signin
self.add_widget(Label())
self.signin = Button(text="Sign In")
self.signin.bind(on_press=self.signin_button)
self.add_widget(self.signin)
self.goback = Button(text="Back")
self.signin.bind(on_press=self.go_back)
self.add_widget(self.goback)
self.add_widget(Label())
#sign-in button
def signin_button(self, instance):
username = self.username.text
password = self.password.text
print("Signing in as {username}")
with open("fbprev_details.txt","w") as f:
f.write(f"{username},{password}")
#Back button
def go_back(self, instance):
print('Here')
datastop.screen_manager.current = "Social"
class PedaShield(App):
title = "PedaShield"
def build(self):
self.screen_manager = ScreenManager()
#Main screen with Social Media Options
self.Social = Social()
screen = Screen(name='Social')
screen.add_widget(self.Social)
self.screen_manager.add_widget(screen)
#Facebook sign in/option page
self.fb_signin = FBSignin()
screen = Screen(name="FBSignin")
screen.add_widget(self.fb_signin)
self.screen_manager.add_widget(screen)
return self.screen_manager
if __name__ == "__main__":
datastop = PedaShield()
datastop.run()
I don't have anything to trace, just nothing happens when the 'back' button it pressed.
You assigned function go_back to button self.signin
self.signin.bind(on_press=self.go_back)
but it has to be self.goback
self.goback.bind(on_press=self.go_back)
In old code when you click button "Sign In" then you can see two strings
Here
Signing in as {username}
First text is from function go_back. And this should give you clue where is the problem
Related
I have a Label and a button that I define in the init of my class. In the init I bind my button to a method that should change the label. However the label does not update on button press even tho the variable does.
Why does my variable change but my label text stays the same even tho the text is an ObjectProperty?
class ReviewLayout(BoxLayout):
Price = Price()
textover = ObjectProperty(None)
ordered_products = []
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.get_order()
l = Label(text = str(self.textover))
self.add_widget(l)
b = Button(text= 'button')
b.bind(on_press=lambda x: self.get_order())
self.add_widget(b)
def get_order(self):
ordered_products = self.ordered_products
ordered_products.append("%s")
print("this shall be present", ordered_products)
self.textover = ordered_products
When you declare your label you set its value to self.textover value but when self.textover value changes it doesn't update the label.
You need to change the value of your label by storing it as a class property and updating it whenever you want.
Just refer to this Update label's text when pressing a button in Kivy for Python
class ReviewLayout(BoxLayout):
Price = Price()
textover = ObjectProperty(None)
ordered_products = []
def __init__(self, **kwargs):
super().__init__(**kwargs)
# declare label variable as a class property (in self)
self.label = Label(text = str(self.textover))
self.add_widget(self.label)
self.button = Button(text= 'button')
self.add_widget(self.button)
self.button.bind(on_press=lambda x: self.get_order())
def get_order(self):
ordered_products = self.ordered_products
ordered_products.append("%s")
print("this shall be present", ordered_products)
self.textover = ordered_products
# change class variable text property to be the new textover content
self.label.text = str(self.textover)
I think an easier solution is to use kv to allow it to do the updates for you automatically, like this:
Builder.load_string('''
<ReviewLayout>:
Label:
text: str(root.textover)
Button:
text: 'button'
on_press: root.get_order()
''')
class ReviewLayout(BoxLayout):
Price = Price()
textover = ListProperty() # note change to ListProperty
def get_order(self):
self.textover.append("%s")
print("this shall be present", self.textover)
I am trying to make a popup that can return a true or false to where it was called from when a button is pressed
```python
import kivy
def confirmation_popup(title_text):
btn1 = kivy.uix.button.Button(text="Yes")
btn2 = kivy.uix.button.Button(text="no")
btn1.bind(on_release=return True)#to the function itself
btn2.bind(on_release=return False)
Boxed_layout= kivy.uix.boxlayout.BoxLayout(orientation = "horizontal")
Boxed_layout.add_widget(btn1)
Boxed_layout.add_widget(btn2)
pop = kivy.uix.popup.Popup(title=title_text,content=Boxed_layout)
pop.open()
if confirmation_popup("are you sure you want to delete your user"):
#delete user from database```
Rather than trying to get a return from the Popup, you should just let the Popup call a method that does the confirmed action. If you define your confirmation_popup like this:
def confirmation_popup(title_text, doit):
btn1 = Button(text="Yes")
btn2 = Button(text="no")
Boxed_layout= BoxLayout(orientation = "horizontal")
Boxed_layout.add_widget(btn1)
Boxed_layout.add_widget(btn2)
pop = Popup(title=title_text,content=Boxed_layout)
btn1.bind(on_release=partial(doit, pop)) # bind to whatever action is being confiirmed
btn2.bind(on_release=pop.dismiss)
pop.open()
# a method that does the action being confirmed
def doit(popup, button):
popup.dismiss()
print('do whatever action is confirmed')
Then you can use it by:
confirmation_popup('This is a Test', doit)
I was writing a piece of code with kivy with all the packages installed.
When I run the code it still shows "No module named kivy".
The modules were installed from both the command prompt and the VS code terminal though this code had worked fine just a few days ago. Today i opened it and it showed me this error
This is my code
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from database import DataBase
class CreateAccountWindow(Screen):
namee = ObjectProperty(None)
email = ObjectProperty(None)
password = ObjectProperty(None)
def submit(self):
if self.namee.text != "" and self.email.text != "" and self.email.text.count("#") == 1 and self.email.text.count(".") > 0:
if self.password != "":
db.add_user(self.email.text, self.password.text, self.namee.text)
self.reset()
sm.current = "login"
else:
invalidForm()
else:
invalidForm()
def login(self):
self.reset()
sm.current = "login"
def reset(self):
self.email.text = ""
self.password.text = ""
self.namee.text = ""
class LoginWindow(Screen):
email = ObjectProperty(None)
password = ObjectProperty(None)
def loginBtn(self):
if db.validate(self.email.text, self.password.text):
MainWindow.current = self.email.text
self.reset()
sm.current = "main"
else:
invalidLogin()
def createBtn(self):
self.reset()
sm.current = "create"
def reset(self):
self.email.text = ""
self.password.text = ""
class MainWindow(Screen):
n = ObjectProperty(None)
created = ObjectProperty(None)
email = ObjectProperty(None)
current = ""
def logOut(self):
sm.current = "login"
def on_enter(self, *args):
password, name, created = db.get_user(self.current)
self.n.text = "Account Name: " + name
self.email.text = "Email: " + self.current
self.created.text = "Created On: " + created
class WindowManager(ScreenManager):
pass
def invalidLogin():
pop = Popup(title='Invalid Login',
content=Label(text='Invalid username or password.'),
size_hint=(None, None), size=(400, 400))
pop.open()
def invalidForm():
pop = Popup(title='Invalid Form',
content=Label(text='Please fill in all inputs with valid information.'),
size_hint=(None, None), size=(400, 400))
pop.open()
kv = Builder.load_file("my.kv")
sm = WindowManager()
db = DataBase("users.txt")
screens = [LoginWindow(name="login"), CreateAccountWindow(name="create"),MainWindow(name="main")]
for screen in screens:
sm.add_widget(screen)
sm.current = "login"
class MyMainApp(App):
def build(self):
return sm
if __name__ == "__main__":
MyMainApp().run()
As people said in the comments, the reason is that the Python environment used by the terminal does not contain modules.
Solution: Please select the Python environment where the module "kivy" is installed in the lower left corner of VS Code, and use the shortcut key Ctrl+Shift+` to open a new VS Code terminal, it will automatically enter the selected environment.
check: We can use the command "pip --version" or "python --version" to check which Python the terminal is using and the module is installed in this location:
Reference: Python environment in VS Code.
You just need to select the right version of python with which you installed kivy.
Click at the bottom part as indicated in the image below to select the right one.
Change python interpreter
It was working fine. It would open window with 3 columns, with text I could enter. After adding some code, it suddenly stopped showing a screen, and it just says Username: in the terminal. I used a completely newly typed code, but still same result:
(I left out the importing from the top)
class ConnectPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2 # used for our grid
with open("prev_details.txt","r") as f:
d = f.read().split(",")
prev_ip = d[0]
prev_port = d[1]
prev_username = d[2]
self.add_widget(Label(text='IP:')) # widget #1, top left
self.ip = TextInput(text=prev_ip, multiline=False) # defining self.ip...
self.add_widget(self.ip) # widget #2, top right
self.add_widget(Label(text='Port:'))
self.port = TextInput(text=prev_port, multiline=False)
self.add_widget(self.port)
self.add_widget(Label(text='Username:'))
self.username = TextInput(text=prev_username, multiline=False)
self.add_widget(self.username)
# add our button.
self.join = Button(text="Join")
self.join.bind(on_press=self.join_button)
self.add_widget(Label()) # just take up the spot.
self.add_widget(self.join)
def join_button(self, instance):
port = self.port.text
ip = self.ip.text
username = self.username.text
with open("prev_details.txt","w") as f:
f.write(f"{ip},{port},{username}")
info = f"Joining {ip}:{port} as {username}"
chat_app.info_page.update_info(info)
chat_app.screen_manager.current = 'Info'
Clock.schedule_once(self.connect, 1)
def connect(self, _):
port = int(self.port.text)
ip = self.ip.text
username = self.username.text
if not socket_client.connect(ip, port, username, show_error):
return
chat_app.create_chat_page()
chat_app.screen_manager.current = 'Chat'
class ChatPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.add_widget(Label(text='Fancy stuff here to come!!!', font_size=30))
class InfoPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.message = Label(halign="center", valign="middle", font_size=30)
self.message.bind(width=self.update_text_width)
self.add_widget(self.message)
def update_info(self, message):
self.message.text = message
def update_text_width(self, *_):
self.message.text_size = (self.message.width * 0.9, None)
class Epicapp(App):
def build(self):
self.screen_manager = ScreenManager()
self.connect_page = ConnectPage()
screen = Screen(name='Connect')
screen.add_widget(self.connect_page)
self.screen_manager.add_widget(screen)
# Info page
self.info_page = InfoPage()
screen = Screen(name='Info')
screen.add_widget(self.info_page)
self.screen_manager.add_widget(screen)
return self.screen_manager
def create_chat_page(self):
self.chat_page = ChatPage()
screen = Screen(name='Chat')
screen.add_widget(self.chat_page)
self.screen_manager.add_widget(screen)
def show_error(message):
chat_app.info_page.update_info(message)
chat_app.screen_manager.current = 'Info'
Clock.schedule_once(sys.exit, 10)
This is the result (no screen)
Username:
Process finished with exit code -1
Problem has been solved, i removed the import socket_client.py which is not shown in the code above. Now the prev_details.txt is making an error. FileNotFoundError: [Errno 2] No such file or directory: 'prev_details.txt'
Importing libraries.
from PySide2 import QtWidgets,QtCore,QtGui
from UI import main
This is my class which is inheriting and have a constructor
class MyQtApp(main.Ui_MainWindow,QtWidgets.QMainWindow):
def __init__(self):
super(MyQtApp,self).__init__()
self.setupUi(self)
window size
self.showNormal()
self.submit_pb.clicked.connect(self.fill_box)
self.Menu()
This fill_box is for the combo box, and I have three combo boxes
model_cb, size_cb and color_cb
And the zeroth index is just an empty string for all of them
def fill_box(self):
model = self.model_cb.currentText()
color = self.model_cb.currentText()
size = self.size_cb.currentText()
none = ""
check = True
if model is none:
QtWidgets.QMessageBox.about(self,"Name Required","Please enter the Name!")
check = False
return
if color is none:
QtWidgets.QMessageBox.about(self,"Color Required","Please enter the Color!")
check = False
return
if size is none:
QtWidgets.QMessageBox.about(self,"Size Required","Please Enter the Size!")
check = False
return
if check:
QtWidgets.QMessageBox.about(self, "Done","Submitted")
This Menu function is for the menu bar options what happens if someone click close. I have only two options here 1)close which works fine and 2) Refresh which does not work.
def Menu(self):
self.actionClose.triggered.connect(self.close)
self.actionRefresh.triggered.connect(self.fill_box1)
def fill_box1(self):
#If I do this It will reset all the boxes to its original empty
#strings but then I would not have all the methods in the class
#to add the functionality.
self.setupUi(self)
if __name__ == '__main__':
app = QtWidgets.QApplication()
qt_app = MyQtApp()
qt_app.show()
app.exec_()