how to send console output to Kivy display object? kivy+Raspberry Pi hides console output

1,493 views
Skip to first unread message

Griffo

unread,
Dec 28, 2017, 2:06:49 PM12/28/17
to Kivy users support
As the title suggests, I'm trying to access basically the stdout (e.g. outputs from print statements etc.) within the App because the App auto-fullscreen on a Raspberry Pi hides the console output in the background. I looked into kivy.Logging but this all just sends to file etc. just like python logging. I want to direct it to the app screen itself in a TextInput that is scrollable say (sort of like CodeInput but receives stdout).

Note: I thought I could just make the app half screen in size. I have tried this but I discovered you can't actually get enough power to the raspberrypi to power the sdl2/openGL enabled graphics, a touch screen and the pi itself which means a "half-screen" app possible (with console outputting on the bottom half say). I've also tried a thread option found on SO but it just updates the Label one line at a time whereas I want the stdout as though it appears in the terminal.

Overall I'd like to show all my diagnostic information but still maintain access to the buttons etc. and core functionality of my app.

Thanks in advance.

Griffo

unread,
Dec 28, 2017, 2:37:46 PM12/28/17
to Kivy users support
As an update, I found a sort of ugly work around just using TextInput(multiline=True) whereby each time I want to add a new piece of information I just add:

self.log_label.text += "Update 1\n"


To ensure it actually displays stuff whilst running I added self.stdout_label.text to a new thread inside the __init__ of my App.

def my_thread(self):
   
return

_thread
.start_new(my_thread, (self. log_label,))

Connecting this to a button action:

def go_button_fired(self):
   
self.log_label.text += "Update 1\n"
   
self.log_label.text += "Update 2\n"
   
self.log_label.text += "Update 3\n"
   
self.log_label.text += "Update 4\n"
   
self.log_label.text += "Update 5\n"
   
self.log_label.text += "Update 6\n"

Now when I push the "Go!" button I get the following:


This is ugly but it will work for now. Hopefully there won't be any memory issues downstream when adding a lot of text and I have the threading working because I don't want the GUI to hang whilst something is running.

Still seeking better options.

Thanks.

Beat Ludin

unread,
Jan 26, 2023, 5:03:38 PM1/26/23
to Kivy users support
Hi - I'm trying to do exactly the same (ideally split the raspi screen into a Kivy and a console section). Have you made any progress in the meantime?  Thx, Beat

Elliot Garbus

unread,
Jan 27, 2023, 7:23:07 PM1/27/23
to kivy-...@googlegroups.com

If you want to create an output screen that behaves like a console you could do something like this example.  Let me know what you think.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.recycleview import RecycleView

kv =
"""
<ScrollLabel>:
    size_hint: 1, None
    text_size: self.width, None  # height must be calculated based on texture_size
    font_size: 30

<ConsoleRV>:
    viewclass: 'ScrollLabel'
    RecycleBoxLayout:
        id: scroll_box
        orientation: 'vertical'
        key_size: 'ks'
        default_size_hint: 1, None
        size_hint: 1, None
        height: self.minimum_height
        on_width: root.update_text() # when width changes, update sizes in rv data list


BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Test long Scroll'
        size_hint_y: None
        height: 30
    ConsoleRV:
        id: console_rv
"""

class ScrollLabel(Label):
   
pass

class
ConsoleRV(RecycleView):
   
def add_text(self, text):
        st = [x +
'\n' for x in text.split('\n')]  # assuming there are some \n in the text, split into separate labels
       
sl = ScrollLabel() # create a label to use for calculating texture size
       
for t in st:
            sl.text = t
            sl.width =
self.width
            sl.texture_update()
           
self.data.append({'text': t, 'ks': sl.texture_size})

   
def update_text(self):
        sl = ScrollLabel()
       
for i, entry in enumerate(self.data):
            sl.text = entry[
'text']
            sl.width =
self.width
            sl.texture_update()
           
