-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why that trash symbol? #34
Comments
I tested with import gui.fonts.font6 as font6
wri = Writer(ssd, font6) As you know, I was using the nano-gui and I was running |
Ohh, I realized that symbol is the exit button, right? So sorry! Is there how do not use and do not show that exit button? Because that exit button use a very large space on the display when used little display as the |
Let me to do another question: on the Thank you in advance! |
I think the Mostly |
The symbol is the
|
Sorry for that dummy question. Now I see in the # Preferred way to close a screen or dialog. Produces an X button at the top RHS.
# Note that if the bottom screen is closed, the application terminates.
class CloseButton(Button):
Now I have three buttons on the display to use inputs Prev, Select, Next, but as the menus e etc of micro-gui are very large to that 128x64 display, I'm in a dillema what to do:
Ps:
Below are two prints using nano-gui with that re-inveted inputs next, prev, select that I opened that issue in the nano-gui project: peterhinch/micropython-nano-gui#53 Is just two Screens, but will be much more, and the idea is prev/next change of that complete screen to another and use Select to change of Screen too. Could you please give your thoughts about that? Thank you |
Here is the general approach I would use. Use micro-gui. Assign 3 unused pins to Button objects and use them to initialise the GUI. Their job is purely to allow the GUI to start correctly. Assign the three pins used by your physical buttons to Button objects: let's call those Next, Prev and Sel. Note that Button instances allow you to dynamically assign callbacks. Examine the demos to see how next and prev virtual buttons work. On your first screen, define an *On the first screen you'll also need to assign callbacks to Prev and Sel, because you might run this screen in response to Prev from the next. You can also disable the callback - see docs. I'm convinced this could work, but it will require careful coding and studying the screen change mechanism. |
Hello @peterhinch I liked so much about your idea and I understood your rationale. I read many docs and source code as well from
Just to clarify: I already has 3 Pins dedicated for the physical Buttons, so need I more 3 Pins (even temporary Pins) to initialize the GUI? If yes, I have no more Pins unused in my board, the last two unused pins I used to complete 3 physical Buttons instead 1 Button. But, if is really necessary, I can to start the display part of code before others async applications, so I use that 3 pins in temporary mode from that others applications until GUI will be started, and after remap that 3 Pins again to others applications.
I not understand how to that in code, because the
I understand very well about the after_open(self). I did some tests with I examined demo
I don't know if I'm asking too much, but honestly I need your help for an example to start. So, could you please, create a very simple example with two or 3 Screens implementing that idea to me as a start point? And maybe this example can be a Thank you so much! At least I'm glad today that I have ported successfully that two multi_fields.py: # simple.py Minimal micro-gui demo.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch
# hardware_setup must be imported before other modules because of RAM use.
import hardware_setup # Create a display instance
from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton, Meter
from gui.core.writer import Writer
import uasyncio as asyncio
# Font for CWriter
import gui.fonts.arial10 as arial10
import gui.fonts.font6 as small
from gui.core.colors import *
def xorshift64star(modulo, seed = 0xf9ac6ba4):
x = seed
def func():
nonlocal x
x ^= x >> 12
x ^= ((x << 25) & 0xffffffffffffffff) # modulo 2**64
x ^= x >> 27
return (x * 0x2545F4914F6CDD1D) % modulo
return func
async def change_multi_fields(nfields):
random = xorshift64star(2**24 - 1)
while True:
for field in nfields:
value = random() / 16777
field.value('{:5.2f}'.format(value))
await asyncio.sleep_ms(500)
class BaseScreen(Screen):
def __init__(self):
super().__init__()
Writer.set_textpos(ssd, 0, 0) # In case previous tests have altered it
wri = Writer(ssd, small, verbose=False)
wri.set_clip(False, False, False)
nfields = []
dy = small.height() + 6
y = 2
col = 15
width = wri.stringlen('999.99')
for txt in ('1:', '2:', '3:'):
Label(wri, y, 0, txt)
nfields.append(Label(wri, y, col, width, bdcolor=None)) # Draw border
y += dy
dy = small.height() + 6
y = 2
col = 82
for txt in ('4:', '5:', '6:'):
Label(wri, y, 67, txt)
nfields.append(Label(wri, y, col, width, bdcolor=None)) # Draw border
y += dy
self.reg_task(change_multi_fields(nfields))
CloseButton(wri)
def after_open(self):
print('----------------------------- 1')
ssd.hline(60, 60, 30, BLUE)
ssd.vline(67, 0, 28, BLUE)
print('----------------------------- 2')
def test():
Screen.change(BaseScreen) # A class is passed here, not an instance.
test() meter1.py # simple.py Minimal micro-gui demo.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch
# hardware_setup must be imported before other modules because of RAM use.
import hardware_setup # Create a display instance
from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton, Meter
from gui.core.writer import Writer
import uasyncio as asyncio
# Font for CWriter
import gui.fonts.arial10 as arial10
from gui.core.colors import *
async def change_meter(m0, m1, m2):
steps = 10
c = 1
for n in range(steps + 1):
m0.value(c/steps)
m1.value(n/steps)
m2.value(1 - n/steps)
await asyncio.sleep(1)
c += 1
class BaseScreen(Screen):
def __init__(self):
super().__init__()
wri = Writer(ssd, arial10, verbose=False)
m0 = Meter(wri, 5, 2, height = 45, divisions = 4, legends=('0.0', '50', '100', '245!', '250!'), label='4', style=Meter.BAR)
m1 = Meter(wri, 5, 44, height = 45, divisions = 4, legends=('0.0', '50', '200', '295!', '300!'), label='5', style=Meter.BAR)
m2 = Meter(wri, 5, 86, height = 45, divisions = 4, legends=('0.0', '50', '200', '335!', '340!'), label='6', style=Meter.BAR)
self.reg_task(change_meter(m0, m1, m2))
CloseButton(wri)
def after_open(self):
print('----------------------------- 1')
ssd.hline(60, 60, 30, BLUE)
ssd.vline(67, 0, 28, BLUE)
print('----------------------------- 2')
def test():
Screen.change(BaseScreen) # A class is passed here, not an instance.
test() |
Hi @peterhinch Sorry for one more time request, but I would like to know if will be possible to you to create a very simple example with two or 3 Screens implementing that your idea as a start point to me? A good and perfect example with three screens could be that my two screens above and the third scree the simple.py example, because the simple.py is a perfect screen to execute a command (it has button yes and no) to enable/disable some feature. However as the simple.py has real (not more virtual) buttons (yes and no) maybe need to do a additional remap of pins in the after_open(), and this is another thing that I have no idea how to implement, and that's why it's so important an example with those three screens as start point :) Don't worry if you can't to do that, is just to me know what way I will follow. Unfortunately I was no capable to implement your idea using micro-gui, and if you can't to create an example, I will back to nano-gui and and continue with re-invente the inputs Prev, Select and Next. Thank you in advance! |
I'm sorry but I am far too busy on another project to write and test a demo for you. I am convinced that micro-gui is the best, and simplest, approach. Looking at In the case where screens change, the |
Me too. And I did read this messages bellow dozens of times and still have questions.
The two
Now you talk about again of the same And you talk about "associated with the
Here I'm confused too because I do not know what lines in the simple.py are Could you please clarify that? Other question: for that solution need I to change some code in some file inside core/ or widgets/ directories, or all the changes needed is just on the simple.py for example?
I agree, but if you could at least write directly here in the GitHub a piece of code as a draft (without any test) I can get better the idea and I will to do the tests and complete what will need. Thank you so much! |
In your final application you won't have any |
I had progress.. 🥳 I have one Question below. In the
Got it!
Got it!
Done on from gui.primitives import Pushbutton
from machine import Pin
class BaseScreen(Screen):
def __init__(self):
def my_callback(button, arg):
print('Button pressed', button, arg)
super().__init__()
# verbose default indicates if fast rendering is enabled
wri = Writer(ssd, arial10)
col = 2
row = 2
Label(wri, row, col, 'Simple Demo')
row = 50
Button(wri, row, col, text='Yes', callback=my_callback, args=('Yes',))
col += 60
Button(wri, row, col, text='No', callback=my_callback, args=('No',))
# 3 Pushbuttons implemented (prev, sel, next)
prev = Pin(41, Pin.IN, Pin.PULL_UP)
self.btn_prev = Pushbutton(prev)
sel = Pin(12, Pin.IN, Pin.PULL_UP)
self.btn_sel = Pushbutton(sel)
nxt = Pin(42, Pin.IN, Pin.PULL_UP)
self.btn_nxt = Pushbutton(nxt)
# test to implement callback on the pushbutton
#self.btn_nxt = Pushbutton(b_next, callback=my_callback, args=('Test',))
This is in progress yet... I'm stuying!
Question: here I got the idea too, but the Any additional comments about the code above (including that line commented about callback on the pushbutton) is wellcome! Thank you! |
See the Pushbutton docs. You use the |
Hey @peterhinch It works like you told me! 🥳 🎈 Thank you for your support and especially for your patience! I still testing and finding the best way to call each Screen in the A question about this error: Thank you very much! |
I think importing on demand will work. If you want a modular design this is fine, but this way of working won't save resources. The GUI only instantiates the Re the error, I hadn't thought of this. I think suppressing the error will only move the problem elsewhere - the GUI is built on the assumption that there is at least one active control on a screen. So the best solution is probably to make the close button invisible. Adding the following line to class CloseButton(Button):
def __init__(self, writer, width=0, callback=dolittle, args=(), bgcolor=RED):
scr = Screen.current_screen
# Calculate the button width if not provided. Button allows
# 5 pixels either side.
wd = width if width else (writer.stringlen('X') + 10)
self.user_cb = callback
self.user_args = args
super().__init__(writer, *scr.locn(4, scr.width - wd - 4),
width = wd, height = wd, bgcolor = bgcolor,
callback = self.cb, text = 'X')
self.visible = False # Add this line |
Hi @peterhinch works with Mostly Screens that I will have is just to user see the data, like as that Screens I posted above (meter, multifields), but some Screen I want a Screen exactely as the Thank you in advance! |
That sounds OK. |
Hello @peterhinch What's the correct way to integrate my micro-gui app with other async tasks/servers? That integrate below works, but I note that after I integrate that very simple example (the simple.py) all my system got very slow. Ps: I changed on the Any idea why integrate the example main.py: async def main():
await start._setup()
# Start ModBus Slave TCP
slave_tcp_task = _start_slave_tcp('192.168.43.143', 502, 2)
asyncio.run(slave_tcp_task)
# Start micro-gui simple.py
print('starting display... ---------------------')
from main_simple import test
t1 = asyncio.create_task(test())
print('Display started! ---------------------')
# Start Microdot
await app.start_server(host='0.0.0.0', port=80, debug=False)
try:
asyncio.run(main())
except KeyboardInterrupt:
print('Stopped') main_simple.py: import hardware_setup # Create a display instance
from gui.core.ugui import Screen
from simple import BaseScreen
async def test():
print('Simple demo: button presses print to REPL.')
Screen.change(BaseScreen) # A class is passed here, not an instance.
#test() simple.py: # simple.py Minimal micro-gui demo.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch
# hardware_setup must be imported before other modules because of RAM use.
import hardware_setup # Create a display instance
from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
# Font for Writer
import gui.fonts.arial10 as arial10
from gui.core.colors import *
class BaseScreen(Screen):
def __init__(self):
def my_callback(button, arg):
print('Button pressed', arg)
super().__init__()
# verbose default indicates if fast rendering is enabled
wri = Writer(ssd, arial10)
col = 2
row = 2
Label(wri, row, col, 'Simple Demo')
row = 50
Button(wri, row, col, text='Yes', callback=my_callback, args=('Yes',))
col += 60
Button(wri, row, col, text='No', callback=my_callback, args=('No',))
CloseButton(wri) # Quit the application
#def test():
# print('Simple demo: button presses print to REPL.')
# Screen.change(BaseScreen) # A class is passed here, not an instance.
#
#test() EDIT: my ESP32-S3 is clocked at full speed: 240 MHz |
Applications therefore shouldn't use |
Hello @peterhinch
Yes, I see that in the docs. But please, think in a very simple scenario, if I use Microdot (or/and other servers) I need to start the Let me see if I understood what you are saying: software that need to run the
Yes, I already following that example (for the But I can't see how I can to start all
Thank you very much EDIT: About the |
@peterhinch There is a situation with If I comment line CloseButton(wri)
def next_screen(self, arg):
print('Pushbutton pressed', arg)
Screen.change(ScreenTempMeter01)
def after_open(self):
nxt = Pin(42, Pin.IN, Pin.PULL_UP)
self.btn_nxt = Pushbutton(nxt)
self.btn_nxt.press_func(self.next_screen, ('next screen',)) |
@peterhinch one more question: how is possible to pass I'm using the simple.py as reference. I added a
And where the Screen is called I changed from simple.py changed: # simple.py Minimal micro-gui demo.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch
# hardware_setup must be imported before other modules because of RAM use.
import hardware_setup # Create a display instance
from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
# Font for Writer
import gui.fonts.arial10 as arial10
from gui.core.colors import *
class BaseScreen(Screen):
def __init__(self, msg=None):
print(msg)
def my_callback(button, arg):
print('Button pressed', arg)
super().__init__()
# verbose default indicates if fast rendering is enabled
wri = Writer(ssd, arial10)
col = 2
row = 2
Label(wri, row, col, 'Simple Demo')
row = 50
Button(wri, row, col, text='Yes', callback=my_callback, args=('Yes',))
col += 60
Button(wri, row, col, text='No', callback=my_callback, args=('No',))
CloseButton(wri) # Quit the application
def test():
print('Simple demo: button presses print to REPL.')
Screen.change(BaseScreen(msg='test1')) # A class is passed here, not an instance.
test() Thank you again :) |
@peterhinch The args works - thanks :) The proof of concept about your I did a very very simple code - it has Could you please to check my code if there is something wrong? I did a very simple code because if you want to test, you need just to call the Problems:
Question: I'm changing to new screen_main.py: import hardware_setup # Create a display instance
from gui.core.ugui import Screen
from gui.primitives import Pushbutton
from machine import Pin
from screen_1 import BaseScreen_1
from screen_2 import BaseScreen_2
from screen_3 import BaseScreen_3
from screen_4 import BaseScreen_4
screens = {}
screens['BaseScreen_1'] = BaseScreen_1
screens['BaseScreen_2'] = BaseScreen_2
screens['BaseScreen_3'] = BaseScreen_3
screens['BaseScreen_4'] = BaseScreen_4
prev_pin = Pin(41, Pin.IN, Pin.PULL_UP)
sel_pin = Pin(12, Pin.IN, Pin.PULL_UP)
next_pin = Pin(42, Pin.IN, Pin.PULL_UP)
prev_btn = Pushbutton(prev_pin)
sel_btn = Pushbutton(sel_pin)
next_btn = Pushbutton(next_pin)
buttons = {}
buttons['prev'] = prev_btn
buttons['sel'] = sel_btn
buttons['next'] = next_btn
def main_screen():
params = {'screens': screens, 'buttons': buttons}
kwargs = {'params': params}
Screen.change(screens['BaseScreen_1'], kwargs=kwargs)
main_screen() screen_1.py: from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
import gui.fonts.arial10 as arial10
class BaseScreen_1(Screen):
def __init__(self, params):
self.kwargs = {'params': params}
self.params = params
self.screens = params['screens']
self.prev_btn = params['buttons']['prev']
self.sel_btn = params['buttons']['sel']
self.next_btn = params['buttons']['next']
super().__init__()
wri = Writer(ssd, arial10, verbose=False)
col = 2
row = 2
screen_name = 'Screen-1'
print(f'I am screen: {screen_name}')
Label(wri, row, col, screen_name)
CloseButton(wri)
def prev_screen(self, arg):
screen = self.screens['BaseScreen_3']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def sel_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print(f'This Screen has no function to the: {arg}')
def next_screen(self, arg):
screen = self.screens['BaseScreen_2']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def after_open(self):
self.prev_btn.press_func(self.prev_screen, ('prev screen',))
self.sel_btn.press_func(self.sel_screen, ('sel screen',))
self.next_btn.press_func(self.next_screen, ('next screen',)) screen_2.py: from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
import gui.fonts.arial10 as arial10
class BaseScreen_2(Screen):
def __init__(self, params):
self.kwargs = {'params': params}
self.params = params
self.screens = params['screens']
self.prev_btn = params['buttons']['prev']
self.sel_btn = params['buttons']['sel']
self.next_btn = params['buttons']['next']
super().__init__()
wri = Writer(ssd, arial10, verbose=False)
col = 2
row = 2
screen_name = 'Screen-2'
print(f'I am screen: {screen_name}')
Label(wri, row, col, screen_name)
CloseButton(wri)
def prev_screen(self, arg):
screen = self.screens['BaseScreen_1']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def sel_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print(f'This Screen has no function to the: {arg}')
def next_screen(self, arg):
screen = self.screens['BaseScreen_3']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def after_open(self):
self.prev_btn.press_func(self.prev_screen, ('prev screen',))
self.sel_btn.press_func(self.sel_screen, ('sel screen',))
self.next_btn.press_func(self.next_screen, ('next screen',)) screen_3.py: from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
import gui.fonts.arial10 as arial10
class BaseScreen_3(Screen):
def __init__(self, params):
self.kwargs = {'params': params}
self.params = params
self.screens = params['screens']
self.prev_btn = params['buttons']['prev']
self.sel_btn = params['buttons']['sel']
self.next_btn = params['buttons']['next']
super().__init__()
wri = Writer(ssd, arial10, verbose=False)
col = 2
row = 2
screen_name = 'Screen-3'
print(f'I am screen: {screen_name}')
Label(wri, row, col, screen_name)
col = 2
row = 20
Label(wri, row, col, 'Press *SEL* to open')
col = 2
row = 40
Label(wri, row, col, 'the Screen-4')
CloseButton(wri)
def prev_screen(self, arg):
screen = self.screens['BaseScreen_2']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def sel_screen(self, arg):
screen = self.screens['BaseScreen_4']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def next_screen(self, arg):
screen = self.screens['BaseScreen_1']
print(f'Pushbutton pressed: {arg}. Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
def after_open(self):
self.prev_btn.press_func(self.prev_screen, ('prev screen',))
self.sel_btn.press_func(self.sel_screen, ('sel screen',))
self.next_btn.press_func(self.next_screen, ('next screen',)) screen_4.py: from gui.core.ugui import Screen, ssd
from gui.widgets import Label, Button, CloseButton
from gui.core.writer import Writer
import gui.fonts.arial10 as arial10
class BaseScreen_4(Screen):
def __init__(self, params):
self.kwargs = {'params': params}
self.params = params
self.screens = params['screens']
self.prev_btn = params['buttons']['prev']
self.sel_btn = params['buttons']['sel']
self.next_btn = params['buttons']['next']
def my_callback(button, arg):
print('Button pressed', arg)
if arg == 'Yes':
screen = self.screens['BaseScreen_1']
print(f'Your choose was *{arg}*, so Changing to the screen: {screen}')
Screen.change(screen, kwargs=self.kwargs)
super().__init__()
wri = Writer(ssd, arial10, verbose=False)
col = 2
row = 2
screen_name = 'Screen-4'
print(f'I am screen: {screen_name}')
Label(wri, row, col, screen_name)
col = 2
row = 14
Label(wri, row, col, 'Press Yes')
col = 2
row = 28
Label(wri, row, col, 'to go to Screen-1')
row = 40
Button(wri, row, col, text='Yes', callback=my_callback, args=('Yes',))
col += 50
Button(wri, row, col, text='No', callback=my_callback, args=('No',))
CloseButton(wri) # Quit the application
def prev_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print(f'This Screen has no function to the: {arg}')
def sel_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print(f'This Screen has no function to the: {arg}')
def next_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print(f'This Screen has no function to the: {arg}')
def after_open(self):
self.prev_btn.press_func(self.prev_screen, ('prev screen',))
self.sel_btn.press_func(self.sel_screen, ('sel screen',))
self.next_btn.press_func(self.next_screen, ('next screen',)) hardware_setup.py from machine import Pin, SPI
import machine
import gc
import time
from ssd1306 import SSD1306_I2C as SSD
WIDTH = const(128)
HEIGHT = const(64)
i2c = machine.SoftI2C(scl=machine.Pin(18), sda=machine.Pin(17))
gc.collect() # Precaution before instantiating framebuf
ssd = SSD(WIDTH, HEIGHT, i2c)
from gui.core.ugui import Display
# Define control buttons
nxt = Pin(42, Pin.IN, Pin.PULL_UP) # Move to next control
#nxt = Pin(10, Pin.IN, Pin.PULL_UP) # Move to next control
sel = Pin(12, Pin.IN, Pin.PULL_UP) # Operate current control
#sel = Pin(11, Pin.IN, Pin.PULL_UP) # Operate current control
prev = Pin(41, Pin.IN, Pin.PULL_UP) # Move to previous control
#prev = Pin(14, Pin.IN, Pin.PULL_UP) # Move to previous control
display = Display(ssd, nxt, sel, prev) # 3-button mode Output: this is the same output that show in the video (attached): $ mpremote run screen_main.py
Using 3 switches.
I am screen: Screen-1
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_2'>
I am screen: Screen-2
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_3'>
I am screen: Screen-3
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_1'>
I am screen: Screen-1
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_2'>
I am screen: Screen-2
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_3'>
I am screen: Screen-3
Pushbutton pressed: sel screen. Changing to the screen: <class 'BaseScreen_4'>
I am screen: Screen-4
Button pressed Yes
Your choose was *Yes*, so Changing to the screen: <class 'BaseScreen_1'>
I am screen: Screen-1
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_2'>
I am screen: Screen-2
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_3'>
I am screen: Screen-3
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_1'>
I am screen: Screen-1
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_2'>
I am screen: Screen-2
Pushbutton pressed: next screen. Changing to the screen: <class 'BaseScreen_3'>
I am screen: Screen-3
Pushbutton pressed: sel screen. Changing to the screen: <class 'BaseScreen_4'>
I am screen: Screen-4
Button pressed Yes
Your choose was *Yes*, so Changing to the screen: <class 'BaseScreen_1'>
I am screen: Screen-1 micro-gui_test.mp4 |
GitHub complains that the video file is corrupt. I am very busy at the moment - I'm not sure when I'll find time to debug all that code. |
Good morning @peterhinch :)
That's strange, because I watched it directly from github after I posted the thread - I'm using Chromium. Anyway here is a new url for it (shared in the google drive)
All right, take your time! I did a simpler code as possible as prof of concept about the idea, and to not use much your time! Thank you so much for all your help! EDIT: is possible, maybe, for now, at least just to answer that Question Item? That will clarify much things about the design in this Proof of Concept about the idea! |
The design assumes that screens are stacked. If screen A opens screen B, which opens screen C, the stack is ABC. If screen C is closed, screen B is visible and the stack is AB. When screen B is closed, only screen A exists. Visually each screen overlays the previous one, in the expectation that the top one will be closed revealing the one below. This is fundamental to the design. If screen C opens another instance of A - carousel mode - you would end up with ABCA which would pave the way to ABCAB - ABCABC and so on. There would indeed be an ever growing number of instances. Supporting that would require a substantial redesign, a task that I don't intend to undertake. Perhaps there is a way where, when in screen C, on closure the underlying screen B also closes. This is way beyond anything I've tried, or anything any other user has requested. I'm happy to answer queries on design, such as this one. I'm less happy when the answer is in the docs, which I've had cause to point out several times. My least favourite is being presented with pages of code and an invitation to fix it. This would involve setting up hardware and a substantial commitment of time. Time that I don't have. |
Hi @peterhinch
To solve this problem I used this strategy: I have a
I totally agree. Apologize for that. Is my responsibility read the docs, also write the code and test it. Please, ignore my invite to check my code. I will contact you just if the docs do not exists or docs is not well understand by me, or a bug, otherwise you are correct, I need to do my home work. You already help so much about design asking, strategy, suggestion, examples, docs, new features, bug fix, etc! Well, I have just one problem yet. When I use It stop in the def launch(func, tup_args):
print('----------- 1')
print(func.__name__)
print(*tup_args)
res = func(*tup_args)
print('----------- 2')
if isinstance(res, type_coro):
res = asyncio.create_task(res)
return res Test with $ mpremote run screen_main.py
----------- 1
ctrl_move
1 Ps: Look that it stop/congeal in the Test with $ mpremote run screen_main.py
----------- 1
ctrl_move
1
----------- 2
----------- 1
next_screen
next screen
----------- 2 Ps: this works ok Thank you in advance! |
Perhaps setting To create an invisible control you might like to try the |
Hello @peterhinch I did set all colors possible as I tried this three ways: but all cases still have a little The docs say that setting So to get out that if self.args:
if self.args[0] == 'invisible':
color = BLACK def draw_border(self):
if self.screen is Screen.current_screen:
dev = display.usegrey(self._greyed_out)
x = self.col - 2
y = self.row - 2
w = self.width + 4
h = self.height + 4
# print('border', self, display.ipdev.is_adjust())
if self.has_focus() and not isinstance(self, DummyWidget):
color = color_map[FOCUS]
if self.args:
if self.args[0] == 'invisible':
color = BLACK $ diff ugui.py ugui.py.ORIG
242c242
< do_gc = False # Allow user to take control of GC
---
> do_gc = True # Allow user to take control of GC
693,695d692
< if self.args:
< if self.args[0] == 'invisible':
< color = BLACK With this change in the I believe, maybe, that should be possible to set from the widgets the correct color (like as BLACK) to that line Thank you! |
The white border indicates that a control has the focus. On a screen with multiple active controls, the white border moves when you press NEXT and PREV pushbuttons. This white border is not the same as the border created by Only |
Hi @peterhinch
I saw that in the colors docs too, and I already tried that, and works, but problem that I have some Screens that has active buttons, exactly as the I have a bigger problem with this design that is when I have a I did a horrible and very ugly thing to try to fix this problem. def my_callback(button, arg):
print('Button pressed', arg)
end_time = time.ticks_ms()
delta_time = time.ticks_diff(end_time, self.start_time)
if delta_time > 1000: # 1 second by guarantee?
if arg == 'Yes':
self.env.change_to_screen = 'ScreenTempValues'
Screen.shutdown()
elif arg == 'No':
self.env.change_to_screen = 'ScreenResetAlPtSel'
Screen.shutdown()
def prev_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print('Do nothing')
def sel_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print('Do nothing')
def next_screen(self, arg):
print(f'Pushbutton pressed: {arg}')
print('Do nothing')
def after_open(self):
self.prev_btn.press_func(self.prev_screen, ('prev screen',))
self.sel_btn.press_func(self.sel_screen, ('sel screen',))
self.next_btn.press_func(self.next_screen, ('next screen',))
self.start_time = time.ticks_ms() Do you have a better way to solve that? Thank you so much! |
@peterhinch I'm sorry, I just realized now that I can to change the All are working perfect, except that problem when I change do Screen Thank you so much Edit: I'm almost sure that |
That was what I had in mind. Sorry if I didn't make this clear. Re To fit this paradigm you want the action which closes an overlaying screen to take place on |
Hi @peterhinch
I understood perfectly well, thanks for that explanation.
Now I changed to do exactly that: now the |
Hello @peterhinch I did a test to check if the pin still pressed just before to change to the Previous Screen of def release_sel_screen(self, arg):
print(f'Pushbutton released: {arg}')
self.env.change_to_screen = 'simple_screen'
print(sel_pin.value())
Screen.shutdown()
def after_open(self):
self.sel_btn.release_func(self.release_sel_screen, ('sel screen - release',)) After that |
Hello Peter I did read many docs and many tests but unfortunately I yet do not found how to solve that problem that still pressing automatically the The only ugly work around that I found to try to solve that is checking if class BaseScreen(Screen):
def __init__(self):
self.start_time = None
def my_callback(button, arg):
end_time = time.ticks_ms()
delta_time = time.ticks_diff(end_time, self.start_time)
if delta_time > 1200:
if arg == 'yes':
self.env.change_to_screen = 'ScreenTempValues'
elif arg == 'no':
self.env.change_to_screen = 'ScreenResetAlPtSel'
Screen.shutdown()
else:
print('Button pressed automatically')
def after_open(self):
self.start_time = time.ticks_ms()
Can that be a Bug? Please, if you have any idea how to solve that, or any suggestion, I will appreciate! Thank you |
Hello @peterhinch
I'm using
micro-gui
with thessd1306
mono display (128 x 64
) with three buttons, but themicro-gui
is showing in all demos a strange symbol (like as a trash) on the top right side. Why that symbol and how to remove?Here a screenshot showing that trash symbol inside the green circle using
demo/simple.py
:As I'm using a mono display I just changed the
simple.py
:CWriter
toWriter
wri = CWriter(ssd, arial10, GREEN, BLACK)
towri = Writer(ssd, arial10)
gui/demos/simple.py:
Output:
My hardware_setup.py:
The
ssd1306.py
is from official micropython driver.Thank you!
The text was updated successfully, but these errors were encountered: