Чего я пытаюсь достичь:, когда экран переключается с ScreenOne на ScreenTwo, запускайте функцию цикла while, пока не будет нажата кнопка на ScreenTwo и цикл не прервется.
Эта функция должна запускаться и получать входные данные от сканера штрих-кода, подключенного к моему компьютеру (это означает, что входными данными являются штрих-коды), и обновляет метку на ScreenTwo с количеством отсканированных штрих-кодов.
Затем, когда у меня больше не будет штрих-кода для сканирования, нажмите кнопку «Готово» на ScreenTwo - и это должно отправить ввод «999», чтобы прервать функцию цикла.
Как я пытался запустить функцию при переключении экрана: с использованием on_enter
class ScreenTwo(Screen):
def on_enter(self):
getStatus()
updatePoints()
Проблема, с которой я столкнулся:
Как решить 1?
Как мне получить 2?
Вот скриншоты ScreenOne и ScreenTwo соответственно:


Вот файл returnStation2.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
def getStatus():
while True:
answer = input('What is the box ID? ')
if answer == 999: #LOOPS BREAK WHEN INPUT IS 999
break
elif type(answer) == int:
do something
else:
print('Sorry I did not get that')
def updatePoints():
do something
class ScreenManagement(ScreenManager):
screen_one = ObjectProperty(None)
screen_two = ObjectProperty(None)
class ScreenOne(Screen):
member_status = ObjectProperty(None)
def backspace(self, textString):
newTextString = textString[0:-1]
self.display.text = newTextString
def getPoints(self, phoneNumber):
self.manager.screen_two.member_status.text = phoneNumber
class ScreenTwo(Screen):
input_text = ObjectProperty(None)
def on_enter(self):
getStatus()
updatePoints()
def clearField(self):
self.manager.screen_one.input_text.text = ""
class ReturnStationLayout2App(App):
def build(self):
return ScreenManagement()
if __name__ == '__main__':
ReturnStationLayout2App().run()
Вот returnStationLayout2.kv
Кнопка «Готово» (в ScreenTwo) находится внизу скрипта.
Его нельзя нажать, когда экран переключен на ScreenTwo. И я надеюсь, что при нажатии он может ввести «999», чтобы прервать выполняющуюся функцию цикла.
<ScreenManagement>:
screen_one: screen_one
screen_two: screen_two
ScreenOne:
id: screen_one
name: 'menu'
ScreenTwo:
id: screen_two
name: 'settings'
<CustButton@Button>:
font_size: 32
<ScreenOne>:
input_text : entry
GridLayout:
id: numberPad
rows: 5
padding: [300,200]
spacing: 10
# Where input is displayed
BoxLayout:
Label:
text: "+65"
font_size: 50
size_hint: 0.2, 1
TextInput:
id: entry
font_size: 50
multiline: False
padding: [20, ( self.height - self.line_height ) / 2]
BoxLayout:
spacing: 10
CustButton:
text: "1"
on_press: entry.text += self.text
CustButton:
text: "2"
on_press: entry.text += self.text
CustButton:
text: "3"
on_press: entry.text += self.text
CustButton:
text: "DEL"
on_press: root.backspace(entry.text)
BoxLayout:
spacing: 10
CustButton:
text: "4"
on_press: entry.text += self.text
CustButton:
text: "5"
on_press: entry.text += self.text
CustButton:
text: "6"
on_press: entry.text += self.text
CustButton:
text: "AC"
on_press: entry.text = ""
BoxLayout:
spacing: 10
CustButton:
text: "7"
on_press: entry.text += self.text
CustButton:
text: "8"
on_press: entry.text += self.text
CustButton:
text: "9"
on_press: entry.text += self.text
CustButton:
text: "Enter" #HERE IS THE ENTER BUTTON
on_press:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 1
root.manager.current = 'settings'
root.getPoints(entry.text)
BoxLayout:
spacing: 10
Label:
text: ""
CustButton:
text: "0"
on_press: entry.text += self.text
Label:
text: ""
Label:
text: ""
<ScreenTwo>:
member_status: memberStatus
BoxLayout:
Label:
id: memberStatus
text: ''
GridLayout:
rows: 3
padding: [100,500]
spacing: 10
BoxLayout:
Label:
text: "You have scanned:"
BoxLayout:
CustButton:
text: "Done" #THIS IS THE BUTTON I HOPE TO BE ABLE TO BREAK THE LOOP FUNCTION
on_press:
root.manager.transition.direction = "right"
root.manager.current = 'menu'
root.clearField()
Можно вызывать функцию каждые n секунд, используя Clock kivy, а также использовать TextInput kivy для ввода (чтобы не использовать input()). Этого было бы достаточно, чтобы решить вашу проблему?
@Kacper Floriański есть ли способ для петли прослушивать входные данные как с экрана (кнопок), так и с моего сканера штрих-кода? Я хочу добиться того, чтобы пользователь отсканировал любое количество штрих-кодов (поэтому цикл должен прослушивать больше входных данных, если таковые имеются), и как только он завершит сканирование, нажмите кнопку «Готово» и выйдите из цикла. Есть ли способ сделать это?
Самый простой способ - добавить кнопку «Добавить», которую нужно нажимать, чтобы добавить штрих-код. Обратите внимание, что даже при использовании input() в Python требуется, чтобы вы нажимали ввод после каждого ввода. Если штрих-коды вводятся с клавиатуры, вы можете попросить пользователя ввести их все в определенном формате и просто извлечь оттуда значения. Если они являются графическими объектами, вы можете сделать это без нажатия какой-либо кнопки, например, заставив пользователя ждать 1 секунду, не перемещая телефон, чтобы сканировать штрих-код.
@ KacperFloriański Я думаю о киоске в библиотеке. Как это позволяет пользователю сканировать любое количество книг, которые они намереваются взять, а затем щелкнуть «готово» на экране киоска, чтобы обработать заимствование всех отсканированных книг?
Или можно запустить функцию при обнаружении входа? поскольку мой сканер штрих-кода посылает сигнал «ввод» после каждого сканирования, нам не нужно вручную нажимать «ввод» после каждого ввода.
Понятия не имею, я сам не использую этот тип услуг, и я не мог видеть никаких штрих-кодов на видео, которые я нашел на YouTube, я предполагаю, что технология сканирования - RFID-метки.
Как я уже упоминал ранее, вы можете узнать, как использовать kivy Clock и пытаться сканировать тег каждые n секунд, например каждые 0,01 секунды, и в этом случае вам также нужно будет проверить, был ли данный штрих-код уже отсканирован, чтобы избежать многократное сканирование одного и того же штрих-кода. Это будет вести себя как цикл while, не останавливая ваш код. Однако новая проблема появится, если ваша функция сканирования будет заметно медленной.
@ KacperFloriański Да, вы правы, это RFID-метки, но даже в этом случае RFID-считыватель может захватывать метки, и пользователи могут щелкнуть «конец», чтобы остановить чтение. Есть ли способ, кроме метода часов, принимать экранные кнопки в качестве входных данных? так они вроде работают как клавиатура?






