Czytnik kodów QR

0

Cześć.
Robię (a raczej próbuje) w ramach praktyk stworzyć aplikację typu czytnik kodów kreskowych i QR.
Ogólnie chodzi mi o coś więcej niż zwykłe wczytanie, z czym nie było problemu znaleźć w internecie.
Problem się zaczął, jak już program w miarę działa. Tzn mam "menu główne" i miejsce na kod. Przycisk "Skanuj" otwiera (ScreenManager) drugie okno, gdzie mam działającą kamerkę, która wczytuje podany kod.
Problem z jakim się spotkałem, to:
Jak zrobić, żeby kamerka włączała się dopiero po wciśnięciu przycisku 'Skanuj"? Obecnie uruchamia się z programem.
Jak 'wysłać' tekst do "menu głównego" pola tekstowego (MDTextField)?screenshot-20211205213505.png

0

@fornakter: Pan mnie kod pokaże. Z przekazanych przez Ciebie informacji nic nie jestem w stanie wywnioskować.
Opóźnienie możesz zrobić za pomocą https://docs.python.org/3/library/time.html#time.sleep

Jak nie możesz wstawić kodu ciężko mi będzie Ci pomóc

0

Jasne, że mogę.
Funkcja sleep nie rozwiązuje mojego problemu, bo opóźnia w czasie uruchomienie, zamiast uruchamiać w wybranym czasie.
main.py

from kivymd.uix.picker import MDDatePicker
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty

class FirstWindow(Screen):
    pass

class ProfileWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

sm = ScreenManager()
sm.add_widget(FirstWindow(name='first'))
sm.add_widget(ProfileWindow(name='secound'))

class ReadQR(MDApp):

    scan_me = ObjectProperty(None)

    def build(self):
        self.theme_cls.theme_style = "Light"
        self.theme_cls.ptimary_palette = "BlueGray"
        return Builder.load_file('mainapp.kv')

    def on_save(self, instance, value, date_range):
        self.root.ids.date_button.text = str(value)

    def on_cancel(self):
        pass

    def show_date_picker(self):
        date_dialog = MDDatePicker()
        date_dialog.bind(on_save = self.on_save, on_cancel = self.on_cancel)
        date_dialog.open()

ReadQR().run()

plik .kv

ScreenManager:
    FirstWindow:
    ProfileWindow:

#:import ObjectProperty kivy.properties.ObjectProperty

scan_me: scan_me

<FirstWindow>:

    name: 'first'
    MDFloatLayout:

        MDRaisedButton:
            text: "Skanuj kod"
            pos_hint: {"center_x": .5, "center_y": .9}
            id: Skanuj_kod
            on_press: root.manager.current = 'secound'

        MDTextField:
            id: kod_kreskowy
            hint_text: "Kod kreskowy"
            required: True
            size_hint: (0.5, 0.1)
            helper_text_mode: "on_error"
            pos_hint: {"center_x": .5, "center_y": .8}

        MDTextField:
            hint_text: "PLU"
            required: True
            size_hint: (0.5, 0.1)
            helper_text_mode: "on_error"
            input_filter: 'int'
            pos_hint: {"center_x": .5, "center_y": .7}

        MDTextField:
            hint_text: "Nazwa towaru"
            size_hint: (0.5, 0.1)
            pos_hint: {"center_x": .5, "center_y": .6}

        MDLabel:
            text: "Data tostawy:"
            pos_hint: {"center_x": .95, "center_y": .5}

        MDRaisedButton:
            text: "Dzisiaj"
            pos_hint: {"center_x": .5, "center_y": .4}

        MDLabel:
            text: "Data przydatnosci:"
            pos_hint: {"center_x": .93, "center_y": .3}

        MDRaisedButton:
            text: "Wybierz datę"
            id: date_button
            pos_hint: {'center_x': .51, 'center_y': .2}
            on_press: app.on_cancel()

        MDRaisedButton:
            text: "Zapisz"
            pos_hint: {'center_x': .51, 'center_y': .1}

<ProfileWindow>:
    name: 'secound'
    #:import zbarcam kivy_garden.zbarcam.zbarcam
    MDBoxLayout:
        orientation: 'vertical'
        ZBarCam:
            id: qrcodecam
        MDLabel:
            adaptive_height: True
            id: scan_text
            md_bg_color: app.theme_cls.primary_color
            text: ''.join([str(symbol.data) for symbol in qrcodecam.symbols])
            scan_me: scan_text.text
        MDRaisedButton:
            text: "OK"
            pos_hint: {'center_x': .51, 'center_y': .1}
            on_press: root.manager.current = 'first'
0

Przełączasz się na ekran z kamerą to sprawdzasz czy moduł jest załadowany. Jeśli nie to importuj. Jeśli wychodzisz z ekranu z obrazem z kamery to sprawdzasz czy moduł jest załadowany i jak jest to "del" moduł obsługujący kamerę. Potraktuj to jako coś do eksperymentu. To jest tylko tak teoretycznie, a czy działa to sprawdź.

Pozdrawiam
Radek Głębicki

0

No ok, ale mam poważne problemy z komunikacją main <-> .kv
Nie potrafię przenosić danych w jedną i w drugą stronę.
Wszystkie szkolenia jakie znajduje nie rozwiązują mojego problemu. Jak na razie jedynie co mi się udało to 'wysłać' w jedną stronę tekst do main'a

0

@Radosław Głębicki:
Zrobiłem jak radziłeś. Jest w sumie lepiej, ale czy da się do popup/dialog wstawić okno kamerki do skanowania? Bo mi się jak na razie nie udaje.

from kivymd.uix.picker import MDDatePicker
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDRaisedButton
from kivy_garden.zbarcam import zbarcam

KV = """MDFloatLayout:
    
    MDRaisedButton:
        text: "Skanuj kod"
        pos_hint: {"center_x": .5, "center_y": .9}
        id: Skanuj_kod
        on_press: app.show_alert_dialog()
        
    MDTextField:
        id: kod_kreskowy
        hint_text: "Kod kreskowy"
        required: True
        size_hint: (0.5, 0.1)
        helper_text_mode: "on_error"
        pos_hint: {"center_x": .5, "center_y": .8}
    
    MDTextField:
        hint_text: "PLU"
        required: True
        size_hint: (0.5, 0.1)
        helper_text_mode: "on_error"
        input_filter: 'int'
        pos_hint: {"center_x": .5, "center_y": .7}
    
    MDTextField:
        hint_text: "Nazwa towaru"
        size_hint: (0.5, 0.1)
        pos_hint: {"center_x": .5, "center_y": .6}
    
    MDLabel:
        text: "Data tostawy:"
        pos_hint: {"center_x": .95, "center_y": .5}
    
    MDRaisedButton:
        text: "Dzisiaj"
        pos_hint: {"center_x": .5, "center_y": .4}
        
    MDLabel:
        text: "Data przydatnosci:"
        pos_hint: {"center_x": .93, "center_y": .3}
    
    MDRaisedButton:
        text: "Wybierz datę"
        id: date_button
        pos_hint: {'center_x': .51, 'center_y': .2}
        on_press: app.show_date_picker()
    
    MDRaisedButton:
        text: "Zapisz"
        pos_hint: {'center_x': .51, 'center_y': .1} 
"""

class ReadQR(MDApp):
    dialog = None

    def build(self):
        self.theme_cls.theme_style = "Light"
        self.theme_cls.ptimary_palette = "Blue"
        return Builder.load_string(KV)

    def on_save(self, instance, value, date_range):
        try:
            self.root.ids.date_button.text = str(value)
        except AttributeError as e:
            print(e)

    def on_cancel(self, instance, value):
        pass

    def show_date_picker(self):
        date_dialog = MDDatePicker()
        date_dialog.bind(on_save = self.on_save, on_cancel = self.on_cancel)
        date_dialog.open()

    def show_alert_dialog(self):
        if not self.dialog:
            self.dialog = MDDialog(
                text="Ok",
                buttons=[
                    MDRaisedButton(
                        text="ANULUJ",
                        theme_text_color="Custom",
                    ),
                    MDRaisedButton(
                        text="OK",
                        theme_text_color="Custom",
                    ),
                ],
            )
        self.dialog.open()


ReadQR().run()
0

Nie wiem czy to z zbarcam zadziała, ale tak całkiem prosto:

from kivy.app import runTouchApp,stopTouchApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
#from kivy_garden.zbarcam import zbarcam # odkomentuj

mainLay=BoxLayout(orientation='vertical',size_hint=(1,1))
camLay=BoxLayout(orientation='vertical',size_hint=(1,.5))
lab=Label(text='Tu to niby okienko kamery') # zakomentuj
#cam = ZBarCam() # odkomentuj
btnsLay=BoxLayout(orientation='horizontal',size_hint=(1,.2))
def f_open(*data):
	camLay.add_widget(lab) # zakomentuj
	#camLay.add_widget(cam) # odkomentuj
	return None
