Python, Kivy - QRScanner and ScreenManager - python

I want to create an app with 2 (an more) screens (screen manager).
When i make app without that QR reader, i know how to move values from one screen to another. But here i have problem with that.
I spend 3 days on this problem and still dont have answer. Can You help me?
Heres code:
https://github.com/fornakter/Terminarz-Kivy-MD/blob/master/main.py
Errors are on class SecoundWindow, on line 16.
Comments explained errors wit i recive.
Thank You.

The documentation says connect_camera() must be called after on_start(). So change the definition of SecoundWindow to simply:
class SecoundWindow(Screen):
pass
And in your ReadQR App, add the following methods:
def on_start(self):
Clock.schedule_once(self.connect_camera)
def connect_camera(self, dt):
secoundWindow = self.root.get_screen('secound')
secoundWindow.ids.preview.connect_camera(camera_id='front', enable_analyze_pixels=True, default_zoom=0.0)
I needed to add camera_id to avoid SEGFAULT.
Unrelated, but the following lines of your code do nothing and can be deleted:
sm = ScreenManager()
sm.add_widget(FirstWindow(name='first'))
sm.add_widget(SecoundWindow(name='secound'))

Related

Dinamically create buttons

I have a problem that I've partially solved: I want to have a grid layout where I wanna place a certain number of buttons, and let's call that number "x". It's not a difficult task, I can just use a for loop, for example
class Window(Gridlayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for i in range(x):
self.add_widget(Button())
and this works fine, but here comes the first obstacle: I want to have multiple windows and thus the ability to navigate throught them, so I cannot say
class Window(GridLayout)
but I must write
class Window(Screen)
if I want to use the Screen Manager that comes with kivy. To come around this i figured that i could do something like this:
class Registrazione(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
buttons = GridLayout(cols=4)
for i in range(x):
buttons.add_widget(Button())
self.add_widget(buttons)
and this way, everything works properly. Now, let's say I want to add a single button under all of them, I can do
class Registrazione(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
base = BoxLayout(orientation='vertical')
buttons = GridLayout(cols=4)
for i in range(x):
buttons.add_widget(Button())
base.add_widget(buttons)
base.add_widget(Button(text='another button'))
self.add_widget(base)
and again, this works fine. My question is: can I write some of this stuff in my .kv file? Expecially the button that goes under everything, can I add it through the .kv file? It's a lot easier there, and if for some reason I want to add a lot more things under the previously mentioned buttons, it would be much faster and easier to write all that code in the .kv file.
I hope it's clear, and that you can help me out.
Thanks a lot to everyone that answers

How does one update a field from outside the __init__() function with pyqt5

I am reading a sensor and want to display its output as a decimal number in a GUI using PyQt5. I have found a number of tutorials that point out the label.setText('myStr') function. This does not work for my setup, however, because I need to update the field based on the input from another function. I'm not very familiar with PyQt5 yet, and I would appreciate any insight into how this problem ought to be approached.
Note: (I am using LCM to acquire data from a Raspberry Pi. I'm not sure that that is relevant to the problem, but it helps explain my code below.)
Here is what I am trying to do:
class Home_Win(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
loadUi("sensor_interface.ui", self)
self.label_temp.setText('temperature') #Just to verify that I can change it from here
def acquire_sensors(self):
temp = 0 #Make variable available outside nested function
def listen(channel, data):
msg=sensor_data.decode(data)
temp = msg.temperature
lc = lcm.LCM()
subscription = lc.subscribe("sensor_data_0", listen)
while True:
lc.handle()
self.label_temp.setText(str(temp))
Any thoughts on how I can update the GUI to display the readings I am getting from my sensors?
Thanks!
You're almost there. All you need to do is to save the ui in an instance variable in __init__:
self.ui = loadUi("sensor_interface.ui", self)
Then, assuming label_temp is the name of your QLabel widget, just do:
self.ui.label_temp.setText(str(temp))
It turned out that I needed to add repaint(). I also switched to a QLineEdit as this seemed to work better for me. So inside the while loop I now have:
self.ui.lineEdit_temp.setText(str(temp))
self.ui.lineEdit_temp.repaint()
This now outputs live updates to the GUI while reading the data stream.

Init screen in kv on button release using ScreenManager

I'm a beginner Kivy developer and I need some advice from you guys.
I'm using ScreenManager to jump between screens and as far as I noticed, all the screens are initialized just after the application starts, and I need them to be initialized with certain attributes from previous screens, like, selecting the category or stuff. Is there any way to do that?
I have two buttons in CategorySelectScreen both representing certain category, I want them to send a string attribute to DictScreen, where it will be used as an argument in CategorySelect method, which filters the items list, but the thing is, the application need that argument on start and without it the interpreter would just throw errors.
Also, I think I'm using kivy in a very bad way, could you please look into my code and give me some pro tips? Thanks in advance, cheers :)
kv file: http://pastebin.com/UdvGS7Wv
py files: http://pastebin.com/gJn9Mrip
When declaring your screens decide what object would be it's input. Then make this object a property. After that, setup on_... callback where you build your screen with widgets with values based on this input object. For example:
class DictScreen(Screen):
category_selected = ObjectProperty(None)
def on_category_selected(self, instance, value):
category_selected = value
self.clear_widgets()
self.add_widget(Button(text=category_selected.name))
And in previous screen, before you switch to DictScreen get its instance from app.root.ids, then assign category_selected to it and then set new current screen with ScreenManager. This way your DictScreen will be immediately build with choosen category right before you switch to it.
"before you switch to DictScreen get its instance" how this can be done? It's well explained here:
https://kivy.org/docs/api-kivy.uix.widget.html?highlight=widget#kivy.uix.widget.Widget.ids

Kivy image update

I'm absolutely new to GUI desing and trying to create a very simple App using python and kivy with a little bit of animations after pressing buttons. But as I'm completely new to kivy I'm stuck. I think the answer is very easy but after roundabout 8h of trial and error and googling through the internet I'm desperate :-)
I have created a little App with a button and an Image. What I'm trying to do is changing the Image after "button_pressed". The code in kivy file:
<FirstTest>:
my_image: my_image
source_image: self.source_image
Button:
on_press: root.gamer.changeImage()
My_Image:
id: my_image
source: self.parent.source_image
<My_Image>:
allow_stretch:True
keep_ratio: False
And the python Code (only the necessary part):
class Player(object):
def changeImage(self):
FirstTest.source_image = 'new_image.png'
class My_Image(Image):
pass
class FirstTest(FloatLayout):
my_image = ObjectProperty(None)
source_image = StringProperty(None)
source_image = 'First_Image.png'
gamer = Player()
def update(self, dt):
print(self.source_image) #To see in realtime if the image source changed
class MyApp(App):
def build(self):
game = FirstTest()
Clock.schedule_interval(partial(FirstTest.update, FirstTest), 1/60)
return game
When I start the App I see the Button and the "First_Image" loaded. But when I hit the button nothing changes. The only thing I see is that the source_image path changed in the console.
I do not understand why the Image isn't reloaded with the new source. I thought when I change the path I will get a new Image and if I do this repeated I would get some kind of animation. But not even a single image changes. If I try to change the Objectproperty of "my_image" I got an error message with "ObjectProperty has no attribute source"
What do I miss? Please help!
Thanks in advance!
The most obvious problem I see with your code is that you are confusing class objects with instance objects.
FirstTest is a class object, and when you do:
game = FirstTest()
You are creating an instance of FirstTest. The instance will have its own properties and methods. This means that you don't want to call FirstTest.update but game.update.
Also, FirstTest.source_image = ... is wrong, as you are not changing the image source on the instance object in the GUI, but modifying the class definition. You will need to modify game.source_image instead. The easiest way to do this is to save a reference of game in the App object (self.game = game in build), and then reference it with App.get_running_app().game.

Enter-Notify-Event Signal not working on gtk.ToolButton

On a happy (if not irrevelent) note, this is the absolute last obstacle in this particular project. If I fix this, I have my first significant dot release (1.0), and the project will be going public. Thanks to everyone here on SO for helping me through this project, and my other two (the answers help across the board, as they should).
Now, to the actual question...
I have a toolbar in my application (Python 2.7, PyGTK) which has a number of gtk.ToolButton objects on it. These function just fine. I have working "clicked" events tied to them.
However, I need to also connect them to "enter-notify-event" and "leave-notify-event" signals, so I can display the button's functions in the statusbar.
This is the code I have. I am receiving no errors, and yet, the status bar messages are not appearing:
new_tb = gtk.ToolButton(gtk.STOCK_NEW)
toolbar.insert(new_tb, -1)
new_tb.show()
new_tb.connect("clicked", new_event)
new_tb.connect("enter-notify-event", status_push, "Create a new, empty project.")
new_tb.connect("leave-notify-event", status_pop)
I know the issue is not with the "status_push" and "status_pop" events, as I've connected all my gtk.MenuItem objects to them, and they work swimmingly.
I know that gtk.ToolButton objects are in the Widgets class, so "enter-notify-event" and "leave-notify-event" SHOULD technically work. My only guess is that this particular object does not emit any signals other than "clicked", and thus I'd have to put each in a gtk.EventBox.
What am I doing wrong here? How do I fix this?
Thanks in advance!
Your guess was correct, you should wrap your widget in a gtk.EventBox, here is an example that i hope will be hopeful:
import gtk
def callback(widget, event, data):
print event, data
class Win(gtk.Window):
def __init__(self):
super(Win, self).__init__()
self.connect("destroy", gtk.main_quit)
self.set_position(gtk.WIN_POS_CENTER)
self.set_default_size(250, 200)
tb = gtk.ToolButton(gtk.STOCK_NEW)
# Wrap ``gtk.ToolButton`` in an ``gtk.EventBox``.
ev_box = gtk.EventBox()
ev_box.connect("enter-notify-event", callback, "enter")
ev_box.connect("leave-notify-event", callback, "leave")
ev_box.add(tb)
self.add(ev_box)
if __name__ == '__main__':
Win()
gtk.main()
It appears, based on experimentation and evidence, this is impossible in PyGtk 2.24.

Categories