Этот ответ основан на обсуждении в разделе комментариев под вопросом. Приведенный ниже код написан в предположении, что сканер отправляет определенный сигнал при сканировании штрих-кода. Общая идея состоит в том, чтобы запустить функцию после того, как этот сигнал был отправлен.
Предлагаю ознакомиться с объектом kivy Часы. Можно создать функцию прослушивателя, которая будет проверять, отправляется ли сигнал каждые n секунд. Точнее, допустим, вы хотите запустить функцию process() после обнаружения сигнала. Давайте также объявим переменную scanned для хранения информации, если штрих-код был успешно отсканирован, и создадим слушателя, чтобы проверить, был ли отправлен сигнал (поэтому проверьте, содержит ли переменная scannedTrue). Следующий пример кода устанавливает переменную scanned каждые 2 секунды на True, чтобы имитировать поведение сканирования.
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen
# Define constants and the scanned variable, for easy example
INTERVAL = 0.01
scanned = False
# Process method runs every 0.01 seconds, note the use of dt argument (explained in docs)
def process(dt):
# Retrieve the global variable, for easy example
global scanned
# Check if scanned, note setting scanned to False once an item was scanned.
# Here you can also check the uniqueness of the scanned barcode (to avoid having the same barcode processed many times)
if scanned is True:
print("Scanned! Processing the data and setting scanned to False.")
scanned = False
else:
print("Not scanned yet!")
# Mimic scanning behaviour
def scan(dt):
# Retrieve the global variable and set it to true
global scanned
scanned = True
class Main(App):
def __init__(self):
super(Main, self).__init__()
# Schedule the functions to be called every n seconds
Clock.schedule_interval(process, INTERVAL)
Clock.schedule_interval(scan, INTERVAL*200)
def build(self):
# Display screen with a single button for easy example
scr = Screen()
btn = Button(text = "You can press me but nothing will happen!")
scr.add_widget(btn)
return scr
if __name__ == '__main__':
Main().run()
Выход:
Not scanned yet!
.
.
.
Not scanned yet!
Scanned! Processing the data and setting scanned to False.
Могу я спросить, значит, во время интервалов кнопки на экране по-прежнему будут работать? можно ли на них еще давить?
Да, они по-прежнему будут работать. Разрешите отредактировать ответ и добавить кнопку.
Я добавил кнопку, чтобы показать, что приложение будет продолжать реагировать.
ВАУ ОТЛИЧНО! Думаю, это сработает для моего приложения :)) попробую посмотреть, как это вставить в свой код. Я так плохо разбираюсь в этом: / но спасибо, что помогли мне до сих пор! Я очень ценю это!
Не волнуйтесь, идея вашего проекта мне очень нравится, продолжайте в том же духе :)
Еще один вопрос. Как здесь появляется input ()? потому что мне все еще нужно запросить ввод для обработки отсканированного штрих-кода. и он просто зависает, если ввод не обнаружен: /
Как только вы запустите цикл while, он будет продолжаться до тех пор, пока вы его не сломаете, и заблокирует все остальное поведение. Это означает, что вы не сможете нажать кнопку во время выполнения кода и не сможете обновить экран. Вы можете попробовать создать отдельный поток, независимый от других частей вашего приложения, но я считаю, что
input()Python будет блокировать все из-за способа его создания (я был бы признателен, чтобы кто-нибудь поддержал меня в этом). Кроме того, когда я запускал ваш код, кнопка была закрыта другими элементами, и мне пришлось сначала изменить отступы вашего макета сетки на [100, 100].