btnO=Button(text='open')
btnO.bind(on_release=f_open)
def f_close(*data):
	camLay.remove_widget(lab) # zakomentuj
	#camLay.remove_widget(cam) # odkomentuj
	return None
btnC=Button(text='close')
btnC.bind(on_release=f_close)
btnsLay.add_widget(btnO)
btnsLay.add_widget(btnC)
mainLay.add_widget(camLay)
mainLay.add_widget(btnsLay)

runTouchApp(mainLay)

Spróbuj.

Pozdrawiam
Radek Głębicki

0

@Radosław Głębicki:
Wykrzesałem coś takiego

from kivy.app import runTouchApp,stopTouchApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy_garden.zbarcam import ZBarCam # odkomentuj

mainLay=BoxLayout(orientation='vertical',size_hint=(1,1))
camLay=BoxLayout(orientation='vertical',size_hint=(1,.5))
btnsLay=BoxLayout(orientation='horizontal',size_hint=(1,.2))

cam = False
camStat = False

def f_open(*data):
    global cam, camStat

    if camStat == False:
        print('Uruchamiam kamere', cam)
        cam = ZBarCam()
        camLay.add_widget(cam)
        camStat = True
    else:
        pass
    return cam, camStat

def f_close(*data):
    global cam, camStat
    if camStat == True:
        camLay.remove_widget(cam)
        camStat = False
    else:
        print("Nie mogę wylaczyc kamery ", camStat)
    return cam, camStat

btnO=Button(text='open')
btnO.bind(on_release=f_open)

btnC=Button(text='close')
btnC.bind(on_release=f_close)
btnsLay.add_widget(btnO)
btnsLay.add_widget(btnC)
mainLay.add_widget(camLay)
mainLay.add_widget(btnsLay)

runTouchApp(mainLay)

Kamera się uruchamia dopiero po kliknięciu f_open
Jedynie mały problem jest w tym, że po kliknięciu f_close wyłącza podgląd, zmienia status na OFF, ale nie wyłącza fizycznie kamerki. Po kliknięciu f_open uruchamia ją drugi raz.
Szukałem, ale nie znalazłem jaką komendą można OFF kamerę fizycznie. A dzisiaj idę już spać, bo jutro rano trzeba wstać :)

0

A spróbuj w f_close "cam=None"
dodatkowo taki bajer, że dodaj sobie id do cam.id='niepowtarzalne_id' i dalej:

lAllWdgs=[widget for widget in camLay.walk(loopback=True)] # lista widgetów od camLay w dół (dzieci)

for elm in lAllWdgs:
    if isinstance(elm, ZBarCam) and elm.id=='niepowtarzalne_id': # dajesz id na wypadek gdy są dwa takie same typy widgeta muszą mieć id 
        camLay.remove_widget(elm)

Coś w tym stylu. Mogłem coś namieszać, ale u mnie działa to dobrze. Nie trzeba pilnować booleana, gdy coś dodajemy lub chcemy usunąć. Tylko to id dać do elementu. I jeszcze jak definiujesz pustą zmienną globalną to dawaj None: cam=None. Chyba tak "zdrowiej"
w f_open bez else. Takie tam moje przemyślenia.

Pozdrawiam
Radek Głębicki

0

Mam kod, który skanuje kod QR i bez problemu zapisuje go do zmiennej (wartość). Potem bez problemu mogę to wstawić gdzie chcę.
Pozostaje przy Twojej wersji, bez .kv.
Problem mam teraz taki, że tego kodu nie mogę "wkleić" do okienka BoxLayout.
Wyskakuje błąd AttributeError: 'cv2.VideoCapture' object has no attribute 'fbind'

import time
import cv2
from pyzbar.pyzbar import decode

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
camera = True
used_codes = []
while camera == True:
    success, frame = cap.read()

    for code in decode(frame):
        if code.data.decode('utf-8') not in used_codes:
            print(code.data.decode('utf-8'))
            used_codes.append(code.data.decode('utf-8'))
            time.sleep(2)

    cv2.imshow('Testowanie', frame)
    cv2.waitKey(1)
print(used_codes[-1])

1 użytkowników online, w tym zalogowanych: 0, gości: 1