I'm trying to write a very basic Kivy program that will use 3 different layouts to split the screen into :
a header (at the top of the screen)
a text zone (in the middle of the screen)
a console (at the bottom of the screen)
So far I was thinking to use a main gridLayout, in which I use 3 different floatLayout.
Here's what the code looks like:
class Logo(App):
def build(self):
layout = GridLayout(rows=3)
layoutTop = FloatLayout(size=(100,300))
layoutMid = FloatLayout(size=(100,300))
layoutDown = FloatLayout(size=(100,300))
logo = Image(source='imagine.png',size_hint=(.25,.25),pos=(30,380))
blank = Label(text='', font_size = '25sp',pos=(-200,100))
titre = Label(text='#LeCubeMedia',font_size='40sp',pos=(0,280))
ip = Label(text='192.168.42.1',font_size='25sp',pos=(250,280))
layoutTop.add_widget(titre)
layoutTop.add_widget(logo)
layoutTop.add_widget(ip)
layoutMid.add_widget(blank)
layout.add_widget(layoutTop)
layout.add_widget(layoutMid)
return layout
if __name__ == '__main__':
Logo().run()
Actually my problem is regarding the creation of the console. I have read a lot of the Kivy docs, but I am still looking for a good way to do this type of widget.
How do you think it would be if I send something with a Python print into my Kivy app, and then refresh as soon as I need to send something else (to erase the previous print). This way it would be a console-like. But, so far I have not much ideas..
Any ideas ?
I have seen 2 types of consoles in Kivy. The first is a multiline textinput in a scrollview where you append the new text to the old in the textinput. The second is a BoxLayout or GridLayout in a Scrollview where each console output is a separate label in the layout.
This was a attempt trying stuff out with kivy, the code is old and you might need to adjust it a bit to make it run with latest kivy. Kivy-designer also includes this. This is using the simple way of using two textinputs, 1 for history and the other for input.
A better way to do a proper console would be to use pyte and draw characters directly onto the canvas of a widget. This way one would get VT emulation for free.
Related
I am working on developing an application using Kivy. I am using Kivy ActionBar for creating a menu bar for my application.
Kindly refer to the image attached
I want to remove the Kivy icon and move the other options(file / edit) to the left. Please find the snippet of my code.
menuAcBar = ActionBar(pos_hint={'top': 1.3})
menuAcView = ActionView()
menuAcBar.add_widget(menuAcView)
menuAcPrevious = ActionPrevious(with_previous=False)
menuAcView.add_widget(menuAcPrevious)
menuAcView.add_widget(ActionButton(text="File"))
menuAcView.add_widget(ActionButton(text="Edit"))
menuAcView.add_widget(ActionButton(text="Documents"))
menuAcView.add_widget(ActionButton(text="help"))
self.add_widget(menuAcBar)
Right on ActionPrevious you can set app_icon. It's a little bit lower in docs. You can set app_icon_width/height for size of the icon or even remove it with app_icon='', but it'll leave white rectangle instead of a "transparent". Leave app_icon be and set only width and height to make it invisible.
The Ä„ctionPrevious has ActionItem's minimum_width property, therefore you need to change it like this:
menuAcPrevious = ActionPrevious(with_previous=False,
app_icon=<your_image>,
app_icon_width=1,
app_icon_height=0,
minimum_width=10,
size_hint_x: None)
Edit:
It seems that ActionPrevious leaves additional unused space even if title='' and minimum_width=1 and you can't access the damn thing through children because it's unregistered, therefore the only thing I came up with is resizing it so you won't see it anymore:
ActionPrevious(
size_hint_x = None,
width = 0,
app_icon_width = 0.1,
with_previous = False)
I've been working with Kivy and Python 3 and I've run across a problem. I have 2 widgets in a BoxLayout, one a TextInput widget and one a Label widget. When some text is entered into the TextInput widget and the enter key is pressed, I would like Label.text to update to reflect TextInput.text.
I've put together a solution that works. Here is the code (question after the break):
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
class TexttestApp(App):
def on_enter(self,textin):
self.lab.text = textin.text #is this incorrect?
def build(self):
window = BoxLayout()
self.lab = Label(text="Inital Label") #is this incorrect?
text = TextInput(multiline=False)
text.bind(on_text_validate=self.on_enter)
window.add_widget(text)
window.add_widget(self.lab)
return window
My questions are as follows:
Is assigning the Label widget to an instance variable a bad programming practice? From a software engineering point of view, is this bad/confusing? Or should I be assigning all of my widgets to the instance of the TexttestApp class? (i.e. self.text, self.window, etc). The code right now looks disorganized to me, but I can't figure out another way of solving the problem.
Thanks in advance. This is my first attempt at using bind() to attach a function to a keyboard event.
This all looks fine to me. I suppose in principle I could nitpick stuff, but there's really nothing very important in such a small code snippet, since you aren't doing anything really wrong. The stuff you comment is fine, in general terms, and there's no rule against storing stuff as attributes of your app although there may be better or more convenient alternatives (as below).
From a kivy point of view, the biggest thing is probably...use kv language! In this case, you could have a file texttest.kv with
BoxLayout:
TextInput:
multiline: False
on_text_validate: the_label.text = self.text
Label:
id: the_label
text: "Initial Label"
This would replace both methods of your app class. It's quite similar to your example in length, since it's very simple, but I'd say its already a little clearer - and kv rapidly becomes much clearer and less verbose as things become more complicated, since it takes care of a lot of bindings automatically.
This example happens to also avoid binding to your own function to change the label text, since it can all be done in a line of kv, but your way isn't wrong and it might still be appropriate to call a method or function in the python file if the task is more complex.
Image: http://dl.dropbox.com/u/4900888/GUI.png
Source and UI is in comments, due to "New-user-limiations"
I'm sorry if I've totally misunderstood what this site is about, but I have a problem.
When the button in the lower left corner is pressed, I want to get the values from the three spinboxes and save the as variables for use in a function that is triggered by the button.
I'm really blank as to how you would do this.
Any help is appreciated, and additional information can be supplied if it needs to.
EDIT:
I am using Python, and Gtk+ through Glade.
PS:
Does Stack Overflow have any code sharing site prefferences such as pastebin and so on?
The short answer is: with the spin button's get_value_as_int() method.
I suspect, however, that your actual problem is getting a reference to the spin button to call get_value_as_int() on. From your code I see that you are using gtk.Builder to build your UI.
Accessing widgets
Keeping a reference to specific widgets in Handler instance:
handler = Handler()
builder = Gtk.Builder()
...
# Store references to widgets in `handler`
for widget_name in ('sbtn_days', 'sbtn_hours', 'sbtn_minutes'):
setattr(handler, widget_name, builder.get_object(widget_name))
# The above is equivalent to the following:
handler.sbtn_days = builder.get_object('sbtn_days')
...
# In signal handling code:
days = self.sbtn_days.get_value_as_int()
Or you can keep a reference in to builder in your Handler instance:
builder = Gtk.Builder()
handler = Handler()
handler.builder = builder
...
# In signal handler code:
sbtn_days = self.builder.get_object('sbtn_days')
days = sbtn_days.get_value_as_int()
Notes
In the code above,
I assumed that your spin button for days is named sbtn_days. Adjust as necessary.
I only demonstrated accessing sbtn_days and its value. The other buttons can be accessed in a similar way.
P.S. There are a bunch of other problems with your code keeping it from being "good".
To display a wxPython window in full screen mode you use:
ShowFullScreen(True)
How do you get out of full screen though? I've tried the obvious way:
ShowFullScreen(True)
sleep(5)
ShowFullScreen(False)
This doesn't work though. When I run the script, nothing appears. After 5 seconds a window roughly 200x250 appears in the top-left corner of the screen, without anything inside of it. It doesn't appear to have any borders either.
If I change this to
showFullScreen(True)
then I get stuck with a full screen window that I have to use Alt + F2 -> xkill to get out of.
It looks like you need to Show() the window first. (According to the documentation, you shouldn't have to. Maybe this is a bug.) I tested on Mac OS X and Windows - they both exhibit issues if you don't call Show() first.
Also note that you shouldn't sleep in the main GUI thread. You'll hang the UI. Using CallLater is one potential solution, as shown in my example.
Working example:
import wx
def main():
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'Full Screen Test')
frame.Show()
frame.ShowFullScreen(True)
wx.CallLater(5000, frame.ShowFullScreen, False)
app.MainLoop()
if __name__ == '__main__':
main()
The documentation for ShowFullScreen reads:
ShowFullScreen(show, style=wx.FULLSCREEN_ALL)
Depending on the value of show parameter the window is either shown full screen or restored to its normal state.
Parameters:
show (bool)
style (long): is a bit list containing some or all of the following values, which indicate what elements of the window to hide in full-screen mode:
wx.FULLSCREEN_NOMENUBAR
wx.FULLSCREEN_NOTOOLBAR
wx.FULLSCREEN_NOSTATUSBAR
wx.FULLSCREEN_NOBORDER
wx.FULLSCREEN_NOCAPTION
wx.FULLSCREEN_ALL (all of the above)
So put your Full Screen toggle event/s in a Menu and start full screen mode with:
self.window.ShowFullScreen(True, style=(wx.FULLSCREEN_NOTOOLBAR | wx.FULLSCREEN_NOSTATUSBAR |wx.FULLSCREEN_NOBORDER |wx.FULLSCREEN_NOCAPTION))
Note that I omitted wx.FULLSCREEN_NOMENUBAR, in this way you will still be able to access the menu to turn full screen mode off again.
I am re designing a portion of my current software project, and want to use hyperlinks instead of Buttons. I really didn't want to use a Text widget, but that is all I could find when I googled the subject. Anyway, I found an example of this, but keep getting this error:
TclError: bitmap "blue" not defined
When I add this line of code (using the IDLE)
hyperlink = tkHyperlinkManager.HyperlinkManager(text)
The code for the module is located here and the code for the script is located here
Anyone have any ideas?
The part that is giving problems says foreground="blue", which is known as a color in Tkinter, isn't it?
If you don't want to use a text widget, you don't need to. An alternative is to use a label and bind mouse clicks to it. Even though it's a label it still responds to events.
For example:
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
for text in ("link1", "link2", "link3"):
link = tk.Label(text=text, foreground="#0000ff")
link.bind("<1>", lambda event, text=text: self.click_link(event, text))
link.pack()
def click_link(self, event, text):
print("You clicked '%s'" % text)
root = tk.Tk()
app = App(root)
root.mainloop()
If you want, you can get fancy and add additional bindings for <Enter> and <Leave> events so you can alter the look when the user hovers. And, of course, you can change the font so that the text is underlined if you so choose.
Tk is a wonderful toolkit that gives you the building blocks to do just about whatever you want. You just need to look at the widgets not as a set of pre-made walls and doors but more like a pile of lumbar, bricks and mortar.
"blue" should indeed be acceptable (since you're on Windows, Tkinter should use its built-in color names table -- it might be a system misconfiguration on X11, but not on Windows); therefore, this is a puzzling problem (maybe a Tkinter misconfig...?). What happen if you use foreground="#00F" instead, for example? This doesn't explain the problem but might let you work around it, at least...