self.data[i]['ks'] = sl.texture_size
           
self.refresh_from_data()


sample_text = \
"""In general, the worst-case time complexity of QuickSort is O(n^2), which occurs when the array is already sorted or almost sorted in the reverse order. The best-case time complexity is O(n log n), which occurs when the pivot element is always chosen as the middle element or when the array is already sorted. The average-case time complexity of QuickSort is O(n log n), which makes it a good sorting algorithm for most practical purposes.
However, the actual compute efficiency of QuickSort can be affected by a variety of factors, including the choice of pivot element, the size of the input array, and the presence of duplicate elements. For example, if the pivot element is always chosen as the first or last element in the array, the time complexity can degrade to O(n^2) in the worst case. Similarly, if the input array contains a large number of duplicate elements, the time complexity can also degrade to O(n^2) in the worst case.
In general, QuickSort is a fast and efficient sorting algorithm that is well-suited for many practical applications. Its average-case time complexity of O(n log n) makes it a good choice for sorting large arrays, and it can be implemented in a variety of programming languages.
The time complexity of a bubble sort algorithm is typically O(n^2), which means that the algorithm's performance is proportional to the square of the size of the input array. This is because a bubble sort algorithm compares adjacent elements and swaps them if they are out of order, which means that it has to perform a number of comparisons and swaps that is proportional to the size of the input array.
For example, if the input array contains n elements, the bubble sort algorithm will need to perform n-1 comparisons on the first pass, n-2 comparisons on the second pass, and so on, until it reaches the final pass, which will only require one comparison. This gives us a total of (n-1) + (n-2) + ... + 2 + 1 = (n^2 - n)/2 comparisons, which is O(n^2).
In addition to the time complexity, the compute efficiency of a bubble sort algorithm can also be affected by factors such as the choice of data structures and the presence of optimized code. However, in general, bubble sort is not considered to be a very efficient sorting algorithm, especially for large input arrays. There are many other sorting algorithms that have a better time complexity and are more efficient in practice, such as QuickSort and MergeSort.
There are many different sorting algorithms that have been developed over the years, and the most efficient algorithm for a given situation can depend on a variety of factors. Some of the factors that can affect the efficiency of a sorting algorithm include the size of the input array, the type of data being sorted, the presence of certain patterns or distributions in the data, and the hardware and software environment in which the algorithm is being implemented.
In general, the most efficient sorting algorithms have a time complexity of O(n log n), which means that their performance is proportional to the size of the input array multiplied by the logarithm of the array size. Some examples of sorting algorithms that have a time complexity of O(n log n) include Quicksort, MergeSort, and HeapSort. These algorithms are generally considered to be the most efficient for sorting large arrays.
However, there are also other sorting algorithms that can be more efficient in certain situations. For example, if the input array is already partially sorted or has a limited number of possible values, certain algorithms, such as Insertion Sort and Selection Sort, can be more efficient. In addition, some algorithms, such as Radix Sort and Counting Sort, can be more efficient for sorting data with a limited range of values.
In general, it is important to consider the specific requirements and constraints of a sorting problem when selecting an algorithm, as the most efficient algorithm can vary depending on the situation.
"""

class LongScrollApp(App):

   
def build(self):
       
return Builder.load_string(kv)

   
def on_start(self):
       
self.root.ids.console_rv.add_text(sample_text * 10)


LongScrollApp().run()

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/a9370fe5-3017-492d-a998-d1cd2a0acafen%40googlegroups.com.

 

Beat Ludin

unread,
Jan 28, 2023, 2:46:24 AM1/28/23
to Kivy users support
Thanks a lot. That looks promising and may well be what I will resort to if there is no way to actually split the screen and use part of it for the native console. I will still have to figure out the best way to feed stdout into it.
Nice trick to include the kv in the code, btw, didn't know about that yet (I'm a kivy-noob, as you can tell).
Reply all
Reply to author
Forward
0 new messages