基维 |程序结束前屏幕不会改变
Kivy | Screen won't change until the end of the program
我正在尝试使用 Python 并使用 Kivy 作为 GUI 创建一个工具。当用户使用该工具 运行 时,我希望显示一个进度条。我通过使用 Kivy 屏幕实现了这一点。我有一个主菜单屏幕、文件选择器弹出窗口 window 和一个进度条。
屏幕工作正常,但是进度条(屏幕)只会在方法的其余部分完成后从主菜单更改。即使我已经告诉屏幕改变。这破坏了进度条的点,因为当屏幕最终改变时,该工具已经完成 运行ning。
我似乎无法解决这个问题。我尝试使用弹出 windows 但我遇到了同样的问题。通过插入几个断点并使用调试器,我可以看到屏幕管理器已经实现了更改,但直到程序结束才更改屏幕。
main.py
#When run button is pressed the run method is called
import sys
import time
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
import os
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
loadfile = ObjectProperty(None)
text_input = ObjectProperty(None)
# Dissmiss Popup aka cancel button
def dismiss_popup(self):
self._popup.dismiss()
# File Browser
def show_load(self):
content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
self._popup = Popup(title="Select Disk Image", content=content, size_hint=(0.9, 0.9))
self._popup.open()
# Select file function
def load(self, path, filename):
with open(os.path.join(path, filename[0])):
global diskimage
diskimage = filename[0]
# When the run button is clicked
# Makes sure they have to select a file before pressing run
def run(self):
if diskimage is None:
"Please Select a Disk Image"
else:
print("Initialising")
# calling BulkExrtaor class
print("screen currently set to:", self.manager.current)
self.manager.current = 'progressbar'
print("screen currently set to:", self.manager.current)
BulkExtractor().bulkextractor_run()
#p1.start()
print(self.manager.current)
print("changed?")
def startBE(self):
BulkExtractor().bulkextractor_run()
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class GUI_RUN(App):
def build(self):
return presentation
class BulkExtractor(MainScreen):
#Bulk Extractor run method
def bulkextractor_run(self):
print("File Path to file", "\"" + diskimage + "\"")
#Runs Bulk Extractor
#command im trying to run
# os.system("%Programdata%\bulk_extractor64.exe -o output ""\"" + diskimage + "\"")
#Using sleep as a test instead of trying to run the actual command above
print("Still hasn't changed")
time.sleep(20)
print("Still hasn't changed")
print("Program Finished")
class Progressbar(ScreenManager):
pass
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
presentation = Builder.load_file("main.kv")
if __name__ == "__main__":
GUI_RUN().run()
Main.kv
ScreenManagement:
MainScreen:
AnotherScreen:
<MainScreen>:
name: 'main'
FloatLayout:
Label:
font_size: 50
size_hint: 0.3, 0.2
text: "FD"
pos_hint: {"right": 0.65,'top':1}
Button:
font_size: 25
size_hint: 0.3, 0.2
text: "Select Disk Image"
pos_hint: {"right": 0.65,'top':0.5}
on_press: root.show_load()
Button:
font_size: 25
size_hint: 0.3, 0.2
text: "Run"
pos_hint: {"right": 0.65,'top':0.3}
on_press: root.run()
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserIconView:
id: filechooser
path: "C:/"
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Select"
on_press: root.load(filechooser.path, filechooser.selection)
on_release: root.cancel()
<AnotherScreen>:
name: 'progressbar'
Label:
text: 'Progress: {}%'.format(int(pb.value))
size_hint_y: None
pos: 10, 400
font_size: 30
ProgressBar:
id: pb
min: -100
max: 100
value: 0
size_hint: 0.5 , 1.0
width: 200
pos : 200, 70
Button:
on_release: app.root.current = 'main'
text: 'Cancel'
size_hint_x: .3
size_hint_y: .1
pos: 290, 190
font_size:
处理后class/method,画面变化....
谁能告诉我我做错了什么?
要测试此 运行 代码和 select 您系统上的任何文件,然后点击 运行。
您有一个常见问题,即您的 bulkextractor_run()
方法在主线程上 运行ning,因此主线程一直很忙,因此它无法更新任何 GUI 元素。为了使其正常工作,运行 该方法在不同的线程中:
def run(self):
if diskimage is None:
"Please Select a Disk Image"
else:
print("Initialising")
# calling BulkExrtaor class
print("screen currently set to:", self.manager.current)
self.manager.current = 'progressbar'
print("screen currently set to:", self.manager.current)
Thread(target=BulkExtractor().bulkextractor_run).start()
print(self.manager.current)
print("changed?")
然后,在您的 bulkextractor_run()
方法中,您需要在主线程上执行 ProgressBar
更新,也许使用 Clock.schedule_once()
,如下所示:
class BulkExtractor(MainScreen):
#Bulk Extractor run method
def bulkextractor_run(self):
print("File Path to file", "\"" + diskimage + "\"")
#Runs Bulk Extractor
#command im trying to run
# os.system("%Programdata%\bulk_extractor64.exe -o output ""\"" + diskimage + "\"")
#Using sleep as a test instead of trying to run the actual command above
for i in range(101):
time.sleep(0.1)
Clock.schedule_once(partial(self.update_progressBar, i))
print("Program Finished")
def update_progressBar(self, val, dt):
presentation.get_screen('progressbar').ids.pb.value = val
我正在尝试使用 Python 并使用 Kivy 作为 GUI 创建一个工具。当用户使用该工具 运行 时,我希望显示一个进度条。我通过使用 Kivy 屏幕实现了这一点。我有一个主菜单屏幕、文件选择器弹出窗口 window 和一个进度条。
屏幕工作正常,但是进度条(屏幕)只会在方法的其余部分完成后从主菜单更改。即使我已经告诉屏幕改变。这破坏了进度条的点,因为当屏幕最终改变时,该工具已经完成 运行ning。
我似乎无法解决这个问题。我尝试使用弹出 windows 但我遇到了同样的问题。通过插入几个断点并使用调试器,我可以看到屏幕管理器已经实现了更改,但直到程序结束才更改屏幕。
main.py
#When run button is pressed the run method is called
import sys
import time
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
import os
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
loadfile = ObjectProperty(None)
text_input = ObjectProperty(None)
# Dissmiss Popup aka cancel button
def dismiss_popup(self):
self._popup.dismiss()
# File Browser
def show_load(self):
content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
self._popup = Popup(title="Select Disk Image", content=content, size_hint=(0.9, 0.9))
self._popup.open()
# Select file function
def load(self, path, filename):
with open(os.path.join(path, filename[0])):
global diskimage
diskimage = filename[0]
# When the run button is clicked
# Makes sure they have to select a file before pressing run
def run(self):
if diskimage is None:
"Please Select a Disk Image"
else:
print("Initialising")
# calling BulkExrtaor class
print("screen currently set to:", self.manager.current)
self.manager.current = 'progressbar'
print("screen currently set to:", self.manager.current)
BulkExtractor().bulkextractor_run()
#p1.start()
print(self.manager.current)
print("changed?")
def startBE(self):
BulkExtractor().bulkextractor_run()
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class GUI_RUN(App):
def build(self):
return presentation
class BulkExtractor(MainScreen):
#Bulk Extractor run method
def bulkextractor_run(self):
print("File Path to file", "\"" + diskimage + "\"")
#Runs Bulk Extractor
#command im trying to run
# os.system("%Programdata%\bulk_extractor64.exe -o output ""\"" + diskimage + "\"")
#Using sleep as a test instead of trying to run the actual command above
print("Still hasn't changed")
time.sleep(20)
print("Still hasn't changed")
print("Program Finished")
class Progressbar(ScreenManager):
pass
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
presentation = Builder.load_file("main.kv")
if __name__ == "__main__":
GUI_RUN().run()
Main.kv
ScreenManagement:
MainScreen:
AnotherScreen:
<MainScreen>:
name: 'main'
FloatLayout:
Label:
font_size: 50
size_hint: 0.3, 0.2
text: "FD"
pos_hint: {"right": 0.65,'top':1}
Button:
font_size: 25
size_hint: 0.3, 0.2
text: "Select Disk Image"
pos_hint: {"right": 0.65,'top':0.5}
on_press: root.show_load()
Button:
font_size: 25
size_hint: 0.3, 0.2
text: "Run"
pos_hint: {"right": 0.65,'top':0.3}
on_press: root.run()
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserIconView:
id: filechooser
path: "C:/"
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Select"
on_press: root.load(filechooser.path, filechooser.selection)
on_release: root.cancel()
<AnotherScreen>:
name: 'progressbar'
Label:
text: 'Progress: {}%'.format(int(pb.value))
size_hint_y: None
pos: 10, 400
font_size: 30
ProgressBar:
id: pb
min: -100
max: 100
value: 0
size_hint: 0.5 , 1.0
width: 200
pos : 200, 70
Button:
on_release: app.root.current = 'main'
text: 'Cancel'
size_hint_x: .3
size_hint_y: .1
pos: 290, 190
font_size:
处理后class/method,画面变化....
谁能告诉我我做错了什么?
要测试此 运行 代码和 select 您系统上的任何文件,然后点击 运行。
您有一个常见问题,即您的 bulkextractor_run()
方法在主线程上 运行ning,因此主线程一直很忙,因此它无法更新任何 GUI 元素。为了使其正常工作,运行 该方法在不同的线程中:
def run(self):
if diskimage is None:
"Please Select a Disk Image"
else:
print("Initialising")
# calling BulkExrtaor class
print("screen currently set to:", self.manager.current)
self.manager.current = 'progressbar'
print("screen currently set to:", self.manager.current)
Thread(target=BulkExtractor().bulkextractor_run).start()
print(self.manager.current)
print("changed?")
然后,在您的 bulkextractor_run()
方法中,您需要在主线程上执行 ProgressBar
更新,也许使用 Clock.schedule_once()
,如下所示:
class BulkExtractor(MainScreen):
#Bulk Extractor run method
def bulkextractor_run(self):
print("File Path to file", "\"" + diskimage + "\"")
#Runs Bulk Extractor
#command im trying to run
# os.system("%Programdata%\bulk_extractor64.exe -o output ""\"" + diskimage + "\"")
#Using sleep as a test instead of trying to run the actual command above
for i in range(101):
time.sleep(0.1)
Clock.schedule_once(partial(self.update_progressBar, i))
print("Program Finished")
def update_progressBar(self, val, dt):
presentation.get_screen('progressbar').ids.pb.